From 725c59cfc7572943e24c80dcdf79dc0446ec5e0a Mon Sep 17 00:00:00 2001 From: Sachin Saxena Date: Fri, 10 Jun 2016 16:31:30 +0530 Subject: NXP dpaa2 platform initial support - On ARMv8 aarch64 CPU - TARGET is aarch64-linux-gnu - Cross compilation enabled with "gcc-linaro-4.9" toolchain make PLATFORM=dpaa2 TAG=dpaa2 ... Change-Id: I8faf5c8b0d3c81d33a2834c6429a05c8379309c1 Signed-off-by: Sachin Saxena --- build-data/platforms/dpaa2.mk | 63 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 build-data/platforms/dpaa2.mk (limited to 'build-data/platforms/dpaa2.mk') diff --git a/build-data/platforms/dpaa2.mk b/build-data/platforms/dpaa2.mk new file mode 100644 index 00000000..feafd728 --- /dev/null +++ b/build-data/platforms/dpaa2.mk @@ -0,0 +1,63 @@ +# Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. +# 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. + +# Configuration for NXP DPAA2 ARM64 based platform +dpaa2_arch = aarch64 +dpaa2_os = linux-gnu +dpaa2_target = aarch64-linux-gnu +dpaa2_mtune = cortex-A57 +dpaa2_march = "armv8-a+fp+simd+crc+crypto" +dpaa2_cross_ldflags = \ + -Wl,--dynamic-linker=/lib/ld-linux-aarch64.so.1 + +dpaa2_native_tools = vppapigen +dpaa2_root_packages = vpp vlib vlib-api vnet svm vpp-api-test + +# DPDK configuration parameters +# +# We are using external DPDK module with NXP-DPAA2 platform support. +# Compile DPDK only if "DPDK_PATH" variable is defined where we have +# installed DPDK libraries and headers. +ifeq ($(PLATFORM),dpaa2) +ifneq ($(DPDK_PATH),) +dpaa2_uses_dpdk = yes +dpaa2_uses_external_dpdk = yes +dpaa2_dpdk_inc_dir = $(DPDK_PATH)/include/dpdk +dpaa2_dpdk_lib_dir = $(DPDK_PATH)/lib +else +$(error Please define path for installed DPDK headers and libs) +endif +endif + +vpp_configure_args_dpaa2 = --with-dpdk --without-ipsec --without-vcgn \ + --without-ipv6sr --with-sysroot=$(SYSROOT) +vnet_configure_args_dpaa2 = --with-dpdk --without-ipsec --without-vcgn \ + --without-ipv6sr --with-sysroot=$(SYSROOT) + +# Set these parameters carefully. The vlib_buffer_t is 128 bytes, i.e. +vlib_configure_args_dpaa2 = --with-pre-data=128 + + +dpaa2_debug_TAG_CFLAGS = -g -O2 -DCLIB_DEBUG -fPIC -fstack-protector-all \ + -march=$(MARCH) -Werror +dpaa2_debug_TAG_LDFLAGS = -g -O2 -DCLIB_DEBUG -fstack-protector-all \ + -march=$(MARCH) -Werror + +# Use -rdynamic is for stack tracing, O0 for debugging....default is O2 +# Use -DCLIB_LOG2_CACHE_LINE_BYTES to change cache line size +dpaa2_TAG_CFLAGS = -g -O2 -fPIC -march=$(MARCH) -mcpu=$(dpaa2_mtune) \ + -mtune=$(dpaa2_mtune) -funroll-all-loops -Werror +dpaa2_TAG_LDFLAGS = -g -O2 -fPIC -march=$(MARCH) -mcpu=$(dpaa2_mtune) \ + -mtune=$(dpaa2_mtune) -funroll-all-loops -Werror + + -- cgit 1.2.3-korg From bd05e17d79156fb72cb12a0d4855bfeaf44bfa32 Mon Sep 17 00:00:00 2001 From: Sachin Date: Fri, 17 Jun 2016 14:18:19 +0530 Subject: NXP DPAA2 Poll Mode Driver Support in DPDK Upstreaming of DPAA2 driver changes is in progress.This patch will temporary add the support in VPP in built DPDK. Two types of changes: 1. Driver specfic independent files. No impact on any other functionality. 2. Changes in common EAL framework. These changes are done in compile time DPAA2 specific flag, so no impact is expected on other existing features if not compiling for DPAA2. Change-Id: I02abe7189313835b51ff654b4d7e566bc0fb8327 Signed-off-by: Sachin --- build-data/platforms/dpaa2.mk | 10 +- .../0017-NXP-DPAA2-Poll-Mode-Driver-Support.patch | 40404 +++++++++++++++++++ 2 files changed, 40410 insertions(+), 4 deletions(-) create mode 100644 dpdk/dpdk-16.04_patches/0017-NXP-DPAA2-Poll-Mode-Driver-Support.patch (limited to 'build-data/platforms/dpaa2.mk') diff --git a/build-data/platforms/dpaa2.mk b/build-data/platforms/dpaa2.mk index feafd728..7833b876 100644 --- a/build-data/platforms/dpaa2.mk +++ b/build-data/platforms/dpaa2.mk @@ -24,9 +24,8 @@ dpaa2_native_tools = vppapigen dpaa2_root_packages = vpp vlib vlib-api vnet svm vpp-api-test # DPDK configuration parameters -# -# We are using external DPDK module with NXP-DPAA2 platform support. -# Compile DPDK only if "DPDK_PATH" variable is defined where we have +dpaa2_uses_dpdk = yes +# Compile with external DPDK only if "DPDK_PATH" variable is defined where we have # installed DPDK libraries and headers. ifeq ($(PLATFORM),dpaa2) ifneq ($(DPDK_PATH),) @@ -35,7 +34,10 @@ dpaa2_uses_external_dpdk = yes dpaa2_dpdk_inc_dir = $(DPDK_PATH)/include/dpdk dpaa2_dpdk_lib_dir = $(DPDK_PATH)/lib else -$(error Please define path for installed DPDK headers and libs) +# compile using internal DPDK + NXP DPAA2 Driver patch +dpaa2_dpdk_arch = "armv8a" +dpaa2_dpdk_target = "arm64-dpaa2-linuxapp-gcc" +dpaa2_dpdk_make_extra_args = "CROSS=$(dpaa2_target)-" endif endif diff --git a/dpdk/dpdk-16.04_patches/0017-NXP-DPAA2-Poll-Mode-Driver-Support.patch b/dpdk/dpdk-16.04_patches/0017-NXP-DPAA2-Poll-Mode-Driver-Support.patch new file mode 100644 index 00000000..2553997c --- /dev/null +++ b/dpdk/dpdk-16.04_patches/0017-NXP-DPAA2-Poll-Mode-Driver-Support.patch @@ -0,0 +1,40404 @@ +From b8d83a0825f2d7d0d626c00f79de7b415f8dc344 Mon Sep 17 00:00:00 2001 +From: Sachin Saxena +Date: Fri, 17 Jun 2016 12:32:28 +0530 +Subject: [PATCH 17/17] NXP DPAA2 Poll Mode Driver Support + + Upstreaming of DPAA2 driver changes is in progress.This patch will + temporary add the support in VPP in built DPDK. + + Two types of changes: + 1. Driver specfic independent files. No impact on any other functionality. + 2. Changes in common EAL framework. These changes are done in compile time DPAA2 + specific flag, so no impact is expected on other existing features if not + compiling for DPAA2. + +Signed-off-by: Sachin Saxena +--- + config/defconfig_arm64-dpaa2-linuxapp-gcc | 61 + + drivers/net/Makefile | 1 + + drivers/net/dpaa2/Makefile | 102 + + drivers/net/dpaa2/dpaa2_logs.h | 77 + + drivers/net/dpaa2/mc/dpaiop.c | 457 ++++ + drivers/net/dpaa2/mc/dpbp.c | 432 ++++ + drivers/net/dpaa2/mc/dpci.c | 501 ++++ + drivers/net/dpaa2/mc/dpcon.c | 401 +++ + drivers/net/dpaa2/mc/dpdbg.c | 547 +++++ + drivers/net/dpaa2/mc/dpdcei.c | 449 ++++ + drivers/net/dpaa2/mc/dpdmai.c | 452 ++++ + drivers/net/dpaa2/mc/dpdmux.c | 567 +++++ + drivers/net/dpaa2/mc/dpio.c | 468 ++++ + drivers/net/dpaa2/mc/dpmac.c | 422 ++++ + drivers/net/dpaa2/mc/dpmcp.c | 312 +++ + drivers/net/dpaa2/mc/dpmng.c | 58 + + drivers/net/dpaa2/mc/dpni.c | 1907 +++++++++++++++ + drivers/net/dpaa2/mc/dprc.c | 786 ++++++ + drivers/net/dpaa2/mc/dprtc.c | 509 ++++ + drivers/net/dpaa2/mc/dpseci.c | 502 ++++ + drivers/net/dpaa2/mc/dpsw.c | 1639 +++++++++++++ + drivers/net/dpaa2/mc/fsl_dpaiop.h | 494 ++++ + drivers/net/dpaa2/mc/fsl_dpaiop_cmd.h | 190 ++ + drivers/net/dpaa2/mc/fsl_dpbp.h | 438 ++++ + drivers/net/dpaa2/mc/fsl_dpbp_cmd.h | 172 ++ + drivers/net/dpaa2/mc/fsl_dpci.h | 594 +++++ + drivers/net/dpaa2/mc/fsl_dpci_cmd.h | 200 ++ + drivers/net/dpaa2/mc/fsl_dpcon.h | 407 +++ + drivers/net/dpaa2/mc/fsl_dpcon_cmd.h | 162 ++ + drivers/net/dpaa2/mc/fsl_dpdbg.h | 635 +++++ + drivers/net/dpaa2/mc/fsl_dpdbg_cmd.h | 249 ++ + drivers/net/dpaa2/mc/fsl_dpdcei.h | 515 ++++ + drivers/net/dpaa2/mc/fsl_dpdcei_cmd.h | 182 ++ + drivers/net/dpaa2/mc/fsl_dpdmai.h | 521 ++++ + drivers/net/dpaa2/mc/fsl_dpdmai_cmd.h | 191 ++ + drivers/net/dpaa2/mc/fsl_dpdmux.h | 724 ++++++ + drivers/net/dpaa2/mc/fsl_dpdmux_cmd.h | 256 ++ + drivers/net/dpaa2/mc/fsl_dpio.h | 460 ++++ + drivers/net/dpaa2/mc/fsl_dpio_cmd.h | 184 ++ + drivers/net/dpaa2/mc/fsl_dpkg.h | 174 ++ + drivers/net/dpaa2/mc/fsl_dpmac.h | 593 +++++ + drivers/net/dpaa2/mc/fsl_dpmac_cmd.h | 195 ++ + drivers/net/dpaa2/mc/fsl_dpmcp.h | 332 +++ + drivers/net/dpaa2/mc/fsl_dpmcp_cmd.h | 135 + + drivers/net/dpaa2/mc/fsl_dpmng.h | 74 + + drivers/net/dpaa2/mc/fsl_dpmng_cmd.h | 46 + + drivers/net/dpaa2/mc/fsl_dpni.h | 2581 ++++++++++++++++++++ + drivers/net/dpaa2/mc/fsl_dpni_cmd.h | 1058 ++++++++ + drivers/net/dpaa2/mc/fsl_dprc.h | 1032 ++++++++ + drivers/net/dpaa2/mc/fsl_dprc_cmd.h | 755 ++++++ + drivers/net/dpaa2/mc/fsl_dprtc.h | 434 ++++ + drivers/net/dpaa2/mc/fsl_dprtc_cmd.h | 181 ++ + drivers/net/dpaa2/mc/fsl_dpseci.h | 647 +++++ + drivers/net/dpaa2/mc/fsl_dpseci_cmd.h | 241 ++ + drivers/net/dpaa2/mc/fsl_dpsw.h | 2164 ++++++++++++++++ + drivers/net/dpaa2/mc/fsl_dpsw_cmd.h | 916 +++++++ + drivers/net/dpaa2/mc/fsl_mc_cmd.h | 221 ++ + drivers/net/dpaa2/mc/fsl_mc_sys.h | 95 + + drivers/net/dpaa2/mc/fsl_net.h | 480 ++++ + drivers/net/dpaa2/mc/mc_sys.c | 129 + + drivers/net/dpaa2/qbman/driver/qbman_debug.c | 926 +++++++ + drivers/net/dpaa2/qbman/driver/qbman_debug.h | 140 ++ + drivers/net/dpaa2/qbman/driver/qbman_portal.c | 1407 +++++++++++ + drivers/net/dpaa2/qbman/driver/qbman_portal.h | 266 ++ + drivers/net/dpaa2/qbman/driver/qbman_private.h | 165 ++ + drivers/net/dpaa2/qbman/driver/qbman_sys.h | 367 +++ + drivers/net/dpaa2/qbman/driver/qbman_sys_decl.h | 68 + + drivers/net/dpaa2/qbman/include/compat.h | 597 +++++ + .../dpaa2/qbman/include/drivers/fsl_qbman_base.h | 151 ++ + .../dpaa2/qbman/include/drivers/fsl_qbman_portal.h | 1089 +++++++++ + drivers/net/dpaa2/rte_eth_dpaa2_pvt.h | 313 +++ + drivers/net/dpaa2/rte_eth_dpbp.c | 430 ++++ + drivers/net/dpaa2/rte_eth_dpio.c | 339 +++ + drivers/net/dpaa2/rte_eth_dpni.c | 2230 +++++++++++++++++ + drivers/net/dpaa2/rte_eth_dpni_annot.h | 311 +++ + drivers/net/dpaa2/rte_pmd_dpaa2_version.map | 4 + + lib/librte_eal/common/eal_private.h | 12 + + lib/librte_eal/linuxapp/eal/Makefile | 11 + + lib/librte_eal/linuxapp/eal/eal.c | 10 + + lib/librte_eal/linuxapp/eal/eal_soc.c | 84 + + lib/librte_eal/linuxapp/eal/eal_vfio_fsl_mc.c | 653 +++++ + lib/librte_eal/linuxapp/eal/eal_vfio_fsl_mc.h | 102 + + lib/librte_mbuf/Makefile | 4 + + lib/librte_mbuf/rte_mbuf.c | 67 + + lib/librte_mempool/Makefile | 4 + + lib/librte_mempool/rte_mempool.c | 13 + + lib/librte_mempool/rte_mempool.h | 30 +- + mk/machine/dpaa2/rte.vars.mk | 60 + + mk/rte.app.mk | 1 + + 89 files changed, 39560 insertions(+), 1 deletion(-) + create mode 100644 config/defconfig_arm64-dpaa2-linuxapp-gcc + create mode 100644 drivers/net/dpaa2/Makefile + create mode 100644 drivers/net/dpaa2/dpaa2_logs.h + create mode 100644 drivers/net/dpaa2/mc/dpaiop.c + create mode 100644 drivers/net/dpaa2/mc/dpbp.c + create mode 100644 drivers/net/dpaa2/mc/dpci.c + create mode 100644 drivers/net/dpaa2/mc/dpcon.c + create mode 100644 drivers/net/dpaa2/mc/dpdbg.c + create mode 100644 drivers/net/dpaa2/mc/dpdcei.c + create mode 100644 drivers/net/dpaa2/mc/dpdmai.c + create mode 100644 drivers/net/dpaa2/mc/dpdmux.c + create mode 100644 drivers/net/dpaa2/mc/dpio.c + create mode 100644 drivers/net/dpaa2/mc/dpmac.c + create mode 100644 drivers/net/dpaa2/mc/dpmcp.c + create mode 100644 drivers/net/dpaa2/mc/dpmng.c + create mode 100644 drivers/net/dpaa2/mc/dpni.c + create mode 100644 drivers/net/dpaa2/mc/dprc.c + create mode 100644 drivers/net/dpaa2/mc/dprtc.c + create mode 100644 drivers/net/dpaa2/mc/dpseci.c + create mode 100644 drivers/net/dpaa2/mc/dpsw.c + create mode 100644 drivers/net/dpaa2/mc/fsl_dpaiop.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpaiop_cmd.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpbp.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpbp_cmd.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpci.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpci_cmd.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpcon.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpcon_cmd.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpdbg.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpdbg_cmd.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpdcei.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpdcei_cmd.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpdmai.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpdmai_cmd.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpdmux.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpdmux_cmd.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpio.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpio_cmd.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpkg.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpmac.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpmac_cmd.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpmcp.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpmcp_cmd.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpmng.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpmng_cmd.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpni.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpni_cmd.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dprc.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dprc_cmd.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dprtc.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dprtc_cmd.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpseci.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpseci_cmd.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpsw.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpsw_cmd.h + create mode 100644 drivers/net/dpaa2/mc/fsl_mc_cmd.h + create mode 100644 drivers/net/dpaa2/mc/fsl_mc_sys.h + create mode 100644 drivers/net/dpaa2/mc/fsl_net.h + create mode 100644 drivers/net/dpaa2/mc/mc_sys.c + create mode 100644 drivers/net/dpaa2/qbman/driver/qbman_debug.c + create mode 100644 drivers/net/dpaa2/qbman/driver/qbman_debug.h + create mode 100644 drivers/net/dpaa2/qbman/driver/qbman_portal.c + create mode 100644 drivers/net/dpaa2/qbman/driver/qbman_portal.h + create mode 100644 drivers/net/dpaa2/qbman/driver/qbman_private.h + create mode 100644 drivers/net/dpaa2/qbman/driver/qbman_sys.h + create mode 100644 drivers/net/dpaa2/qbman/driver/qbman_sys_decl.h + create mode 100644 drivers/net/dpaa2/qbman/include/compat.h + create mode 100644 drivers/net/dpaa2/qbman/include/drivers/fsl_qbman_base.h + create mode 100644 drivers/net/dpaa2/qbman/include/drivers/fsl_qbman_portal.h + create mode 100644 drivers/net/dpaa2/rte_eth_dpaa2_pvt.h + create mode 100644 drivers/net/dpaa2/rte_eth_dpbp.c + create mode 100644 drivers/net/dpaa2/rte_eth_dpio.c + create mode 100644 drivers/net/dpaa2/rte_eth_dpni.c + create mode 100644 drivers/net/dpaa2/rte_eth_dpni_annot.h + create mode 100644 drivers/net/dpaa2/rte_pmd_dpaa2_version.map + create mode 100644 lib/librte_eal/linuxapp/eal/eal_soc.c + create mode 100644 lib/librte_eal/linuxapp/eal/eal_vfio_fsl_mc.c + create mode 100644 lib/librte_eal/linuxapp/eal/eal_vfio_fsl_mc.h + create mode 100644 mk/machine/dpaa2/rte.vars.mk + +diff --git a/config/defconfig_arm64-dpaa2-linuxapp-gcc b/config/defconfig_arm64-dpaa2-linuxapp-gcc +new file mode 100644 +index 0000000..fafbef4 +--- /dev/null ++++ b/config/defconfig_arm64-dpaa2-linuxapp-gcc +@@ -0,0 +1,61 @@ ++# BSD LICENSE ++# ++# Copyright(c) 2016 Freescale Semiconductor, Inc. All rights reserved. ++# ++# Redistribution and use in source and binary forms, with or without ++# modification, are permitted provided that the following conditions ++# are met: ++# ++# * Redistributions of source code must retain the above copyright ++# notice, this list of conditions and the following disclaimer. ++# * Redistributions in binary form must reproduce the above copyright ++# notice, this list of conditions and the following disclaimer in ++# the documentation and/or other materials provided with the ++# distribution. ++# * Neither the name of Freescale Semiconductor nor the names of its ++# contributors may be used to endorse or promote products derived ++# from this software without specific prior written permission. ++# ++# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++# ++ ++#include "defconfig_arm64-armv8a-linuxapp-gcc" ++ ++# NXP (Freescale) - Soc Architecture with WRIOP and QBMAN support ++CONFIG_RTE_MACHINE="dpaa2" ++CONFIG_RTE_ARCH_ARM_TUNE="cortex-a57+fp+simd" ++ ++# ++# Compile Environment Abstraction Layer ++# ++CONFIG_RTE_MAX_LCORE=8 ++CONFIG_RTE_MAX_NUMA_NODES=1 ++ ++# Compile software PMD backed by FSL DPAA2 files ++# ++CONFIG_RTE_LIBRTE_DPAA2_PMD=y ++CONFIG_RTE_LIBRTE_DPAA2_USE_PHYS_IOVA=n ++CONFIG_RTE_LIBRTE_DPAA2_DEBUG_INIT=n ++CONFIG_RTE_LIBRTE_DPAA2_DEBUG_DRIVER=n ++CONFIG_RTE_LIBRTE_ETHDEV_DEBUG=n ++ ++CONFIG_RTE_LIBRTE_PMD_BOND=y ++CONFIG_RTE_CACHE_LINE_SIZE=128 ++CONFIG_RTE_EAL_IGB_UIO=n ++CONFIG_RTE_LIBRTE_KNI=n ++ ++#FSL DPAA2 caam driver ++CONFIG_RTE_LIBRTE_PMD_DPAA2_CAAM=n ++CONFIG_RTE_LIBRTE_DPAA2_CAAM_DEBUG_INIT=n ++CONFIG_RTE_LIBRTE_DPAA2_CAAM_DEBUG_DRIVER=n ++CONFIG_RTE_LIBRTE_DPAA2_CAAM_DEBUG_RX=n +diff --git a/drivers/net/Makefile b/drivers/net/Makefile +index 3386a67..ed10351 100644 +--- a/drivers/net/Makefile ++++ b/drivers/net/Makefile +@@ -52,6 +52,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PMD_SZEDATA2) += szedata2 + DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtio + DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += vmxnet3 + DIRS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += xenvirt ++DIRS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD) += dpaa2 + + ifeq ($(CONFIG_RTE_LIBRTE_VHOST),y) + DIRS-$(CONFIG_RTE_LIBRTE_PMD_VHOST) += vhost +diff --git a/drivers/net/dpaa2/Makefile b/drivers/net/dpaa2/Makefile +new file mode 100644 +index 0000000..3cf1782 +--- /dev/null ++++ b/drivers/net/dpaa2/Makefile +@@ -0,0 +1,102 @@ ++# BSD LICENSE ++# ++# Copyright (c) 2014 Freescale Semiconductor, Inc. All rights reserved. ++# ++# Redistribution and use in source and binary forms, with or without ++# modification, are permitted provided that the following conditions ++# are met: ++# ++# * Redistributions of source code must retain the above copyright ++# notice, this list of conditions and the following disclaimer. ++# * Redistributions in binary form must reproduce the above copyright ++# notice, this list of conditions and the following disclaimer in ++# the documentation and/or other materials provided with the ++# distribution. ++# * Neither the name of Freescale Semiconductor nor the names of its ++# contributors may be used to endorse or promote products derived ++# from this software without specific prior written permission. ++# ++# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ ++include $(RTE_SDK)/mk/rte.vars.mk ++ ++# ++# library name ++# ++LIB = librte_pmd_dpaa2.a ++ ++ifeq ($(CONFIG_RTE_LIBRTE_DPAA2_DEBUG_INIT),y) ++CFLAGS += -O0 -g ++CFLAGS += "-Wno-error" ++else ++CFLAGS += -O3 -g ++CFLAGS += $(WERROR_FLAGS) ++endif ++CFLAGS +=-Wno-strict-aliasing ++CFLAGS +=-Wno-missing-prototypes ++CFLAGS +=-Wno-missing-declarations ++CFLAGS +=-Wno-unused-function ++ ++CFLAGS += -I$(RTE_SDK)/drivers/net/dpaa2/mc ++CFLAGS += -I$(RTE_SDK)/drivers/net/dpaa2/qbman/include ++CFLAGS += -I$(RTE_SDK)/drivers/net/dpaa2/qbman/include/drivers ++CFLAGS += -I$(RTE_SDK)/drivers/net/dpaa2/driver/ ++CFLAGS += -I$(RTE_SDK)/lib/librte_eal/common/include ++CFLAGS += -I$(RTE_SDK)/lib/librte_ether ++CFLAGS += -I$(RTE_SDK)/lib/librte_eal/linuxapp/eal ++ ++EXPORT_MAP := rte_pmd_dpaa2_version.map ++ ++LIBABIVER := 1 ++# ++# all source are stored in SRCS-y ++# ++SRCS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD) += \ ++ mc/dprc.c \ ++ mc/dprtc.o \ ++ mc/dpaiop.c \ ++ mc/dpdbg.o \ ++ mc/dpdcei.c \ ++ mc/dpdmai.c \ ++ mc/dpmac.c \ ++ mc/dpmcp.c \ ++ mc/dpbp.c \ ++ mc/dpio.c \ ++ mc/dpni.c \ ++ mc/dpsw.c \ ++ mc/dpci.c \ ++ mc/dpcon.c \ ++ mc/dpseci.c \ ++ mc/dpmng.c \ ++ mc/dpdmux.c \ ++ mc/mc_sys.c ++ ++# ++# all source are stored in SRCS-y ++# ++SRCS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD) += \ ++ qbman/driver/qbman_portal.c \ ++ qbman/driver/qbman_debug.c ++ ++SRCS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD) += rte_eth_dpni.c ++SRCS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD) += rte_eth_dpio.c ++SRCS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD) += rte_eth_dpbp.c ++ ++# ++# Export include files ++# ++SYMLINK-y-include += ++ ++# this lib depends upon: ++DEPDIRS-y += lib/librte_eal ++include $(RTE_SDK)/mk/rte.lib.mk +diff --git a/drivers/net/dpaa2/dpaa2_logs.h b/drivers/net/dpaa2/dpaa2_logs.h +new file mode 100644 +index 0000000..319786a +--- /dev/null ++++ b/drivers/net/dpaa2/dpaa2_logs.h +@@ -0,0 +1,77 @@ ++/*- ++ * BSD LICENSE ++ * ++ * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * * Neither the name of Freescale Semiconductor, Inc nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++ ++#ifndef _DPAA2_LOGS_H_ ++#define _DPAA2_LOGS_H_ ++ ++#define PMD_INIT_LOG(level, fmt, args...) \ ++ RTE_LOG(level, PMD, "%s(): " fmt "\n", __func__, ##args) ++ ++#ifdef RTE_LIBRTE_DPAA2_DEBUG_INIT ++#define PMD_INIT_FUNC_TRACE() PMD_INIT_LOG(DEBUG, " >>") ++#else ++#define PMD_INIT_FUNC_TRACE() do { } while (0) ++#endif ++ ++#ifdef RTE_LIBRTE_DPAA2_DEBUG_RX ++#define PMD_RX_LOG(level, fmt, args...) \ ++ RTE_LOG(level, PMD, "%s(): " fmt "\n", __func__, ## args) ++#else ++#define PMD_RX_LOG(level, fmt, args...) do { } while(0) ++#endif ++ ++#ifdef RTE_LIBRTE_DPAA2_DEBUG_TX ++#define PMD_TX_LOG(level, fmt, args...) \ ++ RTE_LOG(level, PMD, "%s(): " fmt "\n", __func__, ## args) ++#else ++#define PMD_TX_LOG(level, fmt, args...) do { } while(0) ++#endif ++ ++#ifdef RTE_LIBRTE_DPAA2_DEBUG_TX_FREE ++#define PMD_TX_FREE_LOG(level, fmt, args...) \ ++ RTE_LOG(level, PMD, "%s(): " fmt "\n", __func__, ## args) ++#else ++#define PMD_TX_FREE_LOG(level, fmt, args...) do { } while(0) ++#endif ++ ++#ifdef RTE_LIBRTE_DPAA2_DEBUG_DRIVER ++#define PMD_DRV_LOG_RAW(level, fmt, args...) \ ++ RTE_LOG(level, PMD, "%s(): " fmt, __func__, ## args) ++#else ++#define PMD_DRV_LOG_RAW(level, fmt, args...) do { } while (0) ++#endif ++ ++#define PMD_DRV_LOG(level, fmt, args...) \ ++ PMD_DRV_LOG_RAW(level, fmt "\n", ## args) ++ ++#endif /* _DPAA2_LOGS_H_ */ +diff --git a/drivers/net/dpaa2/mc/dpaiop.c b/drivers/net/dpaa2/mc/dpaiop.c +new file mode 100644 +index 0000000..7c1ecff +--- /dev/null ++++ b/drivers/net/dpaa2/mc/dpaiop.c +@@ -0,0 +1,457 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++#include ++#include ++ ++int dpaiop_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpaiop_id, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_OPEN, ++ cmd_flags, ++ 0); ++ DPAIOP_CMD_OPEN(cmd, dpaiop_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return err; ++} ++ ++int dpaiop_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_CLOSE, cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpaiop_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpaiop_cfg *cfg, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ (void)(cfg); /* unused */ ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_CREATE, ++ cmd_flags, ++ 0); ++ DPAIOP_CMD_CREATE(cmd, cfg); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpaiop_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_DESTROY, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpaiop_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_RESET, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpaiop_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpaiop_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_SET_IRQ, ++ cmd_flags, ++ token); ++ ++ DPAIOP_CMD_SET_IRQ(cmd, irq_index, irq_cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpaiop_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpaiop_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_GET_IRQ, ++ cmd_flags, ++ token); ++ ++ DPAIOP_CMD_GET_IRQ(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPAIOP_RSP_GET_IRQ(cmd, *type, irq_cfg); ++ ++ return 0; ++} ++ ++int dpaiop_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_SET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ ++ DPAIOP_CMD_SET_IRQ_ENABLE(cmd, irq_index, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpaiop_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_GET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ ++ DPAIOP_CMD_GET_IRQ_ENABLE(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPAIOP_RSP_GET_IRQ_ENABLE(cmd, *en); ++ ++ return 0; ++} ++ ++int dpaiop_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_SET_IRQ_MASK, ++ cmd_flags, ++ token); ++ ++ DPAIOP_CMD_SET_IRQ_MASK(cmd, irq_index, mask); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpaiop_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_GET_IRQ_MASK, ++ cmd_flags, ++ token); ++ ++ DPAIOP_CMD_GET_IRQ_MASK(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPAIOP_RSP_GET_IRQ_MASK(cmd, *mask); ++ ++ return 0; ++} ++ ++int dpaiop_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_GET_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPAIOP_CMD_GET_IRQ_STATUS(cmd, irq_index, *status); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPAIOP_RSP_GET_IRQ_STATUS(cmd, *status); ++ ++ return 0; ++} ++ ++int dpaiop_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_CLEAR_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPAIOP_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpaiop_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpaiop_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_GET_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPAIOP_RSP_GET_ATTRIBUTES(cmd, attr); ++ ++ return 0; ++} ++ ++int dpaiop_load(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpaiop_load_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_LOAD, ++ cmd_flags, ++ token); ++ DPAIOP_CMD_LOAD(cmd, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpaiop_run(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpaiop_run_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_RUN, ++ cmd_flags, ++ token); ++ DPAIOP_CMD_RUN(cmd, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpaiop_get_sl_version(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpaiop_sl_version *version) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_GET_SL_VERSION, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPAIOP_RSP_GET_SL_VERSION(cmd, version); ++ ++ return 0; ++} ++ ++int dpaiop_get_state(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint32_t *state) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_GET_STATE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPAIOP_RSP_GET_STATE(cmd, *state); ++ ++ return 0; ++} ++ ++int dpaiop_set_time_of_day(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint64_t time_of_day) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_SET_TIME_OF_DAY, ++ cmd_flags, ++ token); ++ ++ DPAIOP_CMD_SET_TIME_OF_DAY(cmd, time_of_day); ++ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpaiop_get_time_of_day(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint64_t *time_of_day) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_GET_TIME_OF_DAY, ++ cmd_flags, ++ token); ++ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ DPAIOP_RSP_GET_TIME_OF_DAY(cmd, *time_of_day); ++ ++ return 0; ++} +diff --git a/drivers/net/dpaa2/mc/dpbp.c b/drivers/net/dpaa2/mc/dpbp.c +new file mode 100644 +index 0000000..87899b8 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/dpbp.c +@@ -0,0 +1,432 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++#include ++#include ++ ++int dpbp_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpbp_id, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_OPEN, ++ cmd_flags, ++ 0); ++ DPBP_CMD_OPEN(cmd, dpbp_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return err; ++} ++ ++int dpbp_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_CLOSE, cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpbp_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpbp_cfg *cfg, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ (void)(cfg); /* unused */ ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_CREATE, ++ cmd_flags, ++ 0); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpbp_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_DESTROY, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpbp_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_ENABLE, cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpbp_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_DISABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpbp_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_IS_ENABLED, cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPBP_RSP_IS_ENABLED(cmd, *en); ++ ++ return 0; ++} ++ ++int dpbp_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_RESET, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpbp_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpbp_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_SET_IRQ, ++ cmd_flags, ++ token); ++ ++ DPBP_CMD_SET_IRQ(cmd, irq_index, irq_cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpbp_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpbp_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_IRQ, ++ cmd_flags, ++ token); ++ ++ DPBP_CMD_GET_IRQ(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPBP_RSP_GET_IRQ(cmd, *type, irq_cfg); ++ ++ return 0; ++} ++ ++int dpbp_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_SET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ ++ DPBP_CMD_SET_IRQ_ENABLE(cmd, irq_index, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpbp_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ ++ DPBP_CMD_GET_IRQ_ENABLE(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPBP_RSP_GET_IRQ_ENABLE(cmd, *en); ++ ++ return 0; ++} ++ ++int dpbp_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_SET_IRQ_MASK, ++ cmd_flags, ++ token); ++ ++ DPBP_CMD_SET_IRQ_MASK(cmd, irq_index, mask); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpbp_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_IRQ_MASK, ++ cmd_flags, ++ token); ++ ++ DPBP_CMD_GET_IRQ_MASK(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPBP_RSP_GET_IRQ_MASK(cmd, *mask); ++ ++ return 0; ++} ++ ++int dpbp_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_IRQ_STATUS, ++ cmd_flags, ++ token); ++ ++ DPBP_CMD_GET_IRQ_STATUS(cmd, irq_index, *status); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPBP_RSP_GET_IRQ_STATUS(cmd, *status); ++ ++ return 0; ++} ++ ++int dpbp_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_CLEAR_IRQ_STATUS, ++ cmd_flags, ++ token); ++ ++ DPBP_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpbp_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpbp_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPBP_RSP_GET_ATTRIBUTES(cmd, attr); ++ ++ return 0; ++} ++ ++int dpbp_set_notifications(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpbp_notification_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_SET_NOTIFICATIONS, ++ cmd_flags, ++ token); ++ ++ DPBP_CMD_SET_NOTIFICATIONS(cmd, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpbp_get_notifications(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpbp_notification_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_NOTIFICATIONS, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPBP_CMD_GET_NOTIFICATIONS(cmd, cfg); ++ ++ return 0; ++} +diff --git a/drivers/net/dpaa2/mc/dpci.c b/drivers/net/dpaa2/mc/dpci.c +new file mode 100644 +index 0000000..2ec02a1 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/dpci.c +@@ -0,0 +1,501 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++#include ++#include ++ ++int dpci_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpci_id, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_OPEN, ++ cmd_flags, ++ 0); ++ DPCI_CMD_OPEN(cmd, dpci_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpci_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_CLOSE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpci_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpci_cfg *cfg, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_CREATE, ++ cmd_flags, ++ 0); ++ DPCI_CMD_CREATE(cmd, cfg); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpci_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_DESTROY, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpci_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_ENABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpci_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_DISABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpci_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_IS_ENABLED, cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPCI_RSP_IS_ENABLED(cmd, *en); ++ ++ return 0; ++} ++ ++int dpci_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_RESET, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpci_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpci_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_SET_IRQ, ++ cmd_flags, ++ token); ++ DPCI_CMD_SET_IRQ(cmd, irq_index, irq_cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpci_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpci_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_GET_IRQ, ++ cmd_flags, ++ token); ++ DPCI_CMD_GET_IRQ(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPCI_RSP_GET_IRQ(cmd, *type, irq_cfg); ++ ++ return 0; ++} ++ ++int dpci_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_SET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPCI_CMD_SET_IRQ_ENABLE(cmd, irq_index, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpci_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_GET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPCI_CMD_GET_IRQ_ENABLE(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPCI_RSP_GET_IRQ_ENABLE(cmd, *en); ++ ++ return 0; ++} ++ ++int dpci_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_SET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPCI_CMD_SET_IRQ_MASK(cmd, irq_index, mask); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpci_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_GET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPCI_CMD_GET_IRQ_MASK(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPCI_RSP_GET_IRQ_MASK(cmd, *mask); ++ ++ return 0; ++} ++ ++int dpci_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_GET_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPCI_CMD_GET_IRQ_STATUS(cmd, irq_index, *status); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPCI_RSP_GET_IRQ_STATUS(cmd, *status); ++ ++ return 0; ++} ++ ++int dpci_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_CLEAR_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPCI_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpci_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpci_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_GET_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPCI_RSP_GET_ATTR(cmd, attr); ++ ++ return 0; ++} ++ ++int dpci_get_peer_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpci_peer_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_GET_PEER_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPCI_RSP_GET_PEER_ATTR(cmd, attr); ++ ++ return 0; ++} ++ ++int dpci_get_link_state(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *up) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_GET_LINK_STATE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPCI_RSP_GET_LINK_STATE(cmd, *up); ++ ++ return 0; ++} ++ ++int dpci_set_rx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t priority, ++ const struct dpci_rx_queue_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_SET_RX_QUEUE, ++ cmd_flags, ++ token); ++ DPCI_CMD_SET_RX_QUEUE(cmd, priority, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpci_get_rx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t priority, ++ struct dpci_rx_queue_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_GET_RX_QUEUE, ++ cmd_flags, ++ token); ++ DPCI_CMD_GET_RX_QUEUE(cmd, priority); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPCI_RSP_GET_RX_QUEUE(cmd, attr); ++ ++ return 0; ++} ++ ++int dpci_get_tx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t priority, ++ struct dpci_tx_queue_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_GET_TX_QUEUE, ++ cmd_flags, ++ token); ++ DPCI_CMD_GET_TX_QUEUE(cmd, priority); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPCI_RSP_GET_TX_QUEUE(cmd, attr); ++ ++ return 0; ++} +diff --git a/drivers/net/dpaa2/mc/dpcon.c b/drivers/net/dpaa2/mc/dpcon.c +new file mode 100644 +index 0000000..396303d +--- /dev/null ++++ b/drivers/net/dpaa2/mc/dpcon.c +@@ -0,0 +1,401 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++#include ++#include ++ ++int dpcon_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpcon_id, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_OPEN, ++ cmd_flags, ++ 0); ++ DPCON_CMD_OPEN(cmd, dpcon_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpcon_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_CLOSE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpcon_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpcon_cfg *cfg, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_CREATE, ++ cmd_flags, ++ 0); ++ DPCON_CMD_CREATE(cmd, cfg); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpcon_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_DESTROY, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpcon_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_ENABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpcon_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_DISABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpcon_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_IS_ENABLED, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPCON_RSP_IS_ENABLED(cmd, *en); ++ ++ return 0; ++} ++ ++int dpcon_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_RESET, ++ cmd_flags, token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpcon_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpcon_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_SET_IRQ, ++ cmd_flags, ++ token); ++ DPCON_CMD_SET_IRQ(cmd, irq_index, irq_cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpcon_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpcon_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_GET_IRQ, ++ cmd_flags, ++ token); ++ DPCON_CMD_GET_IRQ(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPCON_RSP_GET_IRQ(cmd, *type, irq_cfg); ++ ++ return 0; ++} ++ ++int dpcon_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_SET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPCON_CMD_SET_IRQ_ENABLE(cmd, irq_index, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpcon_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_GET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPCON_CMD_GET_IRQ_ENABLE(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPCON_RSP_GET_IRQ_ENABLE(cmd, *en); ++ ++ return 0; ++} ++ ++int dpcon_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_SET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPCON_CMD_SET_IRQ_MASK(cmd, irq_index, mask); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpcon_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_GET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPCON_CMD_GET_IRQ_MASK(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPCON_RSP_GET_IRQ_MASK(cmd, *mask); ++ ++ return 0; ++} ++ ++int dpcon_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_GET_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPCON_CMD_GET_IRQ_STATUS(cmd, irq_index, *status); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPCON_RSP_GET_IRQ_STATUS(cmd, *status); ++ ++ return 0; ++} ++ ++int dpcon_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_CLEAR_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPCON_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpcon_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpcon_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_GET_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPCON_RSP_GET_ATTR(cmd, attr); ++ ++ return 0; ++} ++ ++int dpcon_set_notification(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpcon_notification_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_SET_NOTIFICATION, ++ cmd_flags, ++ token); ++ DPCON_CMD_SET_NOTIFICATION(cmd, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ +diff --git a/drivers/net/dpaa2/mc/dpdbg.c b/drivers/net/dpaa2/mc/dpdbg.c +new file mode 100644 +index 0000000..6f2a08d +--- /dev/null ++++ b/drivers/net/dpaa2/mc/dpdbg.c +@@ -0,0 +1,547 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++#include ++#include ++ ++int dpdbg_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpdbg_id, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_OPEN, ++ cmd_flags, ++ 0); ++ DPDBG_CMD_OPEN(cmd, dpdbg_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return err; ++} ++ ++int dpdbg_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_CLOSE, cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdbg_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpdbg_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_GET_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDBG_RSP_GET_ATTRIBUTES(cmd, attr); ++ ++ return 0; ++} ++ ++int dpdbg_get_dpni_info(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpni_id, ++ struct dpdbg_dpni_info *info) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_GET_DPNI_INFO, ++ cmd_flags, ++ token); ++ DPDBG_CMD_GET_DPNI_INFO(cmd, dpni_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDBG_RSP_GET_DPNI_INFO(cmd, info); ++ ++ return 0; ++} ++ ++int dpdbg_get_dpni_priv_tx_conf_fqid(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpni_id, ++ uint8_t sender_id, ++ uint32_t *fqid) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header( ++ DPDBG_CMDID_GET_DPNI_PRIV_TX_CONF_FQID, ++ cmd_flags, ++ token); ++ DPDBG_CMD_GET_DPNI_PRIV_TX_CONF_FQID(cmd, dpni_id, sender_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDBG_RSP_GET_DPNI_PRIV_TX_CONF_FQID(cmd, *fqid); ++ ++ return 0; ++} ++ ++int dpdbg_get_dpcon_info(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpcon_id, ++ struct dpdbg_dpcon_info *info) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_GET_DPCON_INFO, ++ cmd_flags, ++ token); ++ DPDBG_CMD_GET_DPCON_INFO(cmd, dpcon_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDBG_RSP_GET_DPCON_INFO(cmd, info); ++ ++ return 0; ++} ++ ++int dpdbg_get_dpbp_info(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpbp_id, ++ struct dpdbg_dpbp_info *info) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_GET_DPBP_INFO, ++ cmd_flags, ++ token); ++ DPDBG_CMD_GET_DPBP_INFO(cmd, dpbp_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDBG_RSP_GET_DPBP_INFO(cmd, info); ++ ++ return 0; ++} ++ ++int dpdbg_get_dpci_fqid(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpci_id, ++ uint8_t priority, ++ uint32_t *fqid) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_GET_DPBP_INFO, ++ cmd_flags, ++ token); ++ DPDBG_CMD_GET_DPCI_FQID(cmd, dpci_id, priority); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDBG_RSP_GET_DPCI_FQID(cmd, *fqid); ++ ++ return 0; ++} ++ ++int dpdbg_prepare_ctlu_global_rule(struct dpkg_profile_cfg *dpkg_rule, ++ uint8_t *rule_buf) ++{ ++ int i, j; ++ int offset = 0; ++ int param = 1; ++ uint64_t *params = (uint64_t *)rule_buf; ++ ++ if (!rule_buf || !dpkg_rule) ++ return -EINVAL; ++ ++ params[0] |= mc_enc(0, 8, dpkg_rule->num_extracts); ++ params[0] = cpu_to_le64(params[0]); ++ ++ if (dpkg_rule->num_extracts >= DPKG_MAX_NUM_OF_EXTRACTS) ++ return -EINVAL; ++ ++ for (i = 0; i < dpkg_rule->num_extracts; i++) { ++ switch (dpkg_rule->extracts[i].type) { ++ case DPKG_EXTRACT_FROM_HDR: ++ params[param] |= mc_enc(0, 8, ++ dpkg_rule->extracts[i].extract.from_hdr.prot); ++ params[param] |= mc_enc(8, 4, ++ dpkg_rule->extracts[i].extract.from_hdr.type); ++ params[param] |= mc_enc(16, 8, ++ dpkg_rule->extracts[i].extract.from_hdr.size); ++ params[param] |= mc_enc(24, 8, ++ dpkg_rule->extracts[i].extract.from_hdr.offset); ++ params[param] |= mc_enc(32, 32, ++ dpkg_rule->extracts[i].extract.from_hdr.field); ++ params[param] = cpu_to_le64(params[param]); ++ param++; ++ params[param] |= mc_enc(0, 8, ++ dpkg_rule->extracts[i].extract. ++ from_hdr.hdr_index); ++ break; ++ case DPKG_EXTRACT_FROM_DATA: ++ params[param] |= mc_enc(16, 8, ++ dpkg_rule->extracts[i].extract.from_data.size); ++ params[param] |= mc_enc(24, 8, ++ dpkg_rule->extracts[i].extract. ++ from_data.offset); ++ params[param] = cpu_to_le64(params[param]); ++ param++; ++ break; ++ case DPKG_EXTRACT_FROM_PARSE: ++ params[param] |= mc_enc(16, 8, ++ dpkg_rule->extracts[i].extract.from_parse.size); ++ params[param] |= mc_enc(24, 8, ++ dpkg_rule->extracts[i].extract. ++ from_parse.offset); ++ params[param] = cpu_to_le64(params[param]); ++ param++; ++ break; ++ default: ++ return -EINVAL; ++ } ++ params[param] |= mc_enc( ++ 24, 8, dpkg_rule->extracts[i].num_of_byte_masks); ++ params[param] |= mc_enc(32, 4, dpkg_rule->extracts[i].type); ++ params[param] = cpu_to_le64(params[param]); ++ param++; ++ for (offset = 0, j = 0; ++ j < DPKG_NUM_OF_MASKS; ++ offset += 16, j++) { ++ params[param] |= mc_enc( ++ (offset), 8, ++ dpkg_rule->extracts[i].masks[j].mask); ++ params[param] |= mc_enc( ++ (offset + 8), 8, ++ dpkg_rule->extracts[i].masks[j].offset); ++ } ++ params[param] = cpu_to_le64(params[param]); ++ param++; ++ } ++ return 0; ++} ++ ++int dpdbg_set_ctlu_global_marking(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t marking, ++ struct dpdbg_rule_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_SET_CTLU_GLOBAL_MARKING, ++ cmd_flags, ++ token); ++ DPDBG_CMD_SET_CTLU_GLOBAL_MARKING(cmd, marking, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdbg_set_dpni_rx_marking(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpni_id, ++ struct dpdbg_dpni_rx_marking_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_SET_DPNI_RX_MARKING, ++ cmd_flags, ++ token); ++ DPDBG_CMD_SET_DPNI_RX_MARKING(cmd, dpni_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdbg_set_dpni_tx_conf_marking(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpni_id, ++ uint16_t sender_id, ++ uint8_t marking) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_SET_DPNI_TX_CONF_MARKING, ++ cmd_flags, ++ token); ++ DPDBG_CMD_SET_DPNI_TX_CONF_MARKING(cmd, dpni_id, sender_id, marking); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdbg_set_dpio_marking(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpio_id, ++ uint8_t marking) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_SET_DPIO_MARKING, ++ cmd_flags, ++ token); ++ DPDBG_CMD_SET_DPIO_MARKING(cmd, dpio_id, marking); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdbg_set_ctlu_global_trace(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpdbg_rule_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_SET_CTLU_GLOBAL_TRACE, ++ cmd_flags, ++ token); ++ DPDBG_CMD_SET_CTLU_GLOBAL_TRACE(cmd, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdbg_set_dpio_trace(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpio_id, ++ struct dpdbg_dpio_trace_cfg ++ trace_point[DPDBG_NUM_OF_DPIO_TRACE_POINTS]) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_SET_DPIO_TRACE, ++ cmd_flags, ++ token); ++ DPDBG_CMD_SET_DPIO_TRACE(cmd, dpio_id, trace_point); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdbg_set_dpni_rx_trace(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpni_id, ++ struct dpdbg_dpni_rx_trace_cfg *trace_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_SET_DPNI_RX_TRACE, ++ cmd_flags, ++ token); ++ DPDBG_CMD_SET_DPNI_RX_TRACE(cmd, dpni_id, trace_cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdbg_set_dpni_tx_trace(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpni_id, ++ uint16_t sender_id, ++ struct dpdbg_dpni_tx_trace_cfg *trace_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_SET_DPNI_TX_TRACE, ++ cmd_flags, ++ token); ++ DPDBG_CMD_SET_DPNI_TX_TRACE(cmd, dpni_id, sender_id, trace_cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdbg_set_dpcon_trace(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpcon_id, ++ struct dpdbg_dpcon_trace_cfg ++ trace_point[DPDBG_NUM_OF_DPCON_TRACE_POINTS]) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_SET_DPCON_TRACE, ++ cmd_flags, ++ token); ++ DPDBG_CMD_SET_DPCON_TRACE(cmd, dpcon_id, trace_point); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdbg_set_dpseci_trace(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpseci_id, ++ struct dpdbg_dpseci_trace_cfg ++ trace_point[DPDBG_NUM_OF_DPSECI_TRACE_POINTS]) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_SET_DPSECI_TRACE, ++ cmd_flags, ++ token); ++ DPDBG_CMD_SET_DPSECI_TRACE(cmd, dpseci_id, trace_point); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdbg_get_dpmac_counter(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpmac_id, ++ enum dpmac_counter counter_type, ++ uint64_t *counter) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_GET_DPMAC_COUNTER, ++ cmd_flags, ++ token); ++ DPDBG_CMD_GET_DPMAC_COUNTER(cmd, dpmac_id, counter_type); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDBG_RSP_GET_DPMAC_COUNTER(cmd, *counter); ++ ++ return 0; ++} ++ ++int dpdbg_get_dpni_counter(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpni_id, ++ enum dpni_counter counter_type, ++ uint64_t *counter) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_GET_DPNI_COUNTER, ++ cmd_flags, ++ token); ++ DPDBG_CMD_GET_DPMAC_COUNTER(cmd, dpni_id, counter_type); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDBG_RSP_GET_DPNI_COUNTER(cmd, *counter); ++ ++ return 0; ++} +diff --git a/drivers/net/dpaa2/mc/dpdcei.c b/drivers/net/dpaa2/mc/dpdcei.c +new file mode 100644 +index 0000000..a5c4c47 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/dpdcei.c +@@ -0,0 +1,449 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++#include ++#include ++ ++int dpdcei_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpdcei_id, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_OPEN, ++ cmd_flags, ++ 0); ++ DPDCEI_CMD_OPEN(cmd, dpdcei_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpdcei_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_CLOSE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdcei_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpdcei_cfg *cfg, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_CREATE, ++ cmd_flags, ++ 0); ++ DPDCEI_CMD_CREATE(cmd, cfg); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpdcei_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_DESTROY, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdcei_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_ENABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdcei_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_DISABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdcei_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_IS_ENABLED, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDCEI_RSP_IS_ENABLED(cmd, *en); ++ ++ return 0; ++} ++ ++int dpdcei_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_RESET, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdcei_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpdcei_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_GET_IRQ, ++ cmd_flags, ++ token); ++ DPDCEI_CMD_GET_IRQ(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDCEI_RSP_GET_IRQ(cmd, *type, irq_cfg); ++ ++ return 0; ++} ++ ++int dpdcei_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpdcei_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_SET_IRQ, ++ cmd_flags, ++ token); ++ DPDCEI_CMD_SET_IRQ(cmd, irq_index, irq_cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdcei_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_GET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPDCEI_CMD_GET_IRQ_ENABLE(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDCEI_RSP_GET_IRQ_ENABLE(cmd, *en); ++ ++ return 0; ++} ++ ++int dpdcei_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_SET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPDCEI_CMD_SET_IRQ_ENABLE(cmd, irq_index, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdcei_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_GET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPDCEI_CMD_GET_IRQ_MASK(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDCEI_RSP_GET_IRQ_MASK(cmd, *mask); ++ ++ return 0; ++} ++ ++int dpdcei_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_SET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPDCEI_CMD_SET_IRQ_MASK(cmd, irq_index, mask); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdcei_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_GET_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPDCEI_CMD_GET_IRQ_STATUS(cmd, irq_index, *status); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDCEI_RSP_GET_IRQ_STATUS(cmd, *status); ++ ++ return 0; ++} ++ ++int dpdcei_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_CLEAR_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPDCEI_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdcei_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpdcei_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_GET_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDCEI_RSP_GET_ATTR(cmd, attr); ++ ++ return 0; ++} ++ ++int dpdcei_set_rx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpdcei_rx_queue_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_SET_RX_QUEUE, ++ cmd_flags, ++ token); ++ DPDCEI_CMD_SET_RX_QUEUE(cmd, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdcei_get_rx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpdcei_rx_queue_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_GET_RX_QUEUE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDCEI_RSP_GET_RX_QUEUE(cmd, attr); ++ ++ return 0; ++} ++ ++int dpdcei_get_tx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpdcei_tx_queue_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_GET_TX_QUEUE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDCEI_RSP_GET_TX_QUEUE(cmd, attr); ++ ++ return 0; ++} +diff --git a/drivers/net/dpaa2/mc/dpdmai.c b/drivers/net/dpaa2/mc/dpdmai.c +new file mode 100644 +index 0000000..154d2c6 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/dpdmai.c +@@ -0,0 +1,452 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++#include ++#include ++ ++int dpdmai_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpdmai_id, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_OPEN, ++ cmd_flags, ++ 0); ++ DPDMAI_CMD_OPEN(cmd, dpdmai_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpdmai_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_CLOSE, ++ cmd_flags, token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmai_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpdmai_cfg *cfg, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_CREATE, ++ cmd_flags, ++ 0); ++ DPDMAI_CMD_CREATE(cmd, cfg); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpdmai_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_DESTROY, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmai_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_ENABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmai_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_DISABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmai_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_IS_ENABLED, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDMAI_RSP_IS_ENABLED(cmd, *en); ++ ++ return 0; ++} ++ ++int dpdmai_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_RESET, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmai_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpdmai_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_GET_IRQ, ++ cmd_flags, ++ token); ++ DPDMAI_CMD_GET_IRQ(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDMAI_RSP_GET_IRQ(cmd, *type, irq_cfg); ++ ++ return 0; ++} ++ ++int dpdmai_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpdmai_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_SET_IRQ, ++ cmd_flags, ++ token); ++ DPDMAI_CMD_SET_IRQ(cmd, irq_index, irq_cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmai_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_GET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPDMAI_CMD_GET_IRQ_ENABLE(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDMAI_RSP_GET_IRQ_ENABLE(cmd, *en); ++ ++ return 0; ++} ++ ++int dpdmai_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_SET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPDMAI_CMD_SET_IRQ_ENABLE(cmd, irq_index, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmai_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_GET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPDMAI_CMD_GET_IRQ_MASK(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDMAI_RSP_GET_IRQ_MASK(cmd, *mask); ++ ++ return 0; ++} ++ ++int dpdmai_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_SET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPDMAI_CMD_SET_IRQ_MASK(cmd, irq_index, mask); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmai_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_GET_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPDMAI_CMD_GET_IRQ_STATUS(cmd, irq_index, *status); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDMAI_RSP_GET_IRQ_STATUS(cmd, *status); ++ ++ return 0; ++} ++ ++int dpdmai_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_CLEAR_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPDMAI_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmai_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpdmai_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_GET_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDMAI_RSP_GET_ATTR(cmd, attr); ++ ++ return 0; ++} ++ ++int dpdmai_set_rx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t priority, ++ const struct dpdmai_rx_queue_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_SET_RX_QUEUE, ++ cmd_flags, ++ token); ++ DPDMAI_CMD_SET_RX_QUEUE(cmd, priority, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmai_get_rx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t priority, struct dpdmai_rx_queue_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_GET_RX_QUEUE, ++ cmd_flags, ++ token); ++ DPDMAI_CMD_GET_RX_QUEUE(cmd, priority); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDMAI_RSP_GET_RX_QUEUE(cmd, attr); ++ ++ return 0; ++} ++ ++int dpdmai_get_tx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t priority, ++ struct dpdmai_tx_queue_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_GET_TX_QUEUE, ++ cmd_flags, ++ token); ++ DPDMAI_CMD_GET_TX_QUEUE(cmd, priority); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDMAI_RSP_GET_TX_QUEUE(cmd, attr); ++ ++ return 0; ++} +diff --git a/drivers/net/dpaa2/mc/dpdmux.c b/drivers/net/dpaa2/mc/dpdmux.c +new file mode 100644 +index 0000000..dc07608 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/dpdmux.c +@@ -0,0 +1,567 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++#include ++#include ++ ++int dpdmux_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpdmux_id, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_OPEN, ++ cmd_flags, ++ 0); ++ DPDMUX_CMD_OPEN(cmd, dpdmux_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpdmux_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_CLOSE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmux_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpdmux_cfg *cfg, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_CREATE, ++ cmd_flags, ++ 0); ++ DPDMUX_CMD_CREATE(cmd, cfg); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpdmux_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_DESTROY, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmux_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_ENABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmux_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_DISABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmux_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IS_ENABLED, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDMUX_RSP_IS_ENABLED(cmd, *en); ++ ++ return 0; ++} ++ ++int dpdmux_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_RESET, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmux_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpdmux_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_SET_IRQ, ++ cmd_flags, ++ token); ++ DPDMUX_CMD_SET_IRQ(cmd, irq_index, irq_cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmux_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpdmux_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_GET_IRQ, ++ cmd_flags, ++ token); ++ DPDMUX_CMD_GET_IRQ(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDMUX_RSP_GET_IRQ(cmd, *type, irq_cfg); ++ ++ return 0; ++} ++ ++int dpdmux_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_SET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPDMUX_CMD_SET_IRQ_ENABLE(cmd, irq_index, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmux_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_GET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPDMUX_CMD_GET_IRQ_ENABLE(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDMUX_RSP_GET_IRQ_ENABLE(cmd, *en); ++ ++ return 0; ++} ++ ++int dpdmux_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_SET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPDMUX_CMD_SET_IRQ_MASK(cmd, irq_index, mask); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmux_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_GET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPDMUX_CMD_GET_IRQ_MASK(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDMUX_RSP_GET_IRQ_MASK(cmd, *mask); ++ ++ return 0; ++} ++ ++int dpdmux_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_GET_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPDMUX_CMD_GET_IRQ_STATUS(cmd, irq_index, *status); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDMUX_RSP_GET_IRQ_STATUS(cmd, *status); ++ ++ return 0; ++} ++ ++int dpdmux_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_CLEAR_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPDMUX_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmux_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpdmux_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_GET_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDMUX_RSP_GET_ATTR(cmd, attr); ++ ++ return 0; ++} ++ ++int dpdmux_ul_set_max_frame_length(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t max_frame_length) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_UL_SET_MAX_FRAME_LENGTH, ++ cmd_flags, ++ token); ++ DPDMUX_CMD_UL_SET_MAX_FRAME_LENGTH(cmd, max_frame_length); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmux_ul_reset_counters(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_UL_RESET_COUNTERS, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmux_if_set_accepted_frames(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpdmux_accepted_frames *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_SET_ACCEPTED_FRAMES, ++ cmd_flags, ++ token); ++ DPDMUX_CMD_IF_SET_ACCEPTED_FRAMES(cmd, if_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmux_if_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ struct dpdmux_if_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_GET_ATTR, ++ cmd_flags, ++ token); ++ DPDMUX_CMD_IF_GET_ATTR(cmd, if_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDMUX_RSP_IF_GET_ATTR(cmd, attr); ++ ++ return 0; ++} ++ ++int dpdmux_if_remove_l2_rule(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpdmux_l2_rule *rule) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_REMOVE_L2_RULE, ++ cmd_flags, ++ token); ++ DPDMUX_CMD_IF_REMOVE_L2_RULE(cmd, if_id, rule); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmux_if_add_l2_rule(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpdmux_l2_rule *rule) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_ADD_L2_RULE, ++ cmd_flags, ++ token); ++ DPDMUX_CMD_IF_ADD_L2_RULE(cmd, if_id, rule); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmux_if_get_counter(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ enum dpdmux_counter_type counter_type, ++ uint64_t *counter) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_GET_COUNTER, ++ cmd_flags, ++ token); ++ DPDMUX_CMD_IF_GET_COUNTER(cmd, if_id, counter_type); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDMUX_RSP_IF_GET_COUNTER(cmd, *counter); ++ ++ return 0; ++} ++ ++int dpdmux_if_set_link_cfg(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ struct dpdmux_link_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_SET_LINK_CFG, ++ cmd_flags, ++ token); ++ DPDMUX_CMD_IF_SET_LINK_CFG(cmd, if_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmux_if_get_link_state(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ struct dpdmux_link_state *state) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_GET_LINK_STATE, ++ cmd_flags, ++ token); ++ DPDMUX_CMD_IF_GET_LINK_STATE(cmd, if_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDMUX_RSP_IF_GET_LINK_STATE(cmd, state); ++ ++ return 0; ++} +diff --git a/drivers/net/dpaa2/mc/dpio.c b/drivers/net/dpaa2/mc/dpio.c +new file mode 100644 +index 0000000..f511e29 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/dpio.c +@@ -0,0 +1,468 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++#include ++#include ++ ++int dpio_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpio_id, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_OPEN, ++ cmd_flags, ++ 0); ++ DPIO_CMD_OPEN(cmd, dpio_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpio_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_CLOSE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpio_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpio_cfg *cfg, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_CREATE, ++ cmd_flags, ++ 0); ++ DPIO_CMD_CREATE(cmd, cfg); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpio_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_DESTROY, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpio_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_ENABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpio_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_DISABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpio_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_IS_ENABLED, cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPIO_RSP_IS_ENABLED(cmd, *en); ++ ++ return 0; ++} ++ ++int dpio_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_RESET, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpio_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpio_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_SET_IRQ, ++ cmd_flags, ++ token); ++ DPIO_CMD_SET_IRQ(cmd, irq_index, irq_cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpio_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpio_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_GET_IRQ, ++ cmd_flags, ++ token); ++ DPIO_CMD_GET_IRQ(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPIO_RSP_GET_IRQ(cmd, *type, irq_cfg); ++ ++ return 0; ++} ++ ++int dpio_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_SET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPIO_CMD_SET_IRQ_ENABLE(cmd, irq_index, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpio_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_GET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPIO_CMD_GET_IRQ_ENABLE(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPIO_RSP_GET_IRQ_ENABLE(cmd, *en); ++ ++ return 0; ++} ++ ++int dpio_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_SET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPIO_CMD_SET_IRQ_MASK(cmd, irq_index, mask); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpio_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_GET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPIO_CMD_GET_IRQ_MASK(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPIO_RSP_GET_IRQ_MASK(cmd, *mask); ++ ++ return 0; ++} ++ ++int dpio_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_GET_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPIO_CMD_GET_IRQ_STATUS(cmd, irq_index, *status); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPIO_RSP_GET_IRQ_STATUS(cmd, *status); ++ ++ return 0; ++} ++ ++int dpio_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_CLEAR_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPIO_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpio_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpio_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_GET_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPIO_RSP_GET_ATTR(cmd, attr); ++ ++ return 0; ++} ++ ++int dpio_set_stashing_destination(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t sdest) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_SET_STASHING_DEST, ++ cmd_flags, ++ token); ++ DPIO_CMD_SET_STASHING_DEST(cmd, sdest); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpio_get_stashing_destination(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t *sdest) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_GET_STASHING_DEST, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPIO_RSP_GET_STASHING_DEST(cmd, *sdest); ++ ++ return 0; ++} ++ ++int dpio_add_static_dequeue_channel(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpcon_id, ++ uint8_t *channel_index) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_ADD_STATIC_DEQUEUE_CHANNEL, ++ cmd_flags, ++ token); ++ DPIO_CMD_ADD_STATIC_DEQUEUE_CHANNEL(cmd, dpcon_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPIO_RSP_ADD_STATIC_DEQUEUE_CHANNEL(cmd, *channel_index); ++ ++ return 0; ++} ++ ++int dpio_remove_static_dequeue_channel(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpcon_id) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header( ++ DPIO_CMDID_REMOVE_STATIC_DEQUEUE_CHANNEL, ++ cmd_flags, ++ token); ++ DPIO_CMD_REMOVE_STATIC_DEQUEUE_CHANNEL(cmd, dpcon_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} +diff --git a/drivers/net/dpaa2/mc/dpmac.c b/drivers/net/dpaa2/mc/dpmac.c +new file mode 100644 +index 0000000..f31d949 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/dpmac.c +@@ -0,0 +1,422 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++#include ++#include ++ ++int dpmac_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpmac_id, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_OPEN, ++ cmd_flags, ++ 0); ++ DPMAC_CMD_OPEN(cmd, dpmac_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return err; ++} ++ ++int dpmac_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CLOSE, cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpmac_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpmac_cfg *cfg, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CREATE, ++ cmd_flags, ++ 0); ++ DPMAC_CMD_CREATE(cmd, cfg); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpmac_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_DESTROY, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpmac_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpmac_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_IRQ, ++ cmd_flags, ++ token); ++ DPMAC_CMD_SET_IRQ(cmd, irq_index, irq_cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpmac_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpmac_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_IRQ, ++ cmd_flags, ++ token); ++ DPMAC_CMD_GET_IRQ(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPMAC_RSP_GET_IRQ(cmd, *type, irq_cfg); ++ ++ return 0; ++} ++ ++int dpmac_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPMAC_CMD_SET_IRQ_ENABLE(cmd, irq_index, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpmac_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPMAC_CMD_GET_IRQ_ENABLE(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPMAC_RSP_GET_IRQ_ENABLE(cmd, *en); ++ ++ return 0; ++} ++ ++int dpmac_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPMAC_CMD_SET_IRQ_MASK(cmd, irq_index, mask); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpmac_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPMAC_CMD_GET_IRQ_MASK(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPMAC_RSP_GET_IRQ_MASK(cmd, *mask); ++ ++ return 0; ++} ++ ++int dpmac_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPMAC_CMD_GET_IRQ_STATUS(cmd, irq_index, *status); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPMAC_RSP_GET_IRQ_STATUS(cmd, *status); ++ ++ return 0; ++} ++ ++int dpmac_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CLEAR_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPMAC_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpmac_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpmac_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPMAC_RSP_GET_ATTRIBUTES(cmd, attr); ++ ++ return 0; ++} ++ ++int dpmac_mdio_read(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpmac_mdio_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_MDIO_READ, ++ cmd_flags, ++ token); ++ DPMAC_CMD_MDIO_READ(cmd, cfg); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPMAC_RSP_MDIO_READ(cmd, cfg->data); ++ ++ return 0; ++} ++ ++int dpmac_mdio_write(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpmac_mdio_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_MDIO_WRITE, ++ cmd_flags, ++ token); ++ DPMAC_CMD_MDIO_WRITE(cmd, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpmac_get_link_cfg(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpmac_link_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err = 0; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_LINK_CFG, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ DPMAC_RSP_GET_LINK_CFG(cmd, cfg); ++ ++ return 0; ++} ++ ++int dpmac_set_link_state(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpmac_link_state *link_state) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_LINK_STATE, ++ cmd_flags, ++ token); ++ DPMAC_CMD_SET_LINK_STATE(cmd, link_state); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpmac_get_counter(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ enum dpmac_counter type, ++ uint64_t *counter) ++{ ++ struct mc_command cmd = { 0 }; ++ int err = 0; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_COUNTER, ++ cmd_flags, ++ token); ++ DPMAC_CMD_GET_COUNTER(cmd, type); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ DPMAC_RSP_GET_COUNTER(cmd, *counter); ++ ++ return 0; ++} +diff --git a/drivers/net/dpaa2/mc/dpmcp.c b/drivers/net/dpaa2/mc/dpmcp.c +new file mode 100644 +index 0000000..dfd84b8 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/dpmcp.c +@@ -0,0 +1,312 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++#include ++#include ++ ++int dpmcp_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpmcp_id, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_OPEN, ++ cmd_flags, ++ 0); ++ DPMCP_CMD_OPEN(cmd, dpmcp_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return err; ++} ++ ++int dpmcp_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_CLOSE, cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpmcp_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpmcp_cfg *cfg, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_CREATE, ++ cmd_flags, ++ 0); ++ DPMCP_CMD_CREATE(cmd, cfg); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpmcp_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_DESTROY, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpmcp_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_RESET, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpmcp_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpmcp_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_SET_IRQ, ++ cmd_flags, ++ token); ++ DPMCP_CMD_SET_IRQ(cmd, irq_index, irq_cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpmcp_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpmcp_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_IRQ, ++ cmd_flags, ++ token); ++ DPMCP_CMD_GET_IRQ(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPMCP_RSP_GET_IRQ(cmd, *type, irq_cfg); ++ ++ return 0; ++} ++ ++int dpmcp_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_SET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPMCP_CMD_SET_IRQ_ENABLE(cmd, irq_index, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpmcp_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPMCP_CMD_GET_IRQ_ENABLE(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPMCP_RSP_GET_IRQ_ENABLE(cmd, *en); ++ ++ return 0; ++} ++ ++int dpmcp_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_SET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPMCP_CMD_SET_IRQ_MASK(cmd, irq_index, mask); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpmcp_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPMCP_CMD_GET_IRQ_MASK(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPMCP_RSP_GET_IRQ_MASK(cmd, *mask); ++ ++ return 0; ++} ++ ++int dpmcp_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPMCP_CMD_GET_IRQ_STATUS(cmd, irq_index, *status); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPMCP_RSP_GET_IRQ_STATUS(cmd, *status); ++ ++ return 0; ++} ++ ++int dpmcp_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpmcp_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPMCP_RSP_GET_ATTRIBUTES(cmd, attr); ++ ++ return 0; ++} +diff --git a/drivers/net/dpaa2/mc/dpmng.c b/drivers/net/dpaa2/mc/dpmng.c +new file mode 100644 +index 0000000..cac5ba5 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/dpmng.c +@@ -0,0 +1,58 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++#include ++#include ++ ++int mc_get_version(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ struct mc_version *mc_ver_info) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMNG_CMDID_GET_VERSION, ++ cmd_flags, ++ 0); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPMNG_RSP_GET_VERSION(cmd, mc_ver_info); ++ ++ return 0; ++} +diff --git a/drivers/net/dpaa2/mc/dpni.c b/drivers/net/dpaa2/mc/dpni.c +new file mode 100644 +index 0000000..cdd2f37 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/dpni.c +@@ -0,0 +1,1907 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++#include ++#include ++ ++int dpni_prepare_key_cfg(const struct dpkg_profile_cfg *cfg, ++ uint8_t *key_cfg_buf) ++{ ++ int i, j; ++ int offset = 0; ++ int param = 1; ++ uint64_t *params = (uint64_t *)key_cfg_buf; ++ ++ if (!key_cfg_buf || !cfg) ++ return -EINVAL; ++ ++ params[0] |= mc_enc(0, 8, cfg->num_extracts); ++ params[0] = cpu_to_le64(params[0]); ++ ++ if (cfg->num_extracts >= DPKG_MAX_NUM_OF_EXTRACTS) ++ return -EINVAL; ++ ++ for (i = 0; i < cfg->num_extracts; i++) { ++ switch (cfg->extracts[i].type) { ++ case DPKG_EXTRACT_FROM_HDR: ++ params[param] |= mc_enc(0, 8, ++ cfg->extracts[i].extract.from_hdr.prot); ++ params[param] |= mc_enc(8, 4, ++ cfg->extracts[i].extract.from_hdr.type); ++ params[param] |= mc_enc(16, 8, ++ cfg->extracts[i].extract.from_hdr.size); ++ params[param] |= mc_enc(24, 8, ++ cfg->extracts[i].extract. ++ from_hdr.offset); ++ params[param] |= mc_enc(32, 32, ++ cfg->extracts[i].extract. ++ from_hdr.field); ++ params[param] = cpu_to_le64(params[param]); ++ param++; ++ params[param] |= mc_enc(0, 8, ++ cfg->extracts[i].extract. ++ from_hdr.hdr_index); ++ break; ++ case DPKG_EXTRACT_FROM_DATA: ++ params[param] |= mc_enc(16, 8, ++ cfg->extracts[i].extract. ++ from_data.size); ++ params[param] |= mc_enc(24, 8, ++ cfg->extracts[i].extract. ++ from_data.offset); ++ params[param] = cpu_to_le64(params[param]); ++ param++; ++ break; ++ case DPKG_EXTRACT_FROM_PARSE: ++ params[param] |= mc_enc(16, 8, ++ cfg->extracts[i].extract. ++ from_parse.size); ++ params[param] |= mc_enc(24, 8, ++ cfg->extracts[i].extract. ++ from_parse.offset); ++ params[param] = cpu_to_le64(params[param]); ++ param++; ++ break; ++ default: ++ return -EINVAL; ++ } ++ params[param] |= mc_enc( ++ 24, 8, cfg->extracts[i].num_of_byte_masks); ++ params[param] |= mc_enc(32, 4, cfg->extracts[i].type); ++ params[param] = cpu_to_le64(params[param]); ++ param++; ++ for (offset = 0, j = 0; ++ j < DPKG_NUM_OF_MASKS; ++ offset += 16, j++) { ++ params[param] |= mc_enc( ++ (offset), 8, cfg->extracts[i].masks[j].mask); ++ params[param] |= mc_enc( ++ (offset + 8), 8, ++ cfg->extracts[i].masks[j].offset); ++ } ++ params[param] = cpu_to_le64(params[param]); ++ param++; ++ } ++ return 0; ++} ++ ++int dpni_prepare_extended_cfg(const struct dpni_extended_cfg *cfg, ++ uint8_t *ext_cfg_buf) ++{ ++ uint64_t *ext_params = (uint64_t *)ext_cfg_buf; ++ ++ DPNI_PREP_EXTENDED_CFG(ext_params, cfg); ++ ++ return 0; ++} ++ ++int dpni_extract_extended_cfg(struct dpni_extended_cfg *cfg, ++ const uint8_t *ext_cfg_buf) ++{ ++ const uint64_t *ext_params = (const uint64_t *)ext_cfg_buf; ++ ++ DPNI_EXT_EXTENDED_CFG(ext_params, cfg); ++ ++ return 0; ++} ++ ++int dpni_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpni_id, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_OPEN, ++ cmd_flags, ++ 0); ++ DPNI_CMD_OPEN(cmd, dpni_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpni_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_CLOSE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpni_cfg *cfg, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_CREATE, ++ cmd_flags, ++ 0); ++ DPNI_CMD_CREATE(cmd, cfg); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpni_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_DESTROY, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_set_pools(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_pools_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_POOLS, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_POOLS(cmd, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_ENABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_DISABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_IS_ENABLED, cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_IS_ENABLED(cmd, *en); ++ ++ return 0; ++} ++ ++int dpni_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_RESET, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpni_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_IRQ, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_IRQ(cmd, irq_index, irq_cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpni_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_IRQ, ++ cmd_flags, ++ token); ++ DPNI_CMD_GET_IRQ(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_IRQ(cmd, *type, irq_cfg); ++ ++ return 0; ++} ++ ++int dpni_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_IRQ_ENABLE(cmd, irq_index, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPNI_CMD_GET_IRQ_ENABLE(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_IRQ_ENABLE(cmd, *en); ++ ++ return 0; ++} ++ ++int dpni_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_IRQ_MASK(cmd, irq_index, mask); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPNI_CMD_GET_IRQ_MASK(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_IRQ_MASK(cmd, *mask); ++ ++ return 0; ++} ++ ++int dpni_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPNI_CMD_GET_IRQ_STATUS(cmd, irq_index, *status); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_IRQ_STATUS(cmd, *status); ++ ++ return 0; ++} ++ ++int dpni_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_CLEAR_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPNI_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpni_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_ATTR, ++ cmd_flags, ++ token); ++ DPNI_CMD_GET_ATTR(cmd, attr); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_ATTR(cmd, attr); ++ ++ return 0; ++} ++ ++int dpni_set_errors_behavior(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpni_error_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_ERRORS_BEHAVIOR, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_ERRORS_BEHAVIOR(cmd, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_rx_buffer_layout(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpni_buffer_layout *layout) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_RX_BUFFER_LAYOUT, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_RX_BUFFER_LAYOUT(cmd, layout); ++ ++ return 0; ++} ++ ++int dpni_set_rx_buffer_layout(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_buffer_layout *layout) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_RX_BUFFER_LAYOUT, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_RX_BUFFER_LAYOUT(cmd, layout); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_tx_buffer_layout(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpni_buffer_layout *layout) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_BUFFER_LAYOUT, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_TX_BUFFER_LAYOUT(cmd, layout); ++ ++ return 0; ++} ++ ++int dpni_set_tx_buffer_layout(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_buffer_layout *layout) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_BUFFER_LAYOUT, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_TX_BUFFER_LAYOUT(cmd, layout); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_tx_conf_buffer_layout(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpni_buffer_layout *layout) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_CONF_BUFFER_LAYOUT, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_TX_CONF_BUFFER_LAYOUT(cmd, layout); ++ ++ return 0; ++} ++ ++int dpni_set_tx_conf_buffer_layout(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_buffer_layout *layout) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_CONF_BUFFER_LAYOUT, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_TX_CONF_BUFFER_LAYOUT(cmd, layout); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_l3_chksum_validation(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_L3_CHKSUM_VALIDATION, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_L3_CHKSUM_VALIDATION(cmd, *en); ++ ++ return 0; ++} ++ ++int dpni_set_l3_chksum_validation(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_L3_CHKSUM_VALIDATION, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_L3_CHKSUM_VALIDATION(cmd, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_l4_chksum_validation(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_L4_CHKSUM_VALIDATION, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_L4_CHKSUM_VALIDATION(cmd, *en); ++ ++ return 0; ++} ++ ++int dpni_set_l4_chksum_validation(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_L4_CHKSUM_VALIDATION, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_L4_CHKSUM_VALIDATION(cmd, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_qdid(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t *qdid) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_QDID, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_QDID(cmd, *qdid); ++ ++ return 0; ++} ++ ++int dpni_get_sp_info(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpni_sp_info *sp_info) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_SP_INFO, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_SP_INFO(cmd, sp_info); ++ ++ return 0; ++} ++ ++int dpni_get_tx_data_offset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t *data_offset) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_DATA_OFFSET, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_TX_DATA_OFFSET(cmd, *data_offset); ++ ++ return 0; ++} ++ ++int dpni_get_counter(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ enum dpni_counter counter, ++ uint64_t *value) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_COUNTER, ++ cmd_flags, ++ token); ++ DPNI_CMD_GET_COUNTER(cmd, counter); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_COUNTER(cmd, *value); ++ ++ return 0; ++} ++ ++int dpni_set_counter(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ enum dpni_counter counter, ++ uint64_t value) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_COUNTER, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_COUNTER(cmd, counter, value); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_set_link_cfg(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_link_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_LINK_CFG, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_LINK_CFG(cmd, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_link_state(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpni_link_state *state) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_LINK_STATE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_LINK_STATE(cmd, state); ++ ++ return 0; ++} ++ ++int dpni_set_tx_shaping(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_tx_shaping_cfg *tx_shaper) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_SHAPING, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_TX_SHAPING(cmd, tx_shaper); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_set_max_frame_length(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t max_frame_length) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_MAX_FRAME_LENGTH, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_MAX_FRAME_LENGTH(cmd, max_frame_length); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_max_frame_length(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t *max_frame_length) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_MAX_FRAME_LENGTH, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_MAX_FRAME_LENGTH(cmd, *max_frame_length); ++ ++ return 0; ++} ++ ++int dpni_set_mtu(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t mtu) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_MTU, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_MTU(cmd, mtu); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_mtu(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t *mtu) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_MTU, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_MTU(cmd, *mtu); ++ ++ return 0; ++} ++ ++int dpni_set_multicast_promisc(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_MCAST_PROMISC, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_MULTICAST_PROMISC(cmd, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_multicast_promisc(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_MCAST_PROMISC, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_MULTICAST_PROMISC(cmd, *en); ++ ++ return 0; ++} ++ ++int dpni_set_unicast_promisc(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_UNICAST_PROMISC, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_UNICAST_PROMISC(cmd, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_unicast_promisc(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_UNICAST_PROMISC, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_UNICAST_PROMISC(cmd, *en); ++ ++ return 0; ++} ++ ++int dpni_set_primary_mac_addr(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const uint8_t mac_addr[6]) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_PRIM_MAC, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_PRIMARY_MAC_ADDR(cmd, mac_addr); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_primary_mac_addr(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t mac_addr[6]) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_PRIM_MAC, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_PRIMARY_MAC_ADDR(cmd, mac_addr); ++ ++ return 0; ++} ++ ++int dpni_add_mac_addr(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const uint8_t mac_addr[6]) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_ADD_MAC_ADDR, ++ cmd_flags, ++ token); ++ DPNI_CMD_ADD_MAC_ADDR(cmd, mac_addr); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_remove_mac_addr(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const uint8_t mac_addr[6]) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_REMOVE_MAC_ADDR, ++ cmd_flags, ++ token); ++ DPNI_CMD_REMOVE_MAC_ADDR(cmd, mac_addr); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_clear_mac_filters(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int unicast, ++ int multicast) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_CLR_MAC_FILTERS, ++ cmd_flags, ++ token); ++ DPNI_CMD_CLEAR_MAC_FILTERS(cmd, unicast, multicast); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_set_vlan_filters(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_VLAN_FILTERS, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_VLAN_FILTERS(cmd, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_add_vlan_id(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_ADD_VLAN_ID, ++ cmd_flags, ++ token); ++ DPNI_CMD_ADD_VLAN_ID(cmd, vlan_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_remove_vlan_id(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_REMOVE_VLAN_ID, ++ cmd_flags, ++ token); ++ DPNI_CMD_REMOVE_VLAN_ID(cmd, vlan_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_clear_vlan_filters(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_CLR_VLAN_FILTERS, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_set_tx_selection(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_tx_selection_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_SELECTION, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_TX_SELECTION(cmd, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_set_rx_tc_dist(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ const struct dpni_rx_tc_dist_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_RX_TC_DIST, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_RX_TC_DIST(cmd, tc_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_set_tx_flow(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t *flow_id, ++ const struct dpni_tx_flow_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_FLOW, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_TX_FLOW(cmd, *flow_id, cfg); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_SET_TX_FLOW(cmd, *flow_id); ++ ++ return 0; ++} ++ ++int dpni_get_tx_flow(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t flow_id, ++ struct dpni_tx_flow_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_FLOW, ++ cmd_flags, ++ token); ++ DPNI_CMD_GET_TX_FLOW(cmd, flow_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_TX_FLOW(cmd, attr); ++ ++ return 0; ++} ++ ++int dpni_set_rx_flow(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ uint16_t flow_id, ++ const struct dpni_queue_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_RX_FLOW, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_RX_FLOW(cmd, tc_id, flow_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_rx_flow(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ uint16_t flow_id, ++ struct dpni_queue_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_RX_FLOW, ++ cmd_flags, ++ token); ++ DPNI_CMD_GET_RX_FLOW(cmd, tc_id, flow_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_RX_FLOW(cmd, attr); ++ ++ return 0; ++} ++ ++int dpni_set_rx_err_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_queue_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_RX_ERR_QUEUE, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_RX_ERR_QUEUE(cmd, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_rx_err_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpni_queue_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_RX_ERR_QUEUE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_RX_ERR_QUEUE(cmd, attr); ++ ++ return 0; ++} ++ ++int dpni_set_tx_conf_revoke(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int revoke) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_CONF_REVOKE, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_TX_CONF_REVOKE(cmd, revoke); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_set_qos_table(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_qos_tbl_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_QOS_TBL, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_QOS_TABLE(cmd, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_add_qos_entry(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_rule_cfg *cfg, ++ uint8_t tc_id) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_ADD_QOS_ENT, ++ cmd_flags, ++ token); ++ DPNI_CMD_ADD_QOS_ENTRY(cmd, cfg, tc_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_remove_qos_entry(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_rule_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_REMOVE_QOS_ENT, ++ cmd_flags, ++ token); ++ DPNI_CMD_REMOVE_QOS_ENTRY(cmd, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_clear_qos_table(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_CLR_QOS_TBL, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_add_fs_entry(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ const struct dpni_rule_cfg *cfg, ++ uint16_t flow_id) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_ADD_FS_ENT, ++ cmd_flags, ++ token); ++ DPNI_CMD_ADD_FS_ENTRY(cmd, tc_id, cfg, flow_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_remove_fs_entry(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ const struct dpni_rule_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_REMOVE_FS_ENT, ++ cmd_flags, ++ token); ++ DPNI_CMD_REMOVE_FS_ENTRY(cmd, tc_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_clear_fs_entries(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_CLR_FS_ENT, ++ cmd_flags, ++ token); ++ DPNI_CMD_CLEAR_FS_ENTRIES(cmd, tc_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_set_vlan_insertion(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_VLAN_INSERTION, ++ cmd_flags, token); ++ DPNI_CMD_SET_VLAN_INSERTION(cmd, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_set_vlan_removal(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_VLAN_REMOVAL, ++ cmd_flags, token); ++ DPNI_CMD_SET_VLAN_REMOVAL(cmd, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_set_ipr(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_IPR, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_IPR(cmd, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_set_ipf(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_IPF, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_IPF(cmd, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_set_rx_tc_policing(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ const struct dpni_rx_tc_policing_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_RX_TC_POLICING, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_RX_TC_POLICING(cmd, tc_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_rx_tc_policing(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ struct dpni_rx_tc_policing_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_RX_TC_POLICING, ++ cmd_flags, ++ token); ++ DPNI_CMD_GET_RX_TC_POLICING(cmd, tc_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ DPNI_RSP_GET_RX_TC_POLICING(cmd, cfg); ++ ++ return 0; ++} ++ ++void dpni_prepare_early_drop(const struct dpni_early_drop_cfg *cfg, ++ uint8_t *early_drop_buf) ++{ ++ uint64_t *ext_params = (uint64_t *)early_drop_buf; ++ ++ DPNI_PREP_EARLY_DROP(ext_params, cfg); ++} ++ ++void dpni_extract_early_drop(struct dpni_early_drop_cfg *cfg, ++ const uint8_t *early_drop_buf) ++{ ++ const uint64_t *ext_params = (const uint64_t *)early_drop_buf; ++ ++ DPNI_EXT_EARLY_DROP(ext_params, cfg); ++} ++ ++int dpni_set_rx_tc_early_drop(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ uint64_t early_drop_iova) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_RX_TC_EARLY_DROP, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_RX_TC_EARLY_DROP(cmd, tc_id, early_drop_iova); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_rx_tc_early_drop(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ uint64_t early_drop_iova) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_RX_TC_EARLY_DROP, ++ cmd_flags, ++ token); ++ DPNI_CMD_GET_RX_TC_EARLY_DROP(cmd, tc_id, early_drop_iova); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_set_tx_tc_early_drop(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ uint64_t early_drop_iova) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_TC_EARLY_DROP, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_TX_TC_EARLY_DROP(cmd, tc_id, early_drop_iova); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_tx_tc_early_drop(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ uint64_t early_drop_iova) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_TC_EARLY_DROP, ++ cmd_flags, ++ token); ++ DPNI_CMD_GET_TX_TC_EARLY_DROP(cmd, tc_id, early_drop_iova); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_set_rx_tc_congestion_notification(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ const struct dpni_congestion_notification_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header( ++ DPNI_CMDID_SET_RX_TC_CONGESTION_NOTIFICATION, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_RX_TC_CONGESTION_NOTIFICATION(cmd, tc_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_rx_tc_congestion_notification(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ struct dpni_congestion_notification_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header( ++ DPNI_CMDID_GET_RX_TC_CONGESTION_NOTIFICATION, ++ cmd_flags, ++ token); ++ DPNI_CMD_GET_RX_TC_CONGESTION_NOTIFICATION(cmd, tc_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ DPNI_RSP_GET_RX_TC_CONGESTION_NOTIFICATION(cmd, cfg); ++ ++ return 0; ++} ++ ++int dpni_set_tx_tc_congestion_notification(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ const struct dpni_congestion_notification_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header( ++ DPNI_CMDID_SET_TX_TC_CONGESTION_NOTIFICATION, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_TX_TC_CONGESTION_NOTIFICATION(cmd, tc_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_tx_tc_congestion_notification(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ struct dpni_congestion_notification_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header( ++ DPNI_CMDID_GET_TX_TC_CONGESTION_NOTIFICATION, ++ cmd_flags, ++ token); ++ DPNI_CMD_GET_TX_TC_CONGESTION_NOTIFICATION(cmd, tc_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ DPNI_RSP_GET_TX_TC_CONGESTION_NOTIFICATION(cmd, cfg); ++ ++ return 0; ++} ++ ++int dpni_set_tx_conf(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t flow_id, ++ const struct dpni_tx_conf_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_CONF, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_TX_CONF(cmd, flow_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_tx_conf(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t flow_id, ++ struct dpni_tx_conf_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_CONF, ++ cmd_flags, ++ token); ++ DPNI_CMD_GET_TX_CONF(cmd, flow_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ DPNI_RSP_GET_TX_CONF(cmd, attr); ++ ++ return 0; ++} ++ ++int dpni_set_tx_conf_congestion_notification(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t flow_id, ++ const struct dpni_congestion_notification_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header( ++ DPNI_CMDID_SET_TX_CONF_CONGESTION_NOTIFICATION, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_TX_CONF_CONGESTION_NOTIFICATION(cmd, flow_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_tx_conf_congestion_notification(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t flow_id, ++ struct dpni_congestion_notification_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header( ++ DPNI_CMDID_GET_TX_CONF_CONGESTION_NOTIFICATION, ++ cmd_flags, ++ token); ++ DPNI_CMD_GET_TX_CONF_CONGESTION_NOTIFICATION(cmd, flow_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ DPNI_RSP_GET_TX_CONF_CONGESTION_NOTIFICATION(cmd, cfg); ++ ++ return 0; ++} +diff --git a/drivers/net/dpaa2/mc/dprc.c b/drivers/net/dpaa2/mc/dprc.c +new file mode 100644 +index 0000000..75c6a68 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/dprc.c +@@ -0,0 +1,786 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++#include ++#include ++ ++int dprc_get_container_id(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int *container_id) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_CONT_ID, ++ cmd_flags, ++ 0); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRC_RSP_GET_CONTAINER_ID(cmd, *container_id); ++ ++ return 0; ++} ++ ++int dprc_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int container_id, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_OPEN, cmd_flags, ++ 0); ++ DPRC_CMD_OPEN(cmd, container_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dprc_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLOSE, cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprc_create_container(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dprc_cfg *cfg, ++ int *child_container_id, ++ uint64_t *child_portal_paddr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ DPRC_CMD_CREATE_CONTAINER(cmd, cfg); ++ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_CREATE_CONT, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRC_RSP_CREATE_CONTAINER(cmd, *child_container_id, ++ *child_portal_paddr); ++ ++ return 0; ++} ++ ++int dprc_destroy_container(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int child_container_id) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_DESTROY_CONT, ++ cmd_flags, ++ token); ++ DPRC_CMD_DESTROY_CONTAINER(cmd, child_container_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprc_reset_container(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int child_container_id) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_RESET_CONT, ++ cmd_flags, ++ token); ++ DPRC_CMD_RESET_CONTAINER(cmd, child_container_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprc_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dprc_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ, ++ cmd_flags, ++ token); ++ DPRC_CMD_GET_IRQ(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRC_RSP_GET_IRQ(cmd, *type, irq_cfg); ++ ++ return 0; ++} ++ ++int dprc_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dprc_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ, ++ cmd_flags, ++ token); ++ DPRC_CMD_SET_IRQ(cmd, irq_index, irq_cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprc_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPRC_CMD_GET_IRQ_ENABLE(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRC_RSP_GET_IRQ_ENABLE(cmd, *en); ++ ++ return 0; ++} ++ ++int dprc_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPRC_CMD_SET_IRQ_ENABLE(cmd, irq_index, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprc_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPRC_CMD_GET_IRQ_MASK(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRC_RSP_GET_IRQ_MASK(cmd, *mask); ++ ++ return 0; ++} ++ ++int dprc_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPRC_CMD_SET_IRQ_MASK(cmd, irq_index, mask); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprc_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPRC_CMD_GET_IRQ_STATUS(cmd, irq_index, *status); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRC_RSP_GET_IRQ_STATUS(cmd, *status); ++ ++ return 0; ++} ++ ++int dprc_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLEAR_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPRC_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprc_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dprc_attributes *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRC_RSP_GET_ATTRIBUTES(cmd, attr); ++ ++ return 0; ++} ++ ++int dprc_set_res_quota(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int child_container_id, ++ char *type, ++ uint16_t quota) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_RES_QUOTA, ++ cmd_flags, ++ token); ++ DPRC_CMD_SET_RES_QUOTA(cmd, child_container_id, type, quota); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprc_get_res_quota(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int child_container_id, ++ char *type, ++ uint16_t *quota) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_RES_QUOTA, ++ cmd_flags, ++ token); ++ DPRC_CMD_GET_RES_QUOTA(cmd, child_container_id, type); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRC_RSP_GET_RES_QUOTA(cmd, *quota); ++ ++ return 0; ++} ++ ++int dprc_assign(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int container_id, ++ struct dprc_res_req *res_req) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_ASSIGN, ++ cmd_flags, ++ token); ++ DPRC_CMD_ASSIGN(cmd, container_id, res_req); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprc_unassign(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int child_container_id, ++ struct dprc_res_req *res_req) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_UNASSIGN, ++ cmd_flags, ++ token); ++ DPRC_CMD_UNASSIGN(cmd, child_container_id, res_req); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprc_get_pool_count(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *pool_count) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_POOL_COUNT, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRC_RSP_GET_POOL_COUNT(cmd, *pool_count); ++ ++ return 0; ++} ++ ++int dprc_get_pool(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int pool_index, ++ char *type) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_POOL, ++ cmd_flags, ++ token); ++ DPRC_CMD_GET_POOL(cmd, pool_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRC_RSP_GET_POOL(cmd, type); ++ ++ return 0; ++} ++ ++int dprc_get_obj_count(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *obj_count) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_COUNT, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRC_RSP_GET_OBJ_COUNT(cmd, *obj_count); ++ ++ return 0; ++} ++ ++int dprc_get_obj(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int obj_index, ++ struct dprc_obj_desc *obj_desc) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ, ++ cmd_flags, ++ token); ++ DPRC_CMD_GET_OBJ(cmd, obj_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRC_RSP_GET_OBJ(cmd, obj_desc); ++ ++ return 0; ++} ++ ++int dprc_get_obj_desc(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ char *obj_type, ++ int obj_id, ++ struct dprc_obj_desc *obj_desc) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_DESC, ++ cmd_flags, ++ token); ++ DPRC_CMD_GET_OBJ_DESC(cmd, obj_type, obj_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRC_RSP_GET_OBJ_DESC(cmd, obj_desc); ++ ++ return 0; ++} ++ ++int dprc_set_obj_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ char *obj_type, ++ int obj_id, ++ uint8_t irq_index, ++ struct dprc_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_OBJ_IRQ, ++ cmd_flags, ++ token); ++ DPRC_CMD_SET_OBJ_IRQ(cmd, ++ obj_type, ++ obj_id, ++ irq_index, ++ irq_cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprc_get_obj_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ char *obj_type, ++ int obj_id, ++ uint8_t irq_index, ++ int *type, ++ struct dprc_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_IRQ, ++ cmd_flags, ++ token); ++ DPRC_CMD_GET_OBJ_IRQ(cmd, obj_type, obj_id, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRC_RSP_GET_OBJ_IRQ(cmd, *type, irq_cfg); ++ ++ return 0; ++} ++ ++int dprc_get_res_count(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ char *type, ++ int *res_count) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ *res_count = 0; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_RES_COUNT, ++ cmd_flags, ++ token); ++ DPRC_CMD_GET_RES_COUNT(cmd, type); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRC_RSP_GET_RES_COUNT(cmd, *res_count); ++ ++ return 0; ++} ++ ++int dprc_get_res_ids(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ char *type, ++ struct dprc_res_ids_range_desc *range_desc) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_RES_IDS, ++ cmd_flags, ++ token); ++ DPRC_CMD_GET_RES_IDS(cmd, range_desc, type); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRC_RSP_GET_RES_IDS(cmd, range_desc); ++ ++ return 0; ++} ++ ++int dprc_get_obj_region(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ char *obj_type, ++ int obj_id, ++ uint8_t region_index, ++ struct dprc_region_desc *region_desc) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_REG, ++ cmd_flags, ++ token); ++ DPRC_CMD_GET_OBJ_REGION(cmd, obj_type, obj_id, region_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRC_RSP_GET_OBJ_REGION(cmd, region_desc); ++ ++ return 0; ++} ++ ++int dprc_set_obj_label(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ char *obj_type, ++ int obj_id, ++ char *label) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_OBJ_LABEL, ++ cmd_flags, ++ token); ++ DPRC_CMD_SET_OBJ_LABEL(cmd, obj_type, obj_id, label); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprc_connect(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dprc_endpoint *endpoint1, ++ const struct dprc_endpoint *endpoint2, ++ const struct dprc_connection_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_CONNECT, ++ cmd_flags, ++ token); ++ DPRC_CMD_CONNECT(cmd, endpoint1, endpoint2, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprc_disconnect(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dprc_endpoint *endpoint) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_DISCONNECT, ++ cmd_flags, ++ token); ++ DPRC_CMD_DISCONNECT(cmd, endpoint); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprc_get_connection(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dprc_endpoint *endpoint1, ++ struct dprc_endpoint *endpoint2, ++ int *state) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_CONNECTION, ++ cmd_flags, ++ token); ++ DPRC_CMD_GET_CONNECTION(cmd, endpoint1); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRC_RSP_GET_CONNECTION(cmd, endpoint2, *state); ++ ++ return 0; ++} +diff --git a/drivers/net/dpaa2/mc/dprtc.c b/drivers/net/dpaa2/mc/dprtc.c +new file mode 100644 +index 0000000..73667af +--- /dev/null ++++ b/drivers/net/dpaa2/mc/dprtc.c +@@ -0,0 +1,509 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++#include ++#include ++ ++int dprtc_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dprtc_id, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_OPEN, ++ cmd_flags, ++ 0); ++ DPRTC_CMD_OPEN(cmd, dprtc_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return err; ++} ++ ++int dprtc_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_CLOSE, cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprtc_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dprtc_cfg *cfg, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ (void)(cfg); /* unused */ ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_CREATE, ++ cmd_flags, ++ 0); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dprtc_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_DESTROY, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprtc_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_ENABLE, cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprtc_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_DISABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprtc_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_IS_ENABLED, cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRTC_RSP_IS_ENABLED(cmd, *en); ++ ++ return 0; ++} ++ ++int dprtc_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_RESET, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprtc_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dprtc_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_SET_IRQ, ++ cmd_flags, ++ token); ++ ++ DPRTC_CMD_SET_IRQ(cmd, irq_index, irq_cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprtc_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dprtc_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_GET_IRQ, ++ cmd_flags, ++ token); ++ ++ DPRTC_CMD_GET_IRQ(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRTC_RSP_GET_IRQ(cmd, *type, irq_cfg); ++ ++ return 0; ++} ++ ++int dprtc_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_SET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ ++ DPRTC_CMD_SET_IRQ_ENABLE(cmd, irq_index, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprtc_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_GET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ ++ DPRTC_CMD_GET_IRQ_ENABLE(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRTC_RSP_GET_IRQ_ENABLE(cmd, *en); ++ ++ return 0; ++} ++ ++int dprtc_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_SET_IRQ_MASK, ++ cmd_flags, ++ token); ++ ++ DPRTC_CMD_SET_IRQ_MASK(cmd, irq_index, mask); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprtc_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_GET_IRQ_MASK, ++ cmd_flags, ++ token); ++ ++ DPRTC_CMD_GET_IRQ_MASK(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRTC_RSP_GET_IRQ_MASK(cmd, *mask); ++ ++ return 0; ++} ++ ++int dprtc_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_GET_IRQ_STATUS, ++ cmd_flags, ++ token); ++ ++ DPRTC_CMD_GET_IRQ_STATUS(cmd, irq_index, *status); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRTC_RSP_GET_IRQ_STATUS(cmd, *status); ++ ++ return 0; ++} ++ ++int dprtc_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_CLEAR_IRQ_STATUS, ++ cmd_flags, ++ token); ++ ++ DPRTC_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprtc_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dprtc_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_GET_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRTC_RSP_GET_ATTRIBUTES(cmd, attr); ++ ++ return 0; ++} ++ ++int dprtc_set_clock_offset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int64_t offset) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_SET_CLOCK_OFFSET, ++ cmd_flags, ++ token); ++ ++ DPRTC_CMD_SET_CLOCK_OFFSET(cmd, offset); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprtc_set_freq_compensation(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint32_t freq_compensation) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_SET_FREQ_COMPENSATION, ++ cmd_flags, ++ token); ++ ++ DPRTC_CMD_SET_FREQ_COMPENSATION(cmd, freq_compensation); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprtc_get_freq_compensation(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint32_t *freq_compensation) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_GET_FREQ_COMPENSATION, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRTC_RSP_GET_FREQ_COMPENSATION(cmd, *freq_compensation); ++ ++ return 0; ++} ++ ++int dprtc_get_time(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint64_t *time) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_GET_TIME, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRTC_RSP_GET_TIME(cmd, *time); ++ ++ return 0; ++} ++ ++int dprtc_set_time(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint64_t time) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_SET_TIME, ++ cmd_flags, ++ token); ++ ++ DPRTC_CMD_SET_TIME(cmd, time); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprtc_set_alarm(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, uint64_t time) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_SET_ALARM, ++ cmd_flags, ++ token); ++ ++ DPRTC_CMD_SET_ALARM(cmd, time); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} +diff --git a/drivers/net/dpaa2/mc/dpseci.c b/drivers/net/dpaa2/mc/dpseci.c +new file mode 100644 +index 0000000..a4b932a +--- /dev/null ++++ b/drivers/net/dpaa2/mc/dpseci.c +@@ -0,0 +1,502 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++#include ++#include ++ ++int dpseci_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpseci_id, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_OPEN, ++ cmd_flags, ++ 0); ++ DPSECI_CMD_OPEN(cmd, dpseci_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpseci_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_CLOSE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpseci_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpseci_cfg *cfg, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_CREATE, ++ cmd_flags, ++ 0); ++ DPSECI_CMD_CREATE(cmd, cfg); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpseci_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_DESTROY, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpseci_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_ENABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpseci_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_DISABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpseci_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_IS_ENABLED, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSECI_RSP_IS_ENABLED(cmd, *en); ++ ++ return 0; ++} ++ ++int dpseci_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_RESET, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpseci_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpseci_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_GET_IRQ, ++ cmd_flags, ++ token); ++ DPSECI_CMD_GET_IRQ(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSECI_RSP_GET_IRQ(cmd, *type, irq_cfg); ++ ++ return 0; ++} ++ ++int dpseci_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpseci_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_SET_IRQ, ++ cmd_flags, ++ token); ++ DPSECI_CMD_SET_IRQ(cmd, irq_index, irq_cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpseci_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_GET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPSECI_CMD_GET_IRQ_ENABLE(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSECI_RSP_GET_IRQ_ENABLE(cmd, *en); ++ ++ return 0; ++} ++ ++int dpseci_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_SET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPSECI_CMD_SET_IRQ_ENABLE(cmd, irq_index, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpseci_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_GET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPSECI_CMD_GET_IRQ_MASK(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSECI_RSP_GET_IRQ_MASK(cmd, *mask); ++ ++ return 0; ++} ++ ++int dpseci_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_SET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPSECI_CMD_SET_IRQ_MASK(cmd, irq_index, mask); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpseci_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_GET_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPSECI_CMD_GET_IRQ_STATUS(cmd, irq_index, *status); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSECI_RSP_GET_IRQ_STATUS(cmd, *status); ++ ++ return 0; ++} ++ ++int dpseci_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_CLEAR_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPSECI_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpseci_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpseci_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_GET_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSECI_RSP_GET_ATTR(cmd, attr); ++ ++ return 0; ++} ++ ++int dpseci_set_rx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t queue, ++ const struct dpseci_rx_queue_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_SET_RX_QUEUE, ++ cmd_flags, ++ token); ++ DPSECI_CMD_SET_RX_QUEUE(cmd, queue, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpseci_get_rx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t queue, ++ struct dpseci_rx_queue_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_GET_RX_QUEUE, ++ cmd_flags, ++ token); ++ DPSECI_CMD_GET_RX_QUEUE(cmd, queue); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSECI_RSP_GET_RX_QUEUE(cmd, attr); ++ ++ return 0; ++} ++ ++int dpseci_get_tx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t queue, ++ struct dpseci_tx_queue_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_GET_TX_QUEUE, ++ cmd_flags, ++ token); ++ DPSECI_CMD_GET_TX_QUEUE(cmd, queue); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSECI_RSP_GET_TX_QUEUE(cmd, attr); ++ ++ return 0; ++} ++ ++int dpseci_get_sec_attr(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpseci_sec_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_GET_SEC_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSECI_RSP_GET_SEC_ATTR(cmd, attr); ++ ++ return 0; ++} ++ ++int dpseci_get_sec_counters(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpseci_sec_counters *counters) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_GET_SEC_COUNTERS, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSECI_RSP_GET_SEC_COUNTERS(cmd, counters); ++ ++ return 0; ++} +diff --git a/drivers/net/dpaa2/mc/dpsw.c b/drivers/net/dpaa2/mc/dpsw.c +new file mode 100644 +index 0000000..2034b55 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/dpsw.c +@@ -0,0 +1,1639 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++#include ++#include ++ ++/* internal functions */ ++static void build_if_id_bitmap(const uint16_t *if_id, ++ const uint16_t num_ifs, ++ struct mc_command *cmd, ++ int start_param) ++{ ++ int i; ++ ++ for (i = 0; (i < num_ifs) && (i < DPSW_MAX_IF); i++) ++ cmd->params[start_param + (if_id[i] / 64)] |= mc_enc( ++ (if_id[i] % 64), 1, 1); ++} ++ ++static int read_if_id_bitmap(uint16_t *if_id, ++ uint16_t *num_ifs, ++ struct mc_command *cmd, ++ int start_param) ++{ ++ int bitmap[DPSW_MAX_IF] = { 0 }; ++ int i, j = 0; ++ int count = 0; ++ ++ for (i = 0; i < DPSW_MAX_IF; i++) { ++ bitmap[i] = (int)mc_dec(cmd->params[start_param + i / 64], ++ i % 64, 1); ++ count += bitmap[i]; ++ } ++ ++ *num_ifs = (uint16_t)count; ++ ++ for (i = 0; (i < DPSW_MAX_IF) && (j < count); i++) { ++ if (bitmap[i]) { ++ if_id[j] = (uint16_t)i; ++ j++; ++ } ++ } ++ ++ return 0; ++} ++ ++/* DPSW APIs */ ++int dpsw_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpsw_id, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_OPEN, ++ cmd_flags, ++ 0); ++ DPSW_CMD_OPEN(cmd, dpsw_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpsw_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_CLOSE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpsw_cfg *cfg, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_CREATE, ++ cmd_flags, ++ 0); ++ DPSW_CMD_CREATE(cmd, cfg); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpsw_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_DESTROY, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_ENABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_DISABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IS_ENABLED, cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_IS_ENABLED(cmd, *en); ++ ++ return 0; ++} ++ ++int dpsw_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_RESET, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpsw_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_SET_IRQ, ++ cmd_flags, ++ token); ++ DPSW_CMD_SET_IRQ(cmd, irq_index, irq_cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpsw_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_GET_IRQ, ++ cmd_flags, ++ token); ++ DPSW_CMD_GET_IRQ(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_GET_IRQ(cmd, *type, irq_cfg); ++ ++ return 0; ++} ++ ++int dpsw_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_SET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPSW_CMD_SET_IRQ_ENABLE(cmd, irq_index, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_GET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPSW_CMD_GET_IRQ_ENABLE(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_GET_IRQ_ENABLE(cmd, *en); ++ ++ return 0; ++} ++ ++int dpsw_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_SET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPSW_CMD_SET_IRQ_MASK(cmd, irq_index, mask); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_GET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPSW_CMD_GET_IRQ_MASK(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_GET_IRQ_MASK(cmd, *mask); ++ ++ return 0; ++} ++ ++int dpsw_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_GET_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPSW_CMD_GET_IRQ_STATUS(cmd, irq_index, *status); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_GET_IRQ_STATUS(cmd, *status); ++ ++ return 0; ++} ++ ++int dpsw_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_CLEAR_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPSW_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpsw_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_GET_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_GET_ATTR(cmd, attr); ++ ++ return 0; ++} ++ ++int dpsw_set_reflection_if(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_SET_REFLECTION_IF, ++ cmd_flags, ++ token); ++ DPSW_CMD_SET_REFLECTION_IF(cmd, if_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_if_set_link_cfg(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ struct dpsw_link_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_LINK_CFG, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_SET_LINK_CFG(cmd, if_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_if_get_link_state(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ struct dpsw_link_state *state) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_GET_LINK_STATE, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_GET_LINK_STATE(cmd, if_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_IF_GET_LINK_STATE(cmd, state); ++ ++ return 0; ++} ++ ++int dpsw_if_set_flooding(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ int en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_FLOODING, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_SET_FLOODING(cmd, if_id, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_if_set_broadcast(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ int en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_BROADCAST, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_SET_FLOODING(cmd, if_id, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_if_set_multicast(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ int en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_MULTICAST, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_SET_FLOODING(cmd, if_id, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_if_set_tci(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpsw_tci_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_TCI, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_SET_TCI(cmd, if_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_if_get_tci(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ struct dpsw_tci_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err = 0; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_GET_TCI, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_GET_TCI(cmd, if_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_IF_GET_TCI(cmd, cfg); ++ ++ return 0; ++} ++ ++int dpsw_if_set_stp(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpsw_stp_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_STP, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_SET_STP(cmd, if_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_if_set_accepted_frames(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpsw_accepted_frames_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_ACCEPTED_FRAMES, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_SET_ACCEPTED_FRAMES(cmd, if_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_if_set_accept_all_vlan(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ int accept_all) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_SET_IF_ACCEPT_ALL_VLAN, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_SET_ACCEPT_ALL_VLAN(cmd, if_id, accept_all); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_if_get_counter(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ enum dpsw_counter type, ++ uint64_t *counter) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_GET_COUNTER, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_GET_COUNTER(cmd, if_id, type); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_IF_GET_COUNTER(cmd, *counter); ++ ++ return 0; ++} ++ ++int dpsw_if_set_counter(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ enum dpsw_counter type, ++ uint64_t counter) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_COUNTER, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_SET_COUNTER(cmd, if_id, type, counter); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_if_set_tx_selection(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpsw_tx_selection_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_TX_SELECTION, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_SET_TX_SELECTION(cmd, if_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_if_add_reflection(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpsw_reflection_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_ADD_REFLECTION, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_ADD_REFLECTION(cmd, if_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_if_remove_reflection(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpsw_reflection_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_REMOVE_REFLECTION, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_REMOVE_REFLECTION(cmd, if_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_if_set_flooding_metering(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpsw_metering_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_FLOODING_METERING, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_SET_FLOODING_METERING(cmd, if_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_if_set_metering(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ uint8_t tc_id, ++ const struct dpsw_metering_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_METERING, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_SET_METERING(cmd, if_id, tc_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++void dpsw_prepare_early_drop(const struct dpsw_early_drop_cfg *cfg, ++ uint8_t *early_drop_buf) ++{ ++ uint64_t *ext_params = (uint64_t *)early_drop_buf; ++ ++ DPSW_PREP_EARLY_DROP(ext_params, cfg); ++} ++ ++int dpsw_if_set_early_drop(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ uint8_t tc_id, ++ uint64_t early_drop_iova) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_EARLY_DROP, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_SET_EARLY_DROP(cmd, if_id, tc_id, early_drop_iova); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_add_custom_tpid(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpsw_custom_tpid_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_ADD_CUSTOM_TPID, ++ cmd_flags, ++ token); ++ DPSW_CMD_ADD_CUSTOM_TPID(cmd, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_remove_custom_tpid(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpsw_custom_tpid_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_REMOVE_CUSTOM_TPID, ++ cmd_flags, ++ token); ++ DPSW_CMD_REMOVE_CUSTOM_TPID(cmd, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_if_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_ENABLE, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_ENABLE(cmd, if_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_if_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_DISABLE, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_DISABLE(cmd, if_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_if_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ struct dpsw_if_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_GET_ATTR, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_GET_ATTR(cmd, if_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_IF_GET_ATTR(cmd, attr); ++ ++ return 0; ++} ++ ++int dpsw_if_set_max_frame_length(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ uint16_t frame_length) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_MAX_FRAME_LENGTH, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_SET_MAX_FRAME_LENGTH(cmd, if_id, frame_length); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_if_get_max_frame_length(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ uint16_t *frame_length) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_GET_MAX_FRAME_LENGTH, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_GET_MAX_FRAME_LENGTH(cmd, if_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ DPSW_RSP_IF_GET_MAX_FRAME_LENGTH(cmd, *frame_length); ++ ++ return 0; ++} ++ ++int dpsw_vlan_add(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ const struct dpsw_vlan_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_ADD, ++ cmd_flags, ++ token); ++ DPSW_CMD_VLAN_ADD(cmd, vlan_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_vlan_add_if(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ const struct dpsw_vlan_if_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 1); ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_ADD_IF, ++ cmd_flags, ++ token); ++ DPSW_CMD_VLAN_ADD_IF(cmd, vlan_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_vlan_add_if_untagged(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ const struct dpsw_vlan_if_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 1); ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_ADD_IF_UNTAGGED, ++ cmd_flags, ++ token); ++ DPSW_CMD_VLAN_ADD_IF_UNTAGGED(cmd, vlan_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_vlan_add_if_flooding(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ const struct dpsw_vlan_if_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 1); ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_ADD_IF_FLOODING, ++ cmd_flags, ++ token); ++ DPSW_CMD_VLAN_ADD_IF_FLOODING(cmd, vlan_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_vlan_remove_if(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ const struct dpsw_vlan_if_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 1); ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_REMOVE_IF, ++ cmd_flags, ++ token); ++ DPSW_CMD_VLAN_REMOVE_IF(cmd, vlan_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_vlan_remove_if_untagged(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ const struct dpsw_vlan_if_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 1); ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_REMOVE_IF_UNTAGGED, ++ cmd_flags, ++ token); ++ DPSW_CMD_VLAN_REMOVE_IF_UNTAGGED(cmd, vlan_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_vlan_remove_if_flooding(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ const struct dpsw_vlan_if_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 1); ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_REMOVE_IF_FLOODING, ++ cmd_flags, ++ token); ++ DPSW_CMD_VLAN_REMOVE_IF_FLOODING(cmd, vlan_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_vlan_remove(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_REMOVE, ++ cmd_flags, ++ token); ++ DPSW_CMD_VLAN_REMOVE(cmd, vlan_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_vlan_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ struct dpsw_vlan_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_GET_ATTRIBUTES, ++ cmd_flags, ++ token); ++ DPSW_CMD_VLAN_GET_ATTR(cmd, vlan_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_VLAN_GET_ATTR(cmd, attr); ++ ++ return 0; ++} ++ ++int dpsw_vlan_get_if(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ struct dpsw_vlan_if_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_GET_IF, ++ cmd_flags, ++ token); ++ DPSW_CMD_VLAN_GET_IF(cmd, vlan_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_VLAN_GET_IF(cmd, cfg); ++ read_if_id_bitmap(cfg->if_id, &cfg->num_ifs, &cmd, 1); ++ ++ return 0; ++} ++ ++int dpsw_vlan_get_if_flooding(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ struct dpsw_vlan_if_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_GET_IF_FLOODING, ++ cmd_flags, ++ token); ++ DPSW_CMD_VLAN_GET_IF_FLOODING(cmd, vlan_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_VLAN_GET_IF_FLOODING(cmd, cfg); ++ read_if_id_bitmap(cfg->if_id, &cfg->num_ifs, &cmd, 1); ++ ++ return 0; ++} ++ ++int dpsw_vlan_get_if_untagged(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ struct dpsw_vlan_if_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_GET_IF_UNTAGGED, ++ cmd_flags, ++ token); ++ DPSW_CMD_VLAN_GET_IF_UNTAGGED(cmd, vlan_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_VLAN_GET_IF(cmd, cfg); ++ read_if_id_bitmap(cfg->if_id, &cfg->num_ifs, &cmd, 1); ++ ++ return 0; ++} ++ ++int dpsw_fdb_add(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t *fdb_id, ++ const struct dpsw_fdb_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_ADD, ++ cmd_flags, ++ token); ++ DPSW_CMD_FDB_ADD(cmd, cfg); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_FDB_ADD(cmd, *fdb_id); ++ ++ return 0; ++} ++ ++int dpsw_fdb_remove(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t fdb_id) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_REMOVE, ++ cmd_flags, ++ token); ++ DPSW_CMD_FDB_REMOVE(cmd, fdb_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_fdb_add_unicast(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t fdb_id, ++ const struct dpsw_fdb_unicast_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_ADD_UNICAST, ++ cmd_flags, ++ token); ++ DPSW_CMD_FDB_ADD_UNICAST(cmd, fdb_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_fdb_get_unicast(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t fdb_id, ++ struct dpsw_fdb_unicast_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_GET_UNICAST, ++ cmd_flags, ++ token); ++ DPSW_CMD_FDB_GET_UNICAST(cmd, fdb_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_FDB_GET_UNICAST(cmd, cfg); ++ ++ return 0; ++} ++ ++int dpsw_fdb_remove_unicast(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t fdb_id, ++ const struct dpsw_fdb_unicast_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_REMOVE_UNICAST, ++ cmd_flags, ++ token); ++ DPSW_CMD_FDB_REMOVE_UNICAST(cmd, fdb_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_fdb_add_multicast(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t fdb_id, ++ const struct dpsw_fdb_multicast_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 2); ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_ADD_MULTICAST, ++ cmd_flags, ++ token); ++ DPSW_CMD_FDB_ADD_MULTICAST(cmd, fdb_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_fdb_get_multicast(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t fdb_id, ++ struct dpsw_fdb_multicast_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_GET_MULTICAST, ++ cmd_flags, ++ token); ++ DPSW_CMD_FDB_GET_MULTICAST(cmd, fdb_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_FDB_GET_MULTICAST(cmd, cfg); ++ read_if_id_bitmap(cfg->if_id, &cfg->num_ifs, &cmd, 2); ++ ++ return 0; ++} ++ ++int dpsw_fdb_remove_multicast(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t fdb_id, ++ const struct dpsw_fdb_multicast_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 2); ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_REMOVE_MULTICAST, ++ cmd_flags, ++ token); ++ DPSW_CMD_FDB_REMOVE_MULTICAST(cmd, fdb_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_fdb_set_learning_mode(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t fdb_id, ++ enum dpsw_fdb_learning_mode mode) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_SET_LEARNING_MODE, ++ cmd_flags, ++ token); ++ DPSW_CMD_FDB_SET_LEARNING_MODE(cmd, fdb_id, mode); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_fdb_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t fdb_id, ++ struct dpsw_fdb_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_GET_ATTR, ++ cmd_flags, ++ token); ++ DPSW_CMD_FDB_GET_ATTR(cmd, fdb_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_FDB_GET_ATTR(cmd, attr); ++ ++ return 0; ++} ++ ++int dpsw_acl_add(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t *acl_id, ++ const struct dpsw_acl_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_ADD, ++ cmd_flags, ++ token); ++ DPSW_CMD_ACL_ADD(cmd, cfg); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_ACL_ADD(cmd, *acl_id); ++ ++ return 0; ++} ++ ++int dpsw_acl_remove(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t acl_id) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_REMOVE, ++ cmd_flags, ++ token); ++ DPSW_CMD_ACL_REMOVE(cmd, acl_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++void dpsw_acl_prepare_entry_cfg(const struct dpsw_acl_key *key, ++ uint8_t *entry_cfg_buf) ++{ ++ uint64_t *ext_params = (uint64_t *)entry_cfg_buf; ++ ++ DPSW_PREP_ACL_ENTRY(ext_params, key); ++} ++ ++int dpsw_acl_add_entry(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t acl_id, ++ const struct dpsw_acl_entry_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_ADD_ENTRY, ++ cmd_flags, ++ token); ++ DPSW_CMD_ACL_ADD_ENTRY(cmd, acl_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_acl_remove_entry(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t acl_id, ++ const struct dpsw_acl_entry_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_REMOVE_ENTRY, ++ cmd_flags, ++ token); ++ DPSW_CMD_ACL_REMOVE_ENTRY(cmd, acl_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_acl_add_if(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t acl_id, ++ const struct dpsw_acl_if_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 1); ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_ADD_IF, ++ cmd_flags, ++ token); ++ DPSW_CMD_ACL_ADD_IF(cmd, acl_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_acl_remove_if(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t acl_id, ++ const struct dpsw_acl_if_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 1); ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_REMOVE_IF, ++ cmd_flags, ++ token); ++ DPSW_CMD_ACL_REMOVE_IF(cmd, acl_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_acl_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t acl_id, ++ struct dpsw_acl_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_GET_ATTR, ++ cmd_flags, ++ token); ++ DPSW_CMD_ACL_GET_ATTR(cmd, acl_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_ACL_GET_ATTR(cmd, attr); ++ ++ return 0; ++} ++ ++int dpsw_ctrl_if_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpsw_ctrl_if_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_CTRL_IF_GET_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_CTRL_IF_GET_ATTR(cmd, attr); ++ ++ return 0; ++} ++ ++int dpsw_ctrl_if_set_pools(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpsw_ctrl_if_pools_cfg *pools) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_CTRL_IF_SET_POOLS, ++ cmd_flags, ++ token); ++ DPSW_CMD_CTRL_IF_SET_POOLS(cmd, pools); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_ctrl_if_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_CTRL_IF_ENABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++/** ++* @brief Function disables control interface ++* @mc_io: Pointer to MC portal's I/O object ++* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++* @token: Token of DPSW object ++* ++* Return: '0' on Success; Error code otherwise. ++*/ ++int dpsw_ctrl_if_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_CTRL_IF_DISABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} +diff --git a/drivers/net/dpaa2/mc/fsl_dpaiop.h b/drivers/net/dpaa2/mc/fsl_dpaiop.h +new file mode 100644 +index 0000000..b039b2a +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpaiop.h +@@ -0,0 +1,494 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPAIOP_H ++#define __FSL_DPAIOP_H ++ ++struct fsl_mc_io; ++ ++/* Data Path AIOP API ++ * Contains initialization APIs and runtime control APIs for DPAIOP ++ */ ++ ++/** ++ * dpaiop_open() - Open a control session for the specified object. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @dpaiop_id: DPAIOP unique ID ++ * @token: Returned token; use in subsequent API calls ++ * ++ * This function can be used to open a control session for an ++ * already created object; an object may have been declared in ++ * the DPL or by calling the dpaiop_create function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent commands for ++ * this specific object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpaiop_id, ++ uint16_t *token); ++ ++/** ++ * dpaiop_close() - Close the control session of the object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPAIOP object ++ * ++ * After this function is called, no further operations are ++ * allowed on the object without opening a new control session. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_close(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token); ++ ++/** ++ * struct dpaiop_cfg - Structure representing DPAIOP configuration ++ * @aiop_id: AIOP ID ++ * @aiop_container_id: AIOP container ID ++ */ ++struct dpaiop_cfg { ++ int aiop_id; ++ int aiop_container_id; ++}; ++ ++/** ++ * dpaiop_create() - Create the DPAIOP object. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @cfg: Configuration structure ++ * @token: Returned token; use in subsequent API calls ++ * ++ * Create the DPAIOP object, allocate required resources and ++ * perform required initialization. ++ * ++ * The object can be created either by declaring it in the ++ * DPL file, or by calling this function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent calls to ++ * this specific object. For objects that are created using the ++ * DPL file, call dpaiop_open function to get an authentication ++ * token first. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpaiop_cfg *cfg, ++ uint16_t *token); ++ ++/** ++ * dpaiop_destroy() - Destroy the DPAIOP object and release all its resources. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPAIOP object ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpaiop_destroy(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token); ++ ++/** ++ * dpaiop_reset() - Reset the DPAIOP, returns the object to initial state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPAIOP object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_reset(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token); ++ ++/** ++ * struct dpaiop_irq_cfg - IRQ configuration ++ * @addr: Address that must be written to signal a message-based interrupt ++ * @val: Value to write into irq_addr address ++ * @irq_num: A user defined number associated with this IRQ ++ */ ++struct dpaiop_irq_cfg { ++ uint64_t addr; ++ uint32_t val; ++ int irq_num; ++}; ++ ++/** ++ * dpaiop_set_irq() - Set IRQ information for the DPAIOP to trigger an interrupt. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPAIOP object ++ * @irq_index: Identifies the interrupt index to configure ++ * @irq_cfg: IRQ configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpaiop_irq_cfg *irq_cfg); ++ ++/** ++ * dpaiop_get_irq() - Get IRQ information from the DPAIOP. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPAIOP object ++ * @irq_index: The interrupt index to configure ++ * @type: Interrupt type: 0 represents message interrupt ++ * type (both irq_addr and irq_val are valid) ++ * @irq_cfg: IRQ attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpaiop_irq_cfg *irq_cfg); ++ ++/** ++ * dpaiop_set_irq_enable() - Set overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPAIOP object ++ * @irq_index: The interrupt index to configure ++ * @en: Interrupt state - enable = 1, disable = 0 ++ * ++ * Allows GPP software to control when interrupts are generated. ++ * Each interrupt can have up to 32 causes. The enable/disable control's the ++ * overall interrupt state. if the interrupt is disabled no causes will cause ++ * an interrupt. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en); ++ ++/** ++ * dpaiop_get_irq_enable() - Get overall interrupt state ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPAIOP object ++ * @irq_index: The interrupt index to configure ++ * @en: Returned interrupt state - enable = 1, disable = 0 ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en); ++ ++/** ++ * dpaiop_set_irq_mask() - Set interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPAIOP object ++ * @irq_index: The interrupt index to configure ++ * @mask: Event mask to trigger interrupt; ++ * each bit: ++ * 0 = ignore event ++ * 1 = consider event for asserting IRQ ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask); ++ ++/** ++ * dpaiop_get_irq_mask() - Get interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPAIOP object ++ * @irq_index: The interrupt index to configure ++ * @mask: Returned event mask to trigger interrupt ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask); ++ ++/** ++ * dpaiop_get_irq_status() - Get the current status of any pending interrupts. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPAIOP object ++ * @irq_index: The interrupt index to configure ++ * @status: Returned interrupts status - one bit per cause: ++ * 0 = no interrupt pending ++ * 1 = interrupt pending ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status); ++ ++/** ++ * dpaiop_clear_irq_status() - Clear a pending interrupt's status ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPAIOP object ++ * @irq_index: The interrupt index to configure ++ * @status: Bits to clear (W1C) - one bit per cause: ++ * 0 = don't change ++ * 1 = clear status bit ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status); ++ ++/** ++ * struct dpaiop_attr - Structure representing DPAIOP attributes ++ * @id: AIOP ID ++ * @version: DPAIOP version ++ */ ++struct dpaiop_attr { ++ int id; ++ /** ++ * struct version - Structure representing DPAIOP version ++ * @major: DPAIOP major version ++ * @minor: DPAIOP minor version ++ */ ++ struct { ++ uint16_t major; ++ uint16_t minor; ++ } version; ++}; ++ ++/** ++ * dpaiop_get_attributes - Retrieve DPAIOP attributes. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPAIOP object ++ * @attr: Returned object's attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpaiop_attr *attr); ++ ++/** ++ * struct dpaiop_load_cfg - AIOP load configuration ++ * @options: AIOP load options ++ * @img_iova: I/O virtual address of AIOP ELF image ++ * @img_size: Size of AIOP ELF image in memory (in bytes) ++ */ ++struct dpaiop_load_cfg { ++ uint64_t options; ++ uint64_t img_iova; ++ uint32_t img_size; ++}; ++ ++/** ++ * dpaiop_load_aiop() - Loads an image to AIOP ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPAIOP object ++ * @cfg: AIOP load configurations ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_load(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpaiop_load_cfg *cfg); ++ ++#define DPAIOP_RUN_OPT_DEBUG 0x0000000000000001ULL ++ ++/** ++ * struct dpaiop_run_cfg - AIOP run configuration ++ * @cores_mask: Mask of AIOP cores to run (core 0 in most significant bit) ++ * @options: Execution options (currently none defined) ++ * @args_iova: I/O virtual address of AIOP arguments ++ * @args_size: Size of AIOP arguments in memory (in bytes) ++ */ ++struct dpaiop_run_cfg { ++ uint64_t cores_mask; ++ uint64_t options; ++ uint64_t args_iova; ++ uint32_t args_size; ++}; ++ ++/** ++ * dpaiop_run_aiop() - Starts AIOP execution ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPAIOP object ++ * @cfg: AIOP run configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_run(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpaiop_run_cfg *cfg); ++ ++/** ++ * struct dpaiop_sl_version - AIOP SL (Service Layer) version ++ * @major: AIOP SL major version number ++ * @minor: AIOP SL minor version number ++ * @revision: AIOP SL revision number ++ */ ++struct dpaiop_sl_version { ++ uint32_t major; ++ uint32_t minor; ++ uint32_t revision; ++}; ++ ++/** ++ * dpaiop_get_sl_version() - Get AIOP SL (Service Layer) version ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPAIOP object ++ * @version: AIOP SL version number ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_get_sl_version(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpaiop_sl_version *version); ++ ++/** ++ * AIOP states ++ * ++ * AIOP internal states, can be retrieved by calling dpaiop_get_state() routine ++ */ ++ ++/** ++ * AIOP reset successfully completed. ++ */ ++#define DPAIOP_STATE_RESET_DONE 0x00000000 ++/** ++ * AIOP reset is ongoing. ++ */ ++#define DPAIOP_STATE_RESET_ONGOING 0x00000001 ++ ++/** ++ * AIOP image loading successfully completed. ++ */ ++#define DPAIOP_STATE_LOAD_DONE 0x00000002 ++/** ++ * AIOP image loading is ongoing. ++ */ ++#define DPAIOP_STATE_LOAD_ONGIONG 0x00000004 ++/** ++ * AIOP image loading completed with error. ++ */ ++#define DPAIOP_STATE_LOAD_ERROR 0x00000008 ++ ++/** ++ * Boot process of AIOP cores is ongoing. ++ */ ++#define DPAIOP_STATE_BOOT_ONGOING 0x00000010 ++/** ++ * Boot process of AIOP cores completed with an error. ++ */ ++#define DPAIOP_STATE_BOOT_ERROR 0x00000020 ++/** ++ * AIOP cores are functional and running ++ */ ++#define DPAIOP_STATE_RUNNING 0x00000040 ++/** @} */ ++ ++/** ++ * dpaiop_get_state() - Get AIOP state ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPAIOP object ++ * @state: AIOP state ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_get_state(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint32_t *state); ++ ++/** ++ * dpaiop_set_time_of_day() - Set AIOP internal time-of-day ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPAIOP object ++ * @time_of_day: Current number of milliseconds since the Epoch ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_set_time_of_day(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint64_t time_of_day); ++ ++/** ++ * dpaiop_get_time_of_day() - Get AIOP internal time-of-day ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPAIOP object ++ * @time_of_day: Current number of milliseconds since the Epoch ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_get_time_of_day(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint64_t *time_of_day); ++ ++#endif /* __FSL_DPAIOP_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpaiop_cmd.h b/drivers/net/dpaa2/mc/fsl_dpaiop_cmd.h +new file mode 100644 +index 0000000..5b77bb8 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpaiop_cmd.h +@@ -0,0 +1,190 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_DPAIOP_CMD_H ++#define _FSL_DPAIOP_CMD_H ++ ++/* DPAIOP Version */ ++#define DPAIOP_VER_MAJOR 1 ++#define DPAIOP_VER_MINOR 2 ++ ++/* Command IDs */ ++#define DPAIOP_CMDID_CLOSE 0x800 ++#define DPAIOP_CMDID_OPEN 0x80a ++#define DPAIOP_CMDID_CREATE 0x90a ++#define DPAIOP_CMDID_DESTROY 0x900 ++ ++#define DPAIOP_CMDID_GET_ATTR 0x004 ++#define DPAIOP_CMDID_RESET 0x005 ++ ++#define DPAIOP_CMDID_SET_IRQ 0x010 ++#define DPAIOP_CMDID_GET_IRQ 0x011 ++#define DPAIOP_CMDID_SET_IRQ_ENABLE 0x012 ++#define DPAIOP_CMDID_GET_IRQ_ENABLE 0x013 ++#define DPAIOP_CMDID_SET_IRQ_MASK 0x014 ++#define DPAIOP_CMDID_GET_IRQ_MASK 0x015 ++#define DPAIOP_CMDID_GET_IRQ_STATUS 0x016 ++#define DPAIOP_CMDID_CLEAR_IRQ_STATUS 0x017 ++ ++#define DPAIOP_CMDID_LOAD 0x280 ++#define DPAIOP_CMDID_RUN 0x281 ++#define DPAIOP_CMDID_GET_SL_VERSION 0x282 ++#define DPAIOP_CMDID_GET_STATE 0x283 ++#define DPAIOP_CMDID_SET_TIME_OF_DAY 0x284 ++#define DPAIOP_CMDID_GET_TIME_OF_DAY 0x285 ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_CMD_OPEN(cmd, dpaiop_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpaiop_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_CMD_CREATE(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, cfg->aiop_id);\ ++ MC_CMD_OP(cmd, 0, 32, 32, int, cfg->aiop_container_id);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, irq_index);\ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, irq_cfg->val);\ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr); \ ++ MC_CMD_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_CMD_GET_IRQ(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_RSP_GET_IRQ(cmd, type, irq_cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr); \ ++ MC_RSP_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, type); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_CMD_SET_IRQ_ENABLE(cmd, irq_index, en) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, en); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_CMD_GET_IRQ_ENABLE(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_RSP_GET_IRQ_ENABLE(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 8, uint8_t, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, mask);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_CMD_GET_IRQ_MASK(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_RSP_GET_IRQ_MASK(cmd, mask) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mask) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_RSP_GET_IRQ_STATUS(cmd, status) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, status) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_RSP_GET_ATTRIBUTES(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, attr->id);\ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->version.major);\ ++ MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->version.minor);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_CMD_LOAD(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, cfg->img_size); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->img_iova); \ ++ MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->options); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_CMD_RUN(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, cfg->args_size); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->cores_mask); \ ++ MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->options); \ ++ MC_CMD_OP(cmd, 3, 0, 64, uint64_t, cfg->args_iova); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_RSP_GET_SL_VERSION(cmd, version) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, version->major);\ ++ MC_RSP_OP(cmd, 0, 32, 32, uint32_t, version->minor);\ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, version->revision);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_RSP_GET_STATE(cmd, state) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, state) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_CMD_SET_TIME_OF_DAY(cmd, time_of_day) \ ++ MC_CMD_OP(cmd, 0, 0, 64, uint64_t, time_of_day) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_RSP_GET_TIME_OF_DAY(cmd, time_of_day) \ ++ MC_RSP_OP(cmd, 0, 0, 64, uint64_t, time_of_day) ++ ++#endif /* _FSL_DPAIOP_CMD_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpbp.h b/drivers/net/dpaa2/mc/fsl_dpbp.h +new file mode 100644 +index 0000000..9856bb8 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpbp.h +@@ -0,0 +1,438 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPBP_H ++#define __FSL_DPBP_H ++ ++/* Data Path Buffer Pool API ++ * Contains initialization APIs and runtime control APIs for DPBP ++ */ ++ ++struct fsl_mc_io; ++ ++/** ++ * dpbp_open() - Open a control session for the specified object. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @dpbp_id: DPBP unique ID ++ * @token: Returned token; use in subsequent API calls ++ * ++ * This function can be used to open a control session for an ++ * already created object; an object may have been declared in ++ * the DPL or by calling the dpbp_create function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent commands for ++ * this specific object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpbp_id, ++ uint16_t *token); ++ ++/** ++ * dpbp_close() - Close the control session of the object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * ++ * After this function is called, no further operations are ++ * allowed on the object without opening a new control session. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * struct dpbp_cfg - Structure representing DPBP configuration ++ * @options: place holder ++ */ ++struct dpbp_cfg { ++ uint32_t options; ++}; ++ ++/** ++ * dpbp_create() - Create the DPBP object. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @cfg: Configuration structure ++ * @token: Returned token; use in subsequent API calls ++ * ++ * Create the DPBP object, allocate required resources and ++ * perform required initialization. ++ * ++ * The object can be created either by declaring it in the ++ * DPL file, or by calling this function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent calls to ++ * this specific object. For objects that are created using the ++ * DPL file, call dpbp_open function to get an authentication ++ * token first. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpbp_cfg *cfg, ++ uint16_t *token); ++ ++/** ++ * dpbp_destroy() - Destroy the DPBP object and release all its resources. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpbp_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpbp_enable() - Enable the DPBP. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpbp_disable() - Disable the DPBP. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpbp_is_enabled() - Check if the DPBP is enabled. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * @en: Returns '1' if object is enabled; '0' otherwise ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en); ++ ++/** ++ * dpbp_reset() - Reset the DPBP, returns the object to initial state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * struct dpbp_irq_cfg - IRQ configuration ++ * @addr: Address that must be written to signal a message-based interrupt ++ * @val: Value to write into irq_addr address ++ * @irq_num: A user defined number associated with this IRQ ++ */ ++struct dpbp_irq_cfg { ++ uint64_t addr; ++ uint32_t val; ++ int irq_num; ++}; ++ ++/** ++ * dpbp_set_irq() - Set IRQ information for the DPBP to trigger an interrupt. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * @irq_index: Identifies the interrupt index to configure ++ * @irq_cfg: IRQ configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpbp_irq_cfg *irq_cfg); ++ ++/** ++ * dpbp_get_irq() - Get IRQ information from the DPBP. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * @irq_index: The interrupt index to configure ++ * @type: Interrupt type: 0 represents message interrupt ++ * type (both irq_addr and irq_val are valid) ++ * @irq_cfg: IRQ attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpbp_irq_cfg *irq_cfg); ++ ++/** ++ * dpbp_set_irq_enable() - Set overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * @irq_index: The interrupt index to configure ++ * @en: Interrupt state - enable = 1, disable = 0 ++ * ++ * Allows GPP software to control when interrupts are generated. ++ * Each interrupt can have up to 32 causes. The enable/disable control's the ++ * overall interrupt state. if the interrupt is disabled no causes will cause ++ * an interrupt. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en); ++ ++/** ++ * dpbp_get_irq_enable() - Get overall interrupt state ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * @irq_index: The interrupt index to configure ++ * @en: Returned interrupt state - enable = 1, disable = 0 ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en); ++ ++/** ++ * dpbp_set_irq_mask() - Set interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * @irq_index: The interrupt index to configure ++ * @mask: Event mask to trigger interrupt; ++ * each bit: ++ * 0 = ignore event ++ * 1 = consider event for asserting IRQ ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask); ++ ++/** ++ * dpbp_get_irq_mask() - Get interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * @irq_index: The interrupt index to configure ++ * @mask: Returned event mask to trigger interrupt ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask); ++ ++/** ++ * dpbp_get_irq_status() - Get the current status of any pending interrupts. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * @irq_index: The interrupt index to configure ++ * @status: Returned interrupts status - one bit per cause: ++ * 0 = no interrupt pending ++ * 1 = interrupt pending ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status); ++ ++/** ++ * dpbp_clear_irq_status() - Clear a pending interrupt's status ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * @irq_index: The interrupt index to configure ++ * @status: Bits to clear (W1C) - one bit per cause: ++ * 0 = don't change ++ * 1 = clear status bit ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status); ++ ++/** ++ * struct dpbp_attr - Structure representing DPBP attributes ++ * @id: DPBP object ID ++ * @version: DPBP version ++ * @bpid: Hardware buffer pool ID; should be used as an argument in ++ * acquire/release operations on buffers ++ */ ++struct dpbp_attr { ++ int id; ++ /** ++ * struct version - Structure representing DPBP version ++ * @major: DPBP major version ++ * @minor: DPBP minor version ++ */ ++ struct { ++ uint16_t major; ++ uint16_t minor; ++ } version; ++ uint16_t bpid; ++}; ++ ++/** ++ * dpbp_get_attributes - Retrieve DPBP attributes. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * @attr: Returned object's attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpbp_attr *attr); ++ ++/** ++ * DPBP notifications options ++ */ ++ ++/** ++ * BPSCN write will attempt to allocate into a cache (coherent write) ++ */ ++#define DPBP_NOTIF_OPT_COHERENT_WRITE 0x00000001 ++ ++/** ++ * struct dpbp_notification_cfg - Structure representing DPBP notifications ++ * towards software ++ * @depletion_entry: below this threshold the pool is "depleted"; ++ * set it to '0' to disable it ++ * @depletion_exit: greater than or equal to this threshold the pool exit its ++ * "depleted" state ++ * @surplus_entry: above this threshold the pool is in "surplus" state; ++ * set it to '0' to disable it ++ * @surplus_exit: less than or equal to this threshold the pool exit its ++ * "surplus" state ++ * @message_iova: MUST be given if either 'depletion_entry' or 'surplus_entry' ++ * is not '0' (enable); I/O virtual address (must be in DMA-able memory), ++ * must be 16B aligned. ++ * @message_ctx: The context that will be part of the BPSCN message and will ++ * be written to 'message_iova' ++ * @options: Mask of available options; use 'DPBP_NOTIF_OPT_' values ++ */ ++struct dpbp_notification_cfg { ++ uint32_t depletion_entry; ++ uint32_t depletion_exit; ++ uint32_t surplus_entry; ++ uint32_t surplus_exit; ++ uint64_t message_iova; ++ uint64_t message_ctx; ++ uint16_t options; ++}; ++ ++/** ++ * dpbp_set_notifications() - Set notifications towards software ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * @cfg: notifications configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_set_notifications(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpbp_notification_cfg *cfg); ++ ++/** ++ * dpbp_get_notifications() - Get the notifications configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * @cfg: notifications configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_get_notifications(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpbp_notification_cfg *cfg); ++ ++#endif /* __FSL_DPBP_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpbp_cmd.h b/drivers/net/dpaa2/mc/fsl_dpbp_cmd.h +new file mode 100644 +index 0000000..71ad96a +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpbp_cmd.h +@@ -0,0 +1,172 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_DPBP_CMD_H ++#define _FSL_DPBP_CMD_H ++ ++/* DPBP Version */ ++#define DPBP_VER_MAJOR 2 ++#define DPBP_VER_MINOR 2 ++ ++/* Command IDs */ ++#define DPBP_CMDID_CLOSE 0x800 ++#define DPBP_CMDID_OPEN 0x804 ++#define DPBP_CMDID_CREATE 0x904 ++#define DPBP_CMDID_DESTROY 0x900 ++ ++#define DPBP_CMDID_ENABLE 0x002 ++#define DPBP_CMDID_DISABLE 0x003 ++#define DPBP_CMDID_GET_ATTR 0x004 ++#define DPBP_CMDID_RESET 0x005 ++#define DPBP_CMDID_IS_ENABLED 0x006 ++ ++#define DPBP_CMDID_SET_IRQ 0x010 ++#define DPBP_CMDID_GET_IRQ 0x011 ++#define DPBP_CMDID_SET_IRQ_ENABLE 0x012 ++#define DPBP_CMDID_GET_IRQ_ENABLE 0x013 ++#define DPBP_CMDID_SET_IRQ_MASK 0x014 ++#define DPBP_CMDID_GET_IRQ_MASK 0x015 ++#define DPBP_CMDID_GET_IRQ_STATUS 0x016 ++#define DPBP_CMDID_CLEAR_IRQ_STATUS 0x017 ++ ++#define DPBP_CMDID_SET_NOTIFICATIONS 0x01b0 ++#define DPBP_CMDID_GET_NOTIFICATIONS 0x01b1 ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPBP_CMD_OPEN(cmd, dpbp_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpbp_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPBP_RSP_IS_ENABLED(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPBP_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, irq_index);\ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, irq_cfg->val);\ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr); \ ++ MC_CMD_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPBP_CMD_GET_IRQ(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPBP_RSP_GET_IRQ(cmd, type, irq_cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr); \ ++ MC_RSP_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, type); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPBP_CMD_SET_IRQ_ENABLE(cmd, irq_index, en) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, en); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPBP_CMD_GET_IRQ_ENABLE(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPBP_RSP_GET_IRQ_ENABLE(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 8, uint8_t, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPBP_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, mask);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPBP_CMD_GET_IRQ_MASK(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPBP_RSP_GET_IRQ_MASK(cmd, mask) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mask) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPBP_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++/* cmd, param, offset, width, type, arg_name */ ++#define DPBP_RSP_GET_IRQ_STATUS(cmd, status) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, status) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPBP_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPBP_RSP_GET_ATTRIBUTES(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 16, 16, uint16_t, attr->bpid); \ ++ MC_RSP_OP(cmd, 0, 32, 32, int, attr->id);\ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->version.major);\ ++ MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->version.minor);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPBP_CMD_SET_NOTIFICATIONS(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, cfg->depletion_entry); \ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, cfg->depletion_exit);\ ++ MC_CMD_OP(cmd, 1, 0, 32, uint32_t, cfg->surplus_entry);\ ++ MC_CMD_OP(cmd, 1, 32, 32, uint32_t, cfg->surplus_exit);\ ++ MC_CMD_OP(cmd, 2, 0, 16, uint16_t, cfg->options);\ ++ MC_CMD_OP(cmd, 3, 0, 64, uint64_t, cfg->message_ctx);\ ++ MC_CMD_OP(cmd, 4, 0, 64, uint64_t, cfg->message_iova);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPBP_CMD_GET_NOTIFICATIONS(cmd, cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, cfg->depletion_entry); \ ++ MC_RSP_OP(cmd, 0, 32, 32, uint32_t, cfg->depletion_exit);\ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, cfg->surplus_entry);\ ++ MC_RSP_OP(cmd, 1, 32, 32, uint32_t, cfg->surplus_exit);\ ++ MC_RSP_OP(cmd, 2, 0, 16, uint16_t, cfg->options);\ ++ MC_RSP_OP(cmd, 3, 0, 64, uint64_t, cfg->message_ctx);\ ++ MC_RSP_OP(cmd, 4, 0, 64, uint64_t, cfg->message_iova);\ ++} while (0) ++#endif /* _FSL_DPBP_CMD_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpci.h b/drivers/net/dpaa2/mc/fsl_dpci.h +new file mode 100644 +index 0000000..d885935 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpci.h +@@ -0,0 +1,594 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPCI_H ++#define __FSL_DPCI_H ++ ++/* Data Path Communication Interface API ++ * Contains initialization APIs and runtime control APIs for DPCI ++ */ ++ ++struct fsl_mc_io; ++ ++/** General DPCI macros */ ++ ++/** ++ * Maximum number of Tx/Rx priorities per DPCI object ++ */ ++#define DPCI_PRIO_NUM 2 ++ ++/** ++ * Indicates an invalid frame queue ++ */ ++#define DPCI_FQID_NOT_VALID (uint32_t)(-1) ++ ++/** ++ * All queues considered; see dpci_set_rx_queue() ++ */ ++#define DPCI_ALL_QUEUES (uint8_t)(-1) ++ ++/** ++ * dpci_open() - Open a control session for the specified object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @dpci_id: DPCI unique ID ++ * @token: Returned token; use in subsequent API calls ++ * ++ * This function can be used to open a control session for an ++ * already created object; an object may have been declared in ++ * the DPL or by calling the dpci_create() function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent commands for ++ * this specific object. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpci_id, ++ uint16_t *token); ++ ++/** ++ * dpci_close() - Close the control session of the object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * ++ * After this function is called, no further operations are ++ * allowed on the object without opening a new control session. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * struct dpci_cfg - Structure representing DPCI configuration ++ * @num_of_priorities: Number of receive priorities (queues) for the DPCI; ++ * note, that the number of transmit priorities (queues) ++ * is determined by the number of receive priorities of ++ * the peer DPCI object ++ */ ++struct dpci_cfg { ++ uint8_t num_of_priorities; ++}; ++ ++/** ++ * dpci_create() - Create the DPCI object. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @cfg: Configuration structure ++ * @token: Returned token; use in subsequent API calls ++ * ++ * Create the DPCI object, allocate required resources and perform required ++ * initialization. ++ * ++ * The object can be created either by declaring it in the ++ * DPL file, or by calling this function. ++ * ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent calls to ++ * this specific object. For objects that are created using the ++ * DPL file, call dpci_open() function to get an authentication ++ * token first. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpci_cfg *cfg, ++ uint16_t *token); ++ ++/** ++ * dpci_destroy() - Destroy the DPCI object and release all its resources. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpci_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpci_enable() - Enable the DPCI, allow sending and receiving frames. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpci_disable() - Disable the DPCI, stop sending and receiving frames. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpci_is_enabled() - Check if the DPCI is enabled. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @en: Returns '1' if object is enabled; '0' otherwise ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en); ++ ++/** ++ * dpci_reset() - Reset the DPCI, returns the object to initial state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** DPCI IRQ Index and Events */ ++ ++/** ++ * IRQ index ++ */ ++#define DPCI_IRQ_INDEX 0 ++ ++/** ++ * IRQ event - indicates a change in link state ++ */ ++#define DPCI_IRQ_EVENT_LINK_CHANGED 0x00000001 ++/** ++ * IRQ event - indicates a connection event ++ */ ++#define DPCI_IRQ_EVENT_CONNECTED 0x00000002 ++/** ++ * IRQ event - indicates a disconnection event ++ */ ++#define DPCI_IRQ_EVENT_DISCONNECTED 0x00000004 ++ ++/** ++ * struct dpci_irq_cfg - IRQ configuration ++ * @addr: Address that must be written to signal a message-based interrupt ++ * @val: Value to write into irq_addr address ++ * @irq_num: A user defined number associated with this IRQ ++ */ ++struct dpci_irq_cfg { ++ uint64_t addr; ++ uint32_t val; ++ int irq_num; ++}; ++ ++/** ++ * dpci_set_irq() - Set IRQ information for the DPCI to trigger an interrupt. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @irq_index: Identifies the interrupt index to configure ++ * @irq_cfg: IRQ configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpci_irq_cfg *irq_cfg); ++ ++/** ++ * dpci_get_irq() - Get IRQ information from the DPCI. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @irq_index: The interrupt index to configure ++ * @type: Interrupt type: 0 represents message interrupt ++ * type (both irq_addr and irq_val are valid) ++ * @irq_cfg: IRQ attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpci_irq_cfg *irq_cfg); ++ ++/** ++ * dpci_set_irq_enable() - Set overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @irq_index: The interrupt index to configure ++ * @en: Interrupt state - enable = 1, disable = 0 ++ * ++ * Allows GPP software to control when interrupts are generated. ++ * Each interrupt can have up to 32 causes. The enable/disable control's the ++ * overall interrupt state. if the interrupt is disabled no causes will cause ++ * an interrupt. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en); ++ ++/** ++ * dpci_get_irq_enable() - Get overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @irq_index: The interrupt index to configure ++ * @en: Returned interrupt state - enable = 1, disable = 0 ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en); ++ ++/** ++ * dpci_set_irq_mask() - Set interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @irq_index: The interrupt index to configure ++ * @mask: event mask to trigger interrupt; ++ * each bit: ++ * 0 = ignore event ++ * 1 = consider event for asserting IRQ ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask); ++ ++/** ++ * dpci_get_irq_mask() - Get interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @irq_index: The interrupt index to configure ++ * @mask: Returned event mask to trigger interrupt ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask); ++ ++/** ++ * dpci_get_irq_status() - Get the current status of any pending interrupts. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @irq_index: The interrupt index to configure ++ * @status: Returned interrupts status - one bit per cause: ++ * 0 = no interrupt pending ++ * 1 = interrupt pending ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status); ++ ++/** ++ * dpci_clear_irq_status() - Clear a pending interrupt's status ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @irq_index: The interrupt index to configure ++ * @status: bits to clear (W1C) - one bit per cause: ++ * 0 = don't change ++ * 1 = clear status bit ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status); ++ ++/** ++ * struct dpci_attr - Structure representing DPCI attributes ++ * @id: DPCI object ID ++ * @version: DPCI version ++ * @num_of_priorities: Number of receive priorities ++ */ ++struct dpci_attr { ++ int id; ++ /** ++ * struct version - Structure representing DPCI attributes ++ * @major: DPCI major version ++ * @minor: DPCI minor version ++ */ ++ struct { ++ uint16_t major; ++ uint16_t minor; ++ } version; ++ uint8_t num_of_priorities; ++}; ++ ++/** ++ * dpci_get_attributes() - Retrieve DPCI attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @attr: Returned object's attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpci_attr *attr); ++ ++/** ++ * struct dpci_peer_attr - Structure representing the peer DPCI attributes ++ * @peer_id: DPCI peer id; if no peer is connected returns (-1) ++ * @num_of_priorities: The pper's number of receive priorities; determines the ++ * number of transmit priorities for the local DPCI object ++ */ ++struct dpci_peer_attr { ++ int peer_id; ++ uint8_t num_of_priorities; ++}; ++ ++/** ++ * dpci_get_peer_attributes() - Retrieve peer DPCI attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @attr: Returned peer attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_get_peer_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpci_peer_attr *attr); ++ ++/** ++ * dpci_get_link_state() - Retrieve the DPCI link state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @up: Returned link state; returns '1' if link is up, '0' otherwise ++ * ++ * DPCI can be connected to another DPCI, together they ++ * create a 'link'. In order to use the DPCI Tx and Rx queues, ++ * both objects must be enabled. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_get_link_state(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *up); ++ ++/** ++ * enum dpci_dest - DPCI destination types ++ * @DPCI_DEST_NONE: Unassigned destination; The queue is set in parked mode ++ * and does not generate FQDAN notifications; user is ++ * expected to dequeue from the queue based on polling or ++ * other user-defined method ++ * @DPCI_DEST_DPIO: The queue is set in schedule mode and generates FQDAN ++ * notifications to the specified DPIO; user is expected ++ * to dequeue from the queue only after notification is ++ * received ++ * @DPCI_DEST_DPCON: The queue is set in schedule mode and does not generate ++ * FQDAN notifications, but is connected to the specified ++ * DPCON object; ++ * user is expected to dequeue from the DPCON channel ++ */ ++enum dpci_dest { ++ DPCI_DEST_NONE = 0, ++ DPCI_DEST_DPIO = 1, ++ DPCI_DEST_DPCON = 2 ++}; ++ ++/** ++ * struct dpci_dest_cfg - Structure representing DPCI destination configuration ++ * @dest_type: Destination type ++ * @dest_id: Either DPIO ID or DPCON ID, depending on the destination type ++ * @priority: Priority selection within the DPIO or DPCON channel; valid ++ * values are 0-1 or 0-7, depending on the number of priorities ++ * in that channel; not relevant for 'DPCI_DEST_NONE' option ++ */ ++struct dpci_dest_cfg { ++ enum dpci_dest dest_type; ++ int dest_id; ++ uint8_t priority; ++}; ++ ++/** DPCI queue modification options */ ++ ++/** ++ * Select to modify the user's context associated with the queue ++ */ ++#define DPCI_QUEUE_OPT_USER_CTX 0x00000001 ++ ++/** ++ * Select to modify the queue's destination ++ */ ++#define DPCI_QUEUE_OPT_DEST 0x00000002 ++ ++/** ++ * struct dpci_rx_queue_cfg - Structure representing RX queue configuration ++ * @options: Flags representing the suggested modifications to the queue; ++ * Use any combination of 'DPCI_QUEUE_OPT_' flags ++ * @user_ctx: User context value provided in the frame descriptor of each ++ * dequeued frame; ++ * valid only if 'DPCI_QUEUE_OPT_USER_CTX' is contained in ++ * 'options' ++ * @dest_cfg: Queue destination parameters; ++ * valid only if 'DPCI_QUEUE_OPT_DEST' is contained in 'options' ++ */ ++struct dpci_rx_queue_cfg { ++ uint32_t options; ++ uint64_t user_ctx; ++ struct dpci_dest_cfg dest_cfg; ++}; ++ ++/** ++ * dpci_set_rx_queue() - Set Rx queue configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @priority: Select the queue relative to number of ++ * priorities configured at DPCI creation; use ++ * DPCI_ALL_QUEUES to configure all Rx queues ++ * identically. ++ * @cfg: Rx queue configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_set_rx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t priority, ++ const struct dpci_rx_queue_cfg *cfg); ++ ++/** ++ * struct dpci_rx_queue_attr - Structure representing Rx queue attributes ++ * @user_ctx: User context value provided in the frame descriptor of each ++ * dequeued frame ++ * @dest_cfg: Queue destination configuration ++ * @fqid: Virtual FQID value to be used for dequeue operations ++ */ ++struct dpci_rx_queue_attr { ++ uint64_t user_ctx; ++ struct dpci_dest_cfg dest_cfg; ++ uint32_t fqid; ++}; ++ ++/** ++ * dpci_get_rx_queue() - Retrieve Rx queue attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @priority: Select the queue relative to number of ++ * priorities configured at DPCI creation ++ * @attr: Returned Rx queue attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_get_rx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t priority, ++ struct dpci_rx_queue_attr *attr); ++ ++/** ++ * struct dpci_tx_queue_attr - Structure representing attributes of Tx queues ++ * @fqid: Virtual FQID to be used for sending frames to peer DPCI; ++ * returns 'DPCI_FQID_NOT_VALID' if a no peer is connected or if ++ * the selected priority exceeds the number of priorities of the ++ * peer DPCI object ++ */ ++struct dpci_tx_queue_attr { ++ uint32_t fqid; ++}; ++ ++/** ++ * dpci_get_tx_queue() - Retrieve Tx queue attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @priority: Select the queue relative to number of ++ * priorities of the peer DPCI object ++ * @attr: Returned Tx queue attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_get_tx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t priority, ++ struct dpci_tx_queue_attr *attr); ++ ++#endif /* __FSL_DPCI_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpci_cmd.h b/drivers/net/dpaa2/mc/fsl_dpci_cmd.h +new file mode 100644 +index 0000000..f45e435 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpci_cmd.h +@@ -0,0 +1,200 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_DPCI_CMD_H ++#define _FSL_DPCI_CMD_H ++ ++/* DPCI Version */ ++#define DPCI_VER_MAJOR 2 ++#define DPCI_VER_MINOR 2 ++ ++/* Command IDs */ ++#define DPCI_CMDID_CLOSE 0x800 ++#define DPCI_CMDID_OPEN 0x807 ++#define DPCI_CMDID_CREATE 0x907 ++#define DPCI_CMDID_DESTROY 0x900 ++ ++#define DPCI_CMDID_ENABLE 0x002 ++#define DPCI_CMDID_DISABLE 0x003 ++#define DPCI_CMDID_GET_ATTR 0x004 ++#define DPCI_CMDID_RESET 0x005 ++#define DPCI_CMDID_IS_ENABLED 0x006 ++ ++#define DPCI_CMDID_SET_IRQ 0x010 ++#define DPCI_CMDID_GET_IRQ 0x011 ++#define DPCI_CMDID_SET_IRQ_ENABLE 0x012 ++#define DPCI_CMDID_GET_IRQ_ENABLE 0x013 ++#define DPCI_CMDID_SET_IRQ_MASK 0x014 ++#define DPCI_CMDID_GET_IRQ_MASK 0x015 ++#define DPCI_CMDID_GET_IRQ_STATUS 0x016 ++#define DPCI_CMDID_CLEAR_IRQ_STATUS 0x017 ++ ++#define DPCI_CMDID_SET_RX_QUEUE 0x0e0 ++#define DPCI_CMDID_GET_LINK_STATE 0x0e1 ++#define DPCI_CMDID_GET_PEER_ATTR 0x0e2 ++#define DPCI_CMDID_GET_RX_QUEUE 0x0e3 ++#define DPCI_CMDID_GET_TX_QUEUE 0x0e4 ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_CMD_OPEN(cmd, dpci_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpci_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_CMD_CREATE(cmd, cfg) \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, cfg->num_of_priorities) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_RSP_IS_ENABLED(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, irq_index);\ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, irq_cfg->val);\ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\ ++ MC_CMD_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_CMD_GET_IRQ(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_RSP_GET_IRQ(cmd, type, irq_cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\ ++ MC_RSP_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, type); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_CMD_SET_IRQ_ENABLE(cmd, irq_index, en) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, en); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_CMD_GET_IRQ_ENABLE(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_RSP_GET_IRQ_ENABLE(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 8, uint8_t, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, mask); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_CMD_GET_IRQ_MASK(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_RSP_GET_IRQ_MASK(cmd, mask) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mask) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_RSP_GET_IRQ_STATUS(cmd, status) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, status) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_RSP_GET_ATTR(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, attr->id);\ ++ MC_RSP_OP(cmd, 0, 48, 8, uint8_t, attr->num_of_priorities);\ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->version.major);\ ++ MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->version.minor);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_RSP_GET_PEER_ATTR(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, attr->peer_id);\ ++ MC_RSP_OP(cmd, 1, 0, 8, uint8_t, attr->num_of_priorities);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_RSP_GET_LINK_STATE(cmd, up) \ ++ MC_RSP_OP(cmd, 0, 0, 1, int, up) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_CMD_SET_RX_QUEUE(cmd, priority, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, cfg->dest_cfg.dest_id);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->dest_cfg.priority);\ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, priority);\ ++ MC_CMD_OP(cmd, 0, 48, 4, enum dpci_dest, cfg->dest_cfg.dest_type);\ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->user_ctx);\ ++ MC_CMD_OP(cmd, 2, 0, 32, uint32_t, cfg->options);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_CMD_GET_RX_QUEUE(cmd, priority) \ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, priority) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_RSP_GET_RX_QUEUE(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, attr->dest_cfg.dest_id);\ ++ MC_RSP_OP(cmd, 0, 32, 8, uint8_t, attr->dest_cfg.priority);\ ++ MC_RSP_OP(cmd, 0, 48, 4, enum dpci_dest, attr->dest_cfg.dest_type);\ ++ MC_RSP_OP(cmd, 1, 0, 8, uint64_t, attr->user_ctx);\ ++ MC_RSP_OP(cmd, 2, 0, 32, uint32_t, attr->fqid);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_CMD_GET_TX_QUEUE(cmd, priority) \ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, priority) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_RSP_GET_TX_QUEUE(cmd, attr) \ ++ MC_RSP_OP(cmd, 0, 32, 32, uint32_t, attr->fqid) ++ ++#endif /* _FSL_DPCI_CMD_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpcon.h b/drivers/net/dpaa2/mc/fsl_dpcon.h +new file mode 100644 +index 0000000..2555be5 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpcon.h +@@ -0,0 +1,407 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPCON_H ++#define __FSL_DPCON_H ++ ++/* Data Path Concentrator API ++ * Contains initialization APIs and runtime control APIs for DPCON ++ */ ++ ++struct fsl_mc_io; ++ ++/** General DPCON macros */ ++ ++/** ++ * Use it to disable notifications; see dpcon_set_notification() ++ */ ++#define DPCON_INVALID_DPIO_ID (int)(-1) ++ ++/** ++ * dpcon_open() - Open a control session for the specified object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @dpcon_id: DPCON unique ID ++ * @token: Returned token; use in subsequent API calls ++ * ++ * This function can be used to open a control session for an ++ * already created object; an object may have been declared in ++ * the DPL or by calling the dpcon_create() function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent commands for ++ * this specific object. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpcon_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpcon_id, ++ uint16_t *token); ++ ++/** ++ * dpcon_close() - Close the control session of the object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * ++ * After this function is called, no further operations are ++ * allowed on the object without opening a new control session. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpcon_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * struct dpcon_cfg - Structure representing DPCON configuration ++ * @num_priorities: Number of priorities for the DPCON channel (1-8) ++ */ ++struct dpcon_cfg { ++ uint8_t num_priorities; ++}; ++ ++/** ++ * dpcon_create() - Create the DPCON object. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @cfg: Configuration structure ++ * @token: Returned token; use in subsequent API calls ++ * ++ * Create the DPCON object, allocate required resources and ++ * perform required initialization. ++ * ++ * The object can be created either by declaring it in the ++ * DPL file, or by calling this function. ++ * ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent calls to ++ * this specific object. For objects that are created using the ++ * DPL file, call dpcon_open() function to get an authentication ++ * token first. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpcon_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpcon_cfg *cfg, ++ uint16_t *token); ++ ++/** ++ * dpcon_destroy() - Destroy the DPCON object and release all its resources. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpcon_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpcon_enable() - Enable the DPCON ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * ++ * Return: '0' on Success; Error code otherwise ++ */ ++int dpcon_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpcon_disable() - Disable the DPCON ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * ++ * Return: '0' on Success; Error code otherwise ++ */ ++int dpcon_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpcon_is_enabled() - Check if the DPCON is enabled. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * @en: Returns '1' if object is enabled; '0' otherwise ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpcon_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en); ++ ++/** ++ * dpcon_reset() - Reset the DPCON, returns the object to initial state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpcon_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * struct dpcon_irq_cfg - IRQ configuration ++ * @addr: Address that must be written to signal a message-based interrupt ++ * @val: Value to write into irq_addr address ++ * @irq_num: A user defined number associated with this IRQ ++ */ ++struct dpcon_irq_cfg { ++ uint64_t addr; ++ uint32_t val; ++ int irq_num; ++}; ++ ++/** ++ * dpcon_set_irq() - Set IRQ information for the DPCON to trigger an interrupt. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * @irq_index: Identifies the interrupt index to configure ++ * @irq_cfg: IRQ configuration ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpcon_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpcon_irq_cfg *irq_cfg); ++ ++/** ++ * dpcon_get_irq() - Get IRQ information from the DPCON. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * @irq_index: The interrupt index to configure ++ * @type: Interrupt type: 0 represents message interrupt ++ * type (both irq_addr and irq_val are valid) ++ * @irq_cfg: IRQ attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpcon_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpcon_irq_cfg *irq_cfg); ++ ++/** ++ * dpcon_set_irq_enable() - Set overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * @irq_index: The interrupt index to configure ++ * @en: Interrupt state - enable = 1, disable = 0 ++ * ++ * Allows GPP software to control when interrupts are generated. ++ * Each interrupt can have up to 32 causes. The enable/disable control's the ++ * overall interrupt state. if the interrupt is disabled no causes will cause ++ * an interrupt. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpcon_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en); ++ ++/** ++ * dpcon_get_irq_enable() - Get overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * @irq_index: The interrupt index to configure ++ * @en: Returned interrupt state - enable = 1, disable = 0 ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpcon_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en); ++ ++/** ++ * dpcon_set_irq_mask() - Set interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * @irq_index: The interrupt index to configure ++ * @mask: Event mask to trigger interrupt; ++ * each bit: ++ * 0 = ignore event ++ * 1 = consider event for asserting IRQ ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpcon_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask); ++ ++/** ++ * dpcon_get_irq_mask() - Get interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * @irq_index: The interrupt index to configure ++ * @mask: Returned event mask to trigger interrupt ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpcon_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask); ++ ++/** ++ * dpcon_get_irq_status() - Get the current status of any pending interrupts. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * @irq_index: The interrupt index to configure ++ * @status: interrupts status - one bit per cause: ++ * 0 = no interrupt pending ++ * 1 = interrupt pending ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpcon_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status); ++ ++/** ++ * dpcon_clear_irq_status() - Clear a pending interrupt's status ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * @irq_index: The interrupt index to configure ++ * @status: bits to clear (W1C) - one bit per cause: ++ * 0 = don't change ++ * 1 = clear status bit ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpcon_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status); ++ ++/** ++ * struct dpcon_attr - Structure representing DPCON attributes ++ * @id: DPCON object ID ++ * @version: DPCON version ++ * @qbman_ch_id: Channel ID to be used by dequeue operation ++ * @num_priorities: Number of priorities for the DPCON channel (1-8) ++ */ ++struct dpcon_attr { ++ int id; ++ /** ++ * struct version - DPCON version ++ * @major: DPCON major version ++ * @minor: DPCON minor version ++ */ ++ struct { ++ uint16_t major; ++ uint16_t minor; ++ } version; ++ uint16_t qbman_ch_id; ++ uint8_t num_priorities; ++}; ++ ++/** ++ * dpcon_get_attributes() - Retrieve DPCON attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * @attr: Object's attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpcon_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpcon_attr *attr); ++ ++/** ++ * struct dpcon_notification_cfg - Structure representing notification parameters ++ * @dpio_id: DPIO object ID; must be configured with a notification channel; ++ * to disable notifications set it to 'DPCON_INVALID_DPIO_ID'; ++ * @priority: Priority selection within the DPIO channel; valid values ++ * are 0-7, depending on the number of priorities in that channel ++ * @user_ctx: User context value provided with each CDAN message ++ */ ++struct dpcon_notification_cfg { ++ int dpio_id; ++ uint8_t priority; ++ uint64_t user_ctx; ++}; ++ ++/** ++ * dpcon_set_notification() - Set DPCON notification destination ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * @cfg: Notification parameters ++ * ++ * Return: '0' on Success; Error code otherwise ++ */ ++int dpcon_set_notification(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpcon_notification_cfg *cfg); ++ ++#endif /* __FSL_DPCON_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpcon_cmd.h b/drivers/net/dpaa2/mc/fsl_dpcon_cmd.h +new file mode 100644 +index 0000000..ecb40d0 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpcon_cmd.h +@@ -0,0 +1,162 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_DPCON_CMD_H ++#define _FSL_DPCON_CMD_H ++ ++/* DPCON Version */ ++#define DPCON_VER_MAJOR 2 ++#define DPCON_VER_MINOR 2 ++ ++/* Command IDs */ ++#define DPCON_CMDID_CLOSE 0x800 ++#define DPCON_CMDID_OPEN 0x808 ++#define DPCON_CMDID_CREATE 0x908 ++#define DPCON_CMDID_DESTROY 0x900 ++ ++#define DPCON_CMDID_ENABLE 0x002 ++#define DPCON_CMDID_DISABLE 0x003 ++#define DPCON_CMDID_GET_ATTR 0x004 ++#define DPCON_CMDID_RESET 0x005 ++#define DPCON_CMDID_IS_ENABLED 0x006 ++ ++#define DPCON_CMDID_SET_IRQ 0x010 ++#define DPCON_CMDID_GET_IRQ 0x011 ++#define DPCON_CMDID_SET_IRQ_ENABLE 0x012 ++#define DPCON_CMDID_GET_IRQ_ENABLE 0x013 ++#define DPCON_CMDID_SET_IRQ_MASK 0x014 ++#define DPCON_CMDID_GET_IRQ_MASK 0x015 ++#define DPCON_CMDID_GET_IRQ_STATUS 0x016 ++#define DPCON_CMDID_CLEAR_IRQ_STATUS 0x017 ++ ++#define DPCON_CMDID_SET_NOTIFICATION 0x100 ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCON_CMD_OPEN(cmd, dpcon_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpcon_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCON_CMD_CREATE(cmd, cfg) \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, cfg->num_priorities) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCON_RSP_IS_ENABLED(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCON_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, irq_index);\ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, irq_cfg->val);\ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\ ++ MC_CMD_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCON_CMD_GET_IRQ(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCON_RSP_GET_IRQ(cmd, type, irq_cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val);\ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\ ++ MC_RSP_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, type);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCON_CMD_SET_IRQ_ENABLE(cmd, irq_index, en) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, en); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCON_CMD_GET_IRQ_ENABLE(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCON_RSP_GET_IRQ_ENABLE(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 8, uint8_t, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCON_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, mask); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCON_CMD_GET_IRQ_MASK(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCON_RSP_GET_IRQ_MASK(cmd, mask) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mask) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCON_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCON_RSP_GET_IRQ_STATUS(cmd, status) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, status) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCON_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCON_RSP_GET_ATTR(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, attr->id);\ ++ MC_RSP_OP(cmd, 0, 32, 16, uint16_t, attr->qbman_ch_id);\ ++ MC_RSP_OP(cmd, 0, 48, 8, uint8_t, attr->num_priorities);\ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->version.major);\ ++ MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->version.minor);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCON_CMD_SET_NOTIFICATION(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, cfg->dpio_id);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->priority);\ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->user_ctx);\ ++} while (0) ++ ++#endif /* _FSL_DPCON_CMD_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpdbg.h b/drivers/net/dpaa2/mc/fsl_dpdbg.h +new file mode 100644 +index 0000000..ead22e8 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpdbg.h +@@ -0,0 +1,635 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPDBG_H ++#define __FSL_DPDBG_H ++ ++#include ++#include ++#include ++ ++/* Data Path Debug API ++ * Contains initialization APIs and runtime control APIs for DPDBG ++ */ ++ ++struct fsl_mc_io; ++ ++/** ++ * dpdbg_open() - Open a control session for the specified object. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @dpdbg_id: DPDBG unique ID ++ * @token: Returned token; use in subsequent API calls ++ * ++ * This function can be used to open a control session for an ++ * already created object; ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent commands for ++ * this specific object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpdbg_id, ++ uint16_t *token); ++ ++/** ++ * dpdbg_close() - Close the control session of the object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * ++ * After this function is called, no further operations are ++ * allowed on the object without opening a new control session. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * struct dpdbg_attr - Structure representing DPDBG attributes ++ * @id: DPDBG object ID ++ * @version: DPDBG version ++ */ ++struct dpdbg_attr { ++ int id; ++ /** ++ * struct version - Structure representing DPDBG version ++ * @major: DPDBG major version ++ * @minor: DPDBG minor version ++ */ ++ struct { ++ uint16_t major; ++ uint16_t minor; ++ } version; ++}; ++ ++/** ++ * dpdbg_get_attributes - Retrieve DPDBG attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * @attr: Returned object's attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpdbg_attr *attr); ++ ++/** ++ * struct dpdbg_dpni_info - Info of DPNI ++ * @max_senders: Maximum number of different senders; used as the number ++ * of dedicated Tx flows; Non-power-of-2 values are rounded ++ * up to the next power-of-2 value as hardware demands it; ++ * '0' will be treated as '1' ++ * @qdid: Virtual QDID. ++ * @err_fqid: Virtual FQID for error queues ++ * @tx_conf_fqid: Virtual FQID for global TX confirmation queue ++ */ ++struct dpdbg_dpni_info { ++ uint8_t max_senders; ++ uint32_t qdid; ++ uint32_t err_fqid; ++ uint32_t tx_conf_fqid; ++}; ++ ++/** ++ * dpdbg_get_dpni_info() - Retrieve info for a specific DPNI ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * @dpni_id: The requested DPNI ID ++ * @info: The returned info ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_get_dpni_info(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpni_id, ++ struct dpdbg_dpni_info *info); ++ ++/** ++ * dpdbg_get_dpni_private_fqid() - Retrieve the virtual TX confirmation queue ++ * FQID of the required DPNI ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * @dpni_id: The requested DPNI ID ++ * @sender_id: The requested sender ID ++ * @fqid: The returned virtual private TX confirmation FQID. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_get_dpni_priv_tx_conf_fqid(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpni_id, ++ uint8_t sender_id, ++ uint32_t *fqid); ++ ++/** ++ * struct dpdbg_dpcon_info - Info of DPCON ++ * @ch_id: Channel ID ++ */ ++struct dpdbg_dpcon_info { ++ uint32_t ch_id; ++}; ++ ++/** ++ * dpdbg_get_dpcon_info() - Retrieve info of DPCON ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * @dpcon_id: The requested DPCON ID ++ * @info: The returned info. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_get_dpcon_info(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpcon_id, ++ struct dpdbg_dpcon_info *info); ++ ++/** ++ * struct dpdbg_dpbp_info - Info of DPBP ++ * @bpid: Virtual buffer pool ID ++ */ ++struct dpdbg_dpbp_info { ++ uint32_t bpid; ++}; ++ ++/** ++ * dpdbg_get_dpbp_info() - Retrieve info of DPBP ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * @dpbp_id: The requested DPBP ID ++ * @info: The returned info. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_get_dpbp_info(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpbp_id, ++ struct dpdbg_dpbp_info *info); ++ ++/** ++ * dpdbg_get_dpci_fqid() - Retrieve the virtual FQID of the required DPCI ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * @dpci_id: The requested DPCI ID ++ * @priority: Select the queue relative to number of priorities configured at ++ * DPCI creation ++ * @fqid: The returned virtual FQID. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_get_dpci_fqid(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpci_id, ++ uint8_t priority, ++ uint32_t *fqid); ++ ++/** ++ * Maximum size for rule match (in bytes) ++ */ ++#define DPDBG_MAX_RULE_SIZE 56 ++/** ++ * Disable marking ++ */ ++#define DPDBG_DISABLE_MARKING 0xFF ++ ++/** ++ * dpdbg_prepare_ctlu_global_rule() - function prepare extract parameters ++ * @dpkg_rule: defining a full Key Generation profile (rule) ++ * @rule_buf: Zeroed 256 bytes of memory before mapping it to DMA ++ * ++ * This function has to be called before dpdbg_set_global_marking() ++ */ ++int dpdbg_prepare_ctlu_global_rule(struct dpkg_profile_cfg *dpkg_rule, ++ uint8_t *rule_buf); ++ ++/** ++ * struct dpdbg_rule_cfg - Rule configuration for table lookup ++ * @key_iova: I/O virtual address of the key (must be in DMA-able memory) ++ * @rule_iova: I/O virtual address of the rule (must be in DMA-able memory) ++ * @mask_iova: I/O virtual address of the mask (must be in DMA-able memory) ++ * @key_size: key and mask size (in bytes) ++ */ ++struct dpdbg_rule_cfg { ++ uint64_t key_iova; ++ uint64_t mask_iova; ++ uint64_t rule_iova; ++ uint8_t key_size; ++}; ++ ++/** ++ * dpdbg_set_ctlu_global_marking() - Set marking for all match rule frames ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * @marking: The requested Debug marking ++ * @cfg: Marking rule to add ++ * ++ * Warning: must be called after dpdbg_prepare_global_rule() ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_set_ctlu_global_marking(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t marking, ++ struct dpdbg_rule_cfg *cfg); ++ ++/** ++ * All traffic classes considered ++ */ ++#define DPDBG_DPNI_ALL_TCS (uint8_t)(-1) ++/** ++ * All flows within traffic class considered ++ */ ++#define DPDBG_DPNI_ALL_TC_FLOWS (uint8_t)(-1) ++/** ++ * All buffer pools considered ++ */ ++#define DPDBG_DPNI_ALL_DPBP (uint8_t)(-1) ++ ++/** ++ * struct dpdbg_dpni_rx_marking_cfg - Ingress frame configuration ++ * @tc_id: Traffic class ID (0-7); DPDBG_DPNI_ALL_TCS for all traffic classes. ++ * @flow_id: Rx flow id within the traffic class; use ++ * 'DPDBG_DPNI_ALL_TC_FLOWS' to set all flows within this tc_id; ++ * ignored if tc_id is set to 'DPDBG_DPNI_ALL_TCS'; ++ * @dpbp_id: buffer pool ID; 'DPDBG_DPNI_ALL_DPBP' to set all DPBP ++ * @marking: Marking for match frames; ++ * 'DPDBG_DISABLE_MARKING' for disable marking ++ */ ++struct dpdbg_dpni_rx_marking_cfg { ++ uint8_t tc_id; ++ uint16_t flow_id; ++ uint16_t dpbp_id; ++ uint8_t marking; ++}; ++ ++/** ++ * dpdbg_set_dpni_rx_marking() - Set Rx frame marking for DPNI ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * @dpni_id: The requested DPNI ID ++ * @cfg: RX frame marking configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_set_dpni_rx_marking(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpni_id, ++ struct dpdbg_dpni_rx_marking_cfg *cfg); ++ ++/* selects global confirmation queues */ ++#define DPDBG_DPNI_GLOBAL_TX_CONF_QUEUE (uint16_t)(-1) ++ ++/** ++ * dpdbg_set_dpni_tx_conf_marking() - Set Tx frame marking for DPNI ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * @dpni_id: The requested DPNI ID ++ * @sender_id: Sender Id for the confirmation queue; ++ * 'DPDBG_DPNI_GLOBAL_TX_CONF_QUEUE' for global confirmation queue ++ * @marking: The requested marking; ++ * 'DPDBG_DISABLE_MARKING' for disable marking ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_set_dpni_tx_conf_marking(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpni_id, ++ uint16_t sender_id, ++ uint8_t marking); ++ ++/** ++ * dpdbg_set_dpio_marking() - Set debug frame marking on enqueue ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * @dpio_id: The requested DPIO ID ++ * @marking: The requested marking; ++ * 'DPDBG_DISABLE_MARKING' for disable marking ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_set_dpio_marking(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpio_id, ++ uint8_t marking); ++ ++/** ++ * enum dpdbg_verbosity_level - Trace verbosity level ++ * @DPDBG_VERBOSITY_LEVEL_DISABLE: Trace disabled ++ * @DPDBG_VERBOSITY_LEVEL_TERSE: Terse trace ++ * @DPDBG_VERBOSITY_LEVEL_VERBOSE: Verbose trace ++ */ ++enum dpdbg_verbosity_level { ++ DPDBG_VERBOSITY_LEVEL_DISABLE = 0, ++ DPDBG_VERBOSITY_LEVEL_TERSE, ++ DPDBG_VERBOSITY_LEVEL_VERBOSE ++}; ++ ++/** ++ * dpdbg_set_ctlu_global_trace() - Set global trace configuration for CTLU trace ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * @cfg: trace rule to add ++ * ++ * Warning: must be called after dpdbg_prepare_global_rule() ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_set_ctlu_global_trace(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpdbg_rule_cfg *cfg); ++ ++/** ++ * Number of DPIO trace points ++ */ ++#define DPDBG_NUM_OF_DPIO_TRACE_POINTS 2 ++ ++/** ++ * enum dpdbg_dpio_trace_type - Define Trace point type ++ * @DPDBG_DPIO_TRACE_TYPE_ENQUEUE: This trace point triggers when an enqueue ++ * command, received via this portal, ++ * and containing a marked frame, is executed ++ * @DPDBG_DPIO_TRACE_TYPE_DEFERRED: This trace point triggers when the deferred ++ * enqueue of a marked frame received via this ++ * portal completes ++ */ ++enum dpdbg_dpio_trace_type { ++ DPDBG_DPIO_TRACE_TYPE_ENQUEUE = 0, ++ DPDBG_DPIO_TRACE_TYPE_DEFERRED = 1 ++}; ++ ++/** ++ * struct dpdbg_dpio_trace_cfg - Configure the behavior of a trace point ++ * when a frame marked with the specified DD code point is ++ * encountered ++ * @marking: this field will be written into the DD field of every FD ++ * enqueued in this DPIO. ++ * 'DPDBG_DISABLE_MARKING' for disable marking ++ * @verbosity: Verbosity level ++ * @enqueue_type: Enqueue trace point type defining a full Key Generation ++ * profile (rule) ++ */ ++struct dpdbg_dpio_trace_cfg { ++ uint8_t marking; ++ enum dpdbg_verbosity_level verbosity; ++ enum dpdbg_dpio_trace_type enqueue_type; ++}; ++ ++/** ++ * dpdbg_set_dpio_trace() - Set trace for DPIO for every enqueued frame to ++ * the portal ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * @dpio_id: The requested DPIO ID ++ * @trace_point: Trace points configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_set_dpio_trace(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpio_id, ++ struct dpdbg_dpio_trace_cfg ++ trace_point[DPDBG_NUM_OF_DPIO_TRACE_POINTS]); ++ ++/** ++ * struct dpdbg_dpni_trace_cfg - Configure the behavior of a trace point when a ++ * @tc_id: Traffic class ID (0-7); DPDBG_DPNI_ALL_TCS for all traffic classes. ++ * @flow_id: Rx flow id within the traffic class; use ++ * 'DPDBG_DPNI_ALL_TC_FLOWS' to set all flows within this tc_id; ++ * ignored if tc_id is set to 'DPDBG_DPNI_ALL_TCS'; ++ * @dpbp_id: buffer pool ID; 'DPDBG_DPNI_ALL_DPBP' to set all DPBP ++ * @marking: Marking for match frames; ++ * 'DPDBG_DISABLE_MARKING' for disable marking ++ */ ++struct dpdbg_dpni_rx_trace_cfg { ++ uint8_t tc_id; ++ uint16_t flow_id; ++ uint16_t dpbp_id; ++ uint8_t marking; ++}; ++ ++/** ++ * dpdbg_set_dpni_rx_trace() - Set trace for DPNI ingress (WRIOP ingress). ++ * in case of multiple requests for different DPNIs - the trace ++ * will be for the latest DPNI requested. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * @dpni_id: The requested DPNI ID ++ * @trace_cfg: Trace configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_set_dpni_rx_trace(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpni_id, ++ struct dpdbg_dpni_rx_trace_cfg *trace_cfg); ++ ++/** ++ * All DPNI senders ++ */ ++#define DPDBG_DPNI_ALL_SENDERS (uint16_t)(-1) ++ ++/** ++ * struct dpdbg_dpni_trace_cfg - Configure the behavior of a trace point when a ++ * frame marked with the specified DD code point is encountered ++ * @marking: The requested debug marking; ++ * 'DPDBG_DISABLE_MARKING' for disable marking ++ */ ++struct dpdbg_dpni_tx_trace_cfg { ++ uint8_t marking; ++}; ++ ++/** ++ * dpdbg_set_dpni_tx_trace() - Set trace for DPNI dequeued frames ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * @dpni_id: The requested DPNI ID ++ * @sender_id: Sender ID; 'DPDBG_DPNI_ALL_SENDERS' for all senders ++ * @trace_cfg: Trace configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_set_dpni_tx_trace(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpni_id, ++ uint16_t sender_id, ++ struct dpdbg_dpni_tx_trace_cfg *trace_cfg); ++ ++/** ++ * Number of DPCON trace points ++ */ ++#define DPDBG_NUM_OF_DPCON_TRACE_POINTS 2 ++ ++/** ++ * struct dpdbg_dpcon_trace_cfg - Configure the behavior of a trace point when a ++ * frame marked with the specified DD code point is encountered ++ * @marking: The requested debug marking; ++ * 'DPDBG_DISABLE_MARKING' for disable marking ++ * @verbosity: Verbosity level ++ */ ++struct dpdbg_dpcon_trace_cfg { ++ uint8_t marking; ++ enum dpdbg_verbosity_level verbosity; ++}; ++ ++/** ++ * dpdbg_set_dpcon_trace() - Set trace for DPCON when a frame marked with a ++ * specified marking is dequeued from a WQ in the ++ * channel selected ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * @dpcon_id: The requested DPCON ID ++ * @trace_point: Trace points configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_set_dpcon_trace(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpcon_id, ++ struct dpdbg_dpcon_trace_cfg ++ trace_point[DPDBG_NUM_OF_DPCON_TRACE_POINTS]); ++ ++/** ++ * Number of DPSECI trace points ++ */ ++#define DPDBG_NUM_OF_DPSECI_TRACE_POINTS 2 ++ ++/** ++ * struct dpdbg_dpseci_trace_cfg - Configure the behavior of a trace point when ++ * a frame marked with the specified DD code point is ++ * encountered ++ * @marking: The requested debug marking; ++ * 'DPDBG_DISABLE_MARKING' for disable marking ++ * @verbosity: Verbosity level ++ */ ++struct dpdbg_dpseci_trace_cfg { ++ uint8_t marking; ++ enum dpdbg_verbosity_level verbosity; ++}; ++ ++/** ++ * dpdbg_set_dpseci_trace() - Set trace for DPSECI when a frame marked with the ++ * specific marking is enqueued via this portal. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * @dpseci_id: The requested DPSECI ID ++ * @trace_point: Trace points configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_set_dpseci_trace(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpseci_id, ++ struct dpdbg_dpseci_trace_cfg ++ trace_point[DPDBG_NUM_OF_DPSECI_TRACE_POINTS]); ++ ++/** ++ * dpdbg_get_dpmac_counter() - DPMAC packet throughput ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * @dpmac_id: The requested DPMAC ID ++ * @counter_type: The requested DPMAC counter ++ * @counter: Returned counter value ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_get_dpmac_counter(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpmac_id, ++ enum dpmac_counter counter_type, ++ uint64_t *counter); ++ ++/** ++ * dpdbg_get_dpni_counter() - DPNI packet throughput ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * @dpni_id: The requested DPNI ID ++ * @counter_type: The requested DPNI counter ++ * @counter: Returned counter value ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_get_dpni_counter(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpni_id, ++ enum dpni_counter counter_type, ++ uint64_t *counter); ++ ++#endif /* __FSL_DPDBG_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpdbg_cmd.h b/drivers/net/dpaa2/mc/fsl_dpdbg_cmd.h +new file mode 100644 +index 0000000..b672788 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpdbg_cmd.h +@@ -0,0 +1,249 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_DPDBG_CMD_H ++#define _FSL_DPDBG_CMD_H ++ ++/* DPDBG Version */ ++#define DPDBG_VER_MAJOR 1 ++#define DPDBG_VER_MINOR 0 ++ ++/* Command IDs */ ++#define DPDBG_CMDID_CLOSE 0x800 ++#define DPDBG_CMDID_OPEN 0x80F ++ ++#define DPDBG_CMDID_GET_ATTR 0x004 ++ ++#define DPDBG_CMDID_GET_DPNI_INFO 0x130 ++#define DPDBG_CMDID_GET_DPNI_PRIV_TX_CONF_FQID 0x131 ++#define DPDBG_CMDID_GET_DPCON_INFO 0x132 ++#define DPDBG_CMDID_GET_DPBP_INFO 0x133 ++#define DPDBG_CMDID_GET_DPCI_FQID 0x134 ++ ++#define DPDBG_CMDID_SET_CTLU_GLOBAL_MARKING 0x135 ++#define DPDBG_CMDID_SET_DPNI_RX_MARKING 0x136 ++#define DPDBG_CMDID_SET_DPNI_TX_CONF_MARKING 0x137 ++#define DPDBG_CMDID_SET_DPIO_MARKING 0x138 ++ ++#define DPDBG_CMDID_SET_CTLU_GLOBAL_TRACE 0x140 ++#define DPDBG_CMDID_SET_DPIO_TRACE 0x141 ++#define DPDBG_CMDID_SET_DPNI_RX_TRACE 0x142 ++#define DPDBG_CMDID_SET_DPNI_TX_TRACE 0x143 ++#define DPDBG_CMDID_SET_DPCON_TRACE 0x145 ++#define DPDBG_CMDID_SET_DPSECI_TRACE 0x146 ++ ++#define DPDBG_CMDID_GET_DPMAC_COUNTER 0x150 ++#define DPDBG_CMDID_GET_DPNI_COUNTER 0x151 ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_CMD_OPEN(cmd, dpdbg_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpdbg_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_RSP_GET_ATTRIBUTES(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 32, 32, int, attr->id);\ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->version.major);\ ++ MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->version.minor);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_CMD_GET_DPNI_INFO(cmd, dpni_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpni_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_RSP_GET_DPNI_INFO(cmd, info) \ ++do { \ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, info->qdid);\ ++ MC_RSP_OP(cmd, 1, 32, 8, uint8_t, info->max_senders);\ ++ MC_RSP_OP(cmd, 2, 0, 32, uint32_t, info->err_fqid);\ ++ MC_RSP_OP(cmd, 2, 32, 32, uint32_t, info->tx_conf_fqid);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_CMD_GET_DPNI_PRIV_TX_CONF_FQID(cmd, dpni_id, sender_id) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpni_id);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, sender_id);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_RSP_GET_DPNI_PRIV_TX_CONF_FQID(cmd, fqid) \ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, fqid) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_CMD_GET_DPCON_INFO(cmd, dpcon_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpcon_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_RSP_GET_DPCON_INFO(cmd, info) \ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, info->ch_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_CMD_GET_DPBP_INFO(cmd, dpbp_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpbp_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_RSP_GET_DPBP_INFO(cmd, info) \ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, info->bpid) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_CMD_GET_DPCI_FQID(cmd, dpci_id, priority) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpci_id);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, priority);\ ++} while (0) ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_RSP_GET_DPCI_FQID(cmd, fqid) \ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, fqid) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_CMD_SET_CTLU_GLOBAL_MARKING(cmd, marking, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, marking);\ ++ MC_CMD_OP(cmd, 0, 8, 8, uint8_t, cfg->key_size); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->key_iova); \ ++ MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->mask_iova); \ ++ MC_CMD_OP(cmd, 3, 0, 64, uint64_t, cfg->rule_iova); \ ++} while (0) ++ ++#define DPDBG_CMD_SET_DPNI_RX_MARKING(cmd, dpni_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpni_id);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->tc_id);\ ++ MC_CMD_OP(cmd, 0, 48, 16, uint16_t, cfg->flow_id);\ ++ MC_CMD_OP(cmd, 1, 0, 16, uint16_t, cfg->dpbp_id);\ ++ MC_CMD_OP(cmd, 1, 16, 8, uint8_t, cfg->marking);\ ++} while (0) ++ ++#define DPDBG_CMD_SET_DPNI_TX_CONF_MARKING(cmd, dpni_id, sender_id, marking) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpni_id);\ ++ MC_CMD_OP(cmd, 0, 48, 16, uint16_t, sender_id);\ ++ MC_CMD_OP(cmd, 1, 16, 8, uint8_t, marking);\ ++} while (0) ++ ++#define DPDBG_CMD_SET_DPIO_MARKING(cmd, dpio_id, marking) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpio_id);\ ++ MC_CMD_OP(cmd, 1, 16, 8, uint8_t, marking);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_CMD_SET_CTLU_GLOBAL_TRACE(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 8, 8, uint8_t, cfg->key_size); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->key_iova); \ ++ MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->mask_iova); \ ++ MC_CMD_OP(cmd, 3, 0, 64, uint64_t, cfg->rule_iova); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_CMD_SET_DPIO_TRACE(cmd, dpio_id, trace_point) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpio_id);\ ++ MC_CMD_OP(cmd, 1, 0, 4, enum dpdbg_verbosity_level, \ ++ trace_point[0].verbosity); \ ++ MC_CMD_OP(cmd, 1, 4, 4, enum dpdbg_dpio_trace_type, \ ++ trace_point[0].enqueue_type); \ ++ MC_CMD_OP(cmd, 1, 8, 8, uint8_t, trace_point[0].marking); \ ++ MC_CMD_OP(cmd, 1, 32, 4, enum dpdbg_verbosity_level, \ ++ trace_point[1].verbosity); \ ++ MC_CMD_OP(cmd, 1, 36, 4, enum dpdbg_dpio_trace_type, \ ++ trace_point[1].enqueue_type); \ ++ MC_CMD_OP(cmd, 1, 40, 8, uint8_t, trace_point[1].marking); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_CMD_SET_DPNI_RX_TRACE(cmd, dpni_id, trace_cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpni_id);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, trace_cfg->tc_id);\ ++ MC_CMD_OP(cmd, 0, 48, 16, uint16_t, trace_cfg->flow_id);\ ++ MC_CMD_OP(cmd, 1, 0, 16, uint16_t, trace_cfg->dpbp_id);\ ++ MC_CMD_OP(cmd, 1, 16, 8, uint8_t, trace_cfg->marking);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_CMD_SET_DPNI_TX_TRACE(cmd, dpni_id, sender_id, trace_cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpni_id);\ ++ MC_CMD_OP(cmd, 0, 48, 16, uint16_t, sender_id);\ ++ MC_CMD_OP(cmd, 1, 16, 8, uint8_t, trace_cfg->marking);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_CMD_SET_DPCON_TRACE(cmd, dpcon_id, trace_point) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpcon_id);\ ++ MC_CMD_OP(cmd, 1, 0, 4, enum dpdbg_verbosity_level, \ ++ trace_point[0].verbosity); \ ++ MC_CMD_OP(cmd, 1, 8, 8, uint8_t, trace_point[0].marking); \ ++ MC_CMD_OP(cmd, 1, 32, 4, enum dpdbg_verbosity_level, \ ++ trace_point[1].verbosity); \ ++ MC_CMD_OP(cmd, 1, 40, 8, uint8_t, trace_point[1].marking); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_CMD_SET_DPSECI_TRACE(cmd, dpseci_id, trace_point) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpseci_id);\ ++ MC_CMD_OP(cmd, 1, 0, 4, enum dpdbg_verbosity_level, \ ++ trace_point[0].verbosity); \ ++ MC_CMD_OP(cmd, 1, 8, 8, uint8_t, trace_point[0].marking); \ ++ MC_CMD_OP(cmd, 1, 32, 4, enum dpdbg_verbosity_level, \ ++ trace_point[1].verbosity); \ ++ MC_CMD_OP(cmd, 1, 40, 8, uint8_t, trace_point[1].marking); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_CMD_GET_DPMAC_COUNTER(cmd, dpmac_id, counter_type) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpmac_id);\ ++ MC_CMD_OP(cmd, 0, 32, 16, enum dpmac_counter, counter_type);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_RSP_GET_DPMAC_COUNTER(cmd, counter) \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, counter) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_CMD_GET_DPNI_COUNTER(cmd, dpni_id, counter_type) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpni_id);\ ++ MC_CMD_OP(cmd, 0, 32, 16, enum dpni_counter, counter_type);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_RSP_GET_DPNI_COUNTER(cmd, counter) \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, counter) ++ ++#endif /* _FSL_DPDBG_CMD_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpdcei.h b/drivers/net/dpaa2/mc/fsl_dpdcei.h +new file mode 100644 +index 0000000..319795c +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpdcei.h +@@ -0,0 +1,515 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPDCEI_H ++#define __FSL_DPDCEI_H ++ ++/* Data Path DCE Interface API ++ * Contains initialization APIs and runtime control APIs for DPDCEI ++ */ ++ ++struct fsl_mc_io; ++ ++/** General DPDCEI macros */ ++ ++/** ++ * Indicates an invalid frame queue ++ */ ++#define DPDCEI_FQID_NOT_VALID (uint32_t)(-1) ++ ++/** ++ * enum dpdcei_engine - DCE engine block ++ * @DPDCEI_ENGINE_COMPRESSION: Engine compression ++ * @DPDCEI_ENGINE_DECOMPRESSION: Engine decompression ++ */ ++enum dpdcei_engine { ++ DPDCEI_ENGINE_COMPRESSION, ++ DPDCEI_ENGINE_DECOMPRESSION ++}; ++ ++/** ++ * dpdcei_open() - Open a control session for the specified object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDCEI object ++ * @dpdcei_id: DPDCEI unique ID ++ * ++ * This function can be used to open a control session for an ++ * already created object; an object may have been declared in ++ * the DPL or by calling the dpdcei_create() function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent commands for ++ * this specific object. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpdcei_id, ++ uint16_t *token); ++ ++/** ++ * dpdcei_close() - Close the control session of the object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDCEI object ++ * ++ * After this function is called, no further operations are ++ * allowed on the object without opening a new control session. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * struct dpdcei_cfg - Structure representing DPDCEI configuration ++ * @engine: compression or decompression engine to be selected ++ * @priority: Priority for the DCE hardware processing (valid values 1-8). ++ */ ++struct dpdcei_cfg { ++ enum dpdcei_engine engine; ++ uint8_t priority; ++}; ++ ++/** ++ * dpdcei_create() - Create the DPDCEI object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDCEI object ++ * @cfg: configuration parameters ++ * ++ * Create the DPDCEI object, allocate required resources and ++ * perform required initialization. ++ * ++ * The object can be created either by declaring it in the ++ * DPL file, or by calling this function. ++ * ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent calls to ++ * this specific object. For objects that are created using the ++ * DPL file, call dpdcei_open() function to get an authentication ++ * token first. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpdcei_cfg *cfg, ++ uint16_t *token); ++ ++/** ++ * dpdcei_destroy() - Destroy the DPDCEI object and release all its resources. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDCEI object ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpdcei_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpdcei_enable() - Enable the DPDCEI, allow sending and receiving frames. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDCEI object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpdcei_disable() - Disable the DPDCEI, stop sending and receiving frames. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDCEI object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpdcei_is_enabled() - Check if the DPDCEI is enabled. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDCEI object ++ * @en: Return '1' for object enabled/'0' otherwise ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en); ++ ++/** ++ * dpdcei_reset() - Reset the DPDCEI, returns the object to initial state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDCEI object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * struct dpdcei_irq_cfg - IRQ configuration ++ * @addr: Address that must be written to signal a message-based interrupt ++ * @val: Value to write into irq_addr address ++ * @irq_num: A user defined number associated with this IRQ ++ */ ++struct dpdcei_irq_cfg { ++ uint64_t addr; ++ uint32_t val; ++ int irq_num; ++}; ++ ++/** ++ * dpdcei_set_irq() - Set IRQ information for the DPDCEI to trigger an interrupt ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDCEI object ++ * @irq_index: Identifies the interrupt index to configure ++ * @irq_cfg: IRQ configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpdcei_irq_cfg *irq_cfg); ++ ++/** ++ * dpdcei_get_irq() - Get IRQ information from the DPDCEI ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDCEI object ++ * @irq_index: The interrupt index to configure ++ * @type: Interrupt type: 0 represents message interrupt ++ * type (both irq_addr and irq_val are valid) ++ * @irq_cfg: IRQ attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpdcei_irq_cfg *irq_cfg); ++ ++/** ++ * dpdcei_set_irq_enable() - Set overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @irq_index: The interrupt index to configure ++ * @en: Interrupt state - enable = 1, disable = 0 ++ * ++ * Allows GPP software to control when interrupts are generated. ++ * Each interrupt can have up to 32 causes. The enable/disable control's the ++ * overall interrupt state. if the interrupt is disabled no causes will cause ++ * an interrupt ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en); ++ ++/** ++ * dpdcei_get_irq_enable() - Get overall interrupt state ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDCEI object ++ * @irq_index: The interrupt index to configure ++ * @en: Returned Interrupt state - enable = 1, disable = 0 ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en); ++ ++/** ++ * dpdcei_set_irq_mask() - Set interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @irq_index: The interrupt index to configure ++ * @mask: event mask to trigger interrupt; ++ * each bit: ++ * 0 = ignore event ++ * 1 = consider event for asserting IRQ ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask); ++ ++/** ++ * dpdcei_get_irq_mask() - Get interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDCEI object ++ * @irq_index: The interrupt index to configure ++ * @mask: Returned event mask to trigger interrupt ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask); ++ ++/** ++ * dpdcei_get_irq_status() - Get the current status of any pending interrupts ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDCEI object ++ * @irq_index: The interrupt index to configure ++ * @status: Returned interrupts status - one bit per cause: ++ * 0 = no interrupt pending ++ * 1 = interrupt pending ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status); ++ ++/** ++ * dpdcei_clear_irq_status() - Clear a pending interrupt's status ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDCEI object ++ * @irq_index: The interrupt index to configure ++ * @status: bits to clear (W1C) - one bit per cause: ++ * 0 = don't change ++ * 1 = clear status bit ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status); ++/** ++ * struct dpdcei_attr - Structure representing DPDCEI attributes ++ * @id: DPDCEI object ID ++ * @engine: DCE engine block ++ * @version: DPDCEI version ++ */ ++struct dpdcei_attr { ++ int id; ++ enum dpdcei_engine engine; ++ /** ++ * struct version - DPDCEI version ++ * @major: DPDCEI major version ++ * @minor: DPDCEI minor version ++ */ ++ struct { ++ uint16_t major; ++ uint16_t minor; ++ } version; ++}; ++ ++/** ++ * dpdcei_get_attributes() - Retrieve DPDCEI attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDCEI object ++ * @attr: Returned object's attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpdcei_attr *attr); ++ ++/** ++ * enum dpdcei_dest - DPDCEI destination types ++ * @DPDCEI_DEST_NONE: Unassigned destination; The queue is set in parked mode ++ * and does not generate FQDAN notifications; ++ * user is expected to dequeue from the queue based on ++ * polling or other user-defined method ++ * @DPDCEI_DEST_DPIO: The queue is set in schedule mode and generates FQDAN ++ * notifications to the specified DPIO; user is expected to ++ * dequeue from the queue only after notification is ++ * received ++ * @DPDCEI_DEST_DPCON: The queue is set in schedule mode and does not generate ++ * FQDAN notifications, but is connected to the specified ++ * DPCON object; ++ * user is expected to dequeue from the DPCON channel ++ */ ++enum dpdcei_dest { ++ DPDCEI_DEST_NONE = 0, ++ DPDCEI_DEST_DPIO = 1, ++ DPDCEI_DEST_DPCON = 2 ++}; ++ ++/** ++ * struct dpdcei_dest_cfg - Structure representing DPDCEI destination parameters ++ * @dest_type: Destination type ++ * @dest_id: Either DPIO ID or DPCON ID, depending on the destination type ++ * @priority: Priority selection within the DPIO or DPCON channel; valid values ++ * are 0-1 or 0-7, depending on the number of priorities in that ++ * channel; not relevant for 'DPDCEI_DEST_NONE' option ++ */ ++struct dpdcei_dest_cfg { ++ enum dpdcei_dest dest_type; ++ int dest_id; ++ uint8_t priority; ++}; ++ ++/** DPDCEI queue modification options */ ++ ++/** ++ * Select to modify the user's context associated with the queue ++ */ ++#define DPDCEI_QUEUE_OPT_USER_CTX 0x00000001 ++ ++/** ++ * Select to modify the queue's destination ++ */ ++#define DPDCEI_QUEUE_OPT_DEST 0x00000002 ++ ++/** ++ * struct dpdcei_rx_queue_cfg - RX queue configuration ++ * @options: Flags representing the suggested modifications to the queue; ++ * Use any combination of 'DPDCEI_QUEUE_OPT_' flags ++ * @user_ctx: User context value provided in the frame descriptor of each ++ * dequeued frame; ++ * valid only if 'DPDCEI_QUEUE_OPT_USER_CTX' is contained in 'options' ++ * @dest_cfg: Queue destination parameters; ++ * valid only if 'DPDCEI_QUEUE_OPT_DEST' is contained in 'options' ++ */ ++struct dpdcei_rx_queue_cfg { ++ uint32_t options; ++ uint64_t user_ctx; ++ struct dpdcei_dest_cfg dest_cfg; ++}; ++ ++/** ++ * dpdcei_set_rx_queue() - Set Rx queue configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDCEI object ++ * @cfg: Rx queue configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_set_rx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpdcei_rx_queue_cfg *cfg); ++ ++/** ++ * struct dpdcei_rx_queue_attr - Structure representing attributes of Rx queues ++ * @user_ctx: User context value provided in the frame descriptor of each ++ * dequeued frame ++ * @dest_cfg: Queue destination configuration ++ * @fqid: Virtual FQID value to be used for dequeue operations ++ */ ++struct dpdcei_rx_queue_attr { ++ uint64_t user_ctx; ++ struct dpdcei_dest_cfg dest_cfg; ++ uint32_t fqid; ++}; ++ ++/** ++ * dpdcei_get_rx_queue() - Retrieve Rx queue attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDCEI object ++ * @attr: Returned Rx queue attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_get_rx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpdcei_rx_queue_attr *attr); ++ ++/** ++ * struct dpdcei_tx_queue_attr - Structure representing attributes of Tx queues ++ * @fqid: Virtual FQID to be used for sending frames to DCE hardware ++ */ ++struct dpdcei_tx_queue_attr { ++ uint32_t fqid; ++}; ++ ++/** ++ * dpdcei_get_tx_queue() - Retrieve Tx queue attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDCEI object ++ * @attr: Returned Tx queue attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_get_tx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpdcei_tx_queue_attr *attr); ++ ++#endif /* __FSL_DPDCEI_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpdcei_cmd.h b/drivers/net/dpaa2/mc/fsl_dpdcei_cmd.h +new file mode 100644 +index 0000000..8452d88 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpdcei_cmd.h +@@ -0,0 +1,182 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_DPDCEI_CMD_H ++#define _FSL_DPDCEI_CMD_H ++ ++/* DPDCEI Version */ ++#define DPDCEI_VER_MAJOR 1 ++#define DPDCEI_VER_MINOR 2 ++ ++/* Command IDs */ ++#define DPDCEI_CMDID_CLOSE 0x800 ++#define DPDCEI_CMDID_OPEN 0x80D ++#define DPDCEI_CMDID_CREATE 0x90D ++#define DPDCEI_CMDID_DESTROY 0x900 ++ ++#define DPDCEI_CMDID_ENABLE 0x002 ++#define DPDCEI_CMDID_DISABLE 0x003 ++#define DPDCEI_CMDID_GET_ATTR 0x004 ++#define DPDCEI_CMDID_RESET 0x005 ++#define DPDCEI_CMDID_IS_ENABLED 0x006 ++ ++#define DPDCEI_CMDID_SET_IRQ 0x010 ++#define DPDCEI_CMDID_GET_IRQ 0x011 ++#define DPDCEI_CMDID_SET_IRQ_ENABLE 0x012 ++#define DPDCEI_CMDID_GET_IRQ_ENABLE 0x013 ++#define DPDCEI_CMDID_SET_IRQ_MASK 0x014 ++#define DPDCEI_CMDID_GET_IRQ_MASK 0x015 ++#define DPDCEI_CMDID_GET_IRQ_STATUS 0x016 ++#define DPDCEI_CMDID_CLEAR_IRQ_STATUS 0x017 ++ ++#define DPDCEI_CMDID_SET_RX_QUEUE 0x1B0 ++#define DPDCEI_CMDID_GET_RX_QUEUE 0x1B1 ++#define DPDCEI_CMDID_GET_TX_QUEUE 0x1B2 ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_CMD_OPEN(cmd, dpdcei_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpdcei_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_CMD_CREATE(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 8, 8, enum dpdcei_engine, cfg->engine);\ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, cfg->priority);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_RSP_IS_ENABLED(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, irq_index);\ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, irq_cfg->val);\ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\ ++ MC_CMD_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_CMD_GET_IRQ(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_RSP_GET_IRQ(cmd, type, irq_cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\ ++ MC_RSP_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, type); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_CMD_SET_IRQ_ENABLE(cmd, irq_index, enable_state) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, enable_state); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_CMD_GET_IRQ_ENABLE(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_RSP_GET_IRQ_ENABLE(cmd, enable_state) \ ++ MC_RSP_OP(cmd, 0, 0, 8, uint8_t, enable_state) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, mask); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_CMD_GET_IRQ_MASK(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_RSP_GET_IRQ_MASK(cmd, mask) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mask) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_RSP_GET_IRQ_STATUS(cmd, status) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, status) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_RSP_GET_ATTR(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, attr->id); \ ++ MC_RSP_OP(cmd, 0, 32, 8, enum dpdcei_engine, attr->engine); \ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->version.major);\ ++ MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->version.minor);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_CMD_SET_RX_QUEUE(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, cfg->dest_cfg.dest_id); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->dest_cfg.priority); \ ++ MC_CMD_OP(cmd, 0, 48, 4, enum dpdcei_dest, cfg->dest_cfg.dest_type); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->user_ctx); \ ++ MC_CMD_OP(cmd, 2, 0, 32, uint32_t, cfg->options);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_RSP_GET_RX_QUEUE(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, attr->dest_cfg.dest_id);\ ++ MC_RSP_OP(cmd, 0, 32, 8, uint8_t, attr->dest_cfg.priority);\ ++ MC_RSP_OP(cmd, 0, 48, 4, enum dpdcei_dest, attr->dest_cfg.dest_type);\ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, attr->user_ctx);\ ++ MC_RSP_OP(cmd, 2, 0, 32, uint32_t, attr->fqid);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_RSP_GET_TX_QUEUE(cmd, attr) \ ++ MC_RSP_OP(cmd, 0, 32, 32, uint32_t, attr->fqid) ++ ++#endif /* _FSL_DPDCEI_CMD_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpdmai.h b/drivers/net/dpaa2/mc/fsl_dpdmai.h +new file mode 100644 +index 0000000..e931ce1 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpdmai.h +@@ -0,0 +1,521 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPDMAI_H ++#define __FSL_DPDMAI_H ++ ++struct fsl_mc_io; ++ ++/* Data Path DMA Interface API ++ * Contains initialization APIs and runtime control APIs for DPDMAI ++ */ ++ ++/* General DPDMAI macros */ ++ ++/** ++ * Maximum number of Tx/Rx priorities per DPDMAI object ++ */ ++#define DPDMAI_PRIO_NUM 2 ++ ++/** ++ * All queues considered; see dpdmai_set_rx_queue() ++ */ ++#define DPDMAI_ALL_QUEUES (uint8_t)(-1) ++ ++/** ++ * dpdmai_open() - Open a control session for the specified object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @dpdmai_id: DPDMAI unique ID ++ * @token: Returned token; use in subsequent API calls ++ * ++ * This function can be used to open a control session for an ++ * already created object; an object may have been declared in ++ * the DPL or by calling the dpdmai_create() function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent commands for ++ * this specific object. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpdmai_id, ++ uint16_t *token); ++ ++/** ++ * dpdmai_close() - Close the control session of the object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMAI object ++ * ++ * After this function is called, no further operations are ++ * allowed on the object without opening a new control session. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * struct dpdmai_cfg - Structure representing DPDMAI configuration ++ * @priorities: Priorities for the DMA hardware processing; valid priorities are ++ * configured with values 1-8; the entry following last valid entry ++ * should be configured with 0 ++ */ ++struct dpdmai_cfg { ++ uint8_t priorities[DPDMAI_PRIO_NUM]; ++}; ++ ++/** ++ * dpdmai_create() - Create the DPDMAI object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @cfg: Configuration structure ++ * @token: Returned token; use in subsequent API calls ++ * ++ * Create the DPDMAI object, allocate required resources and ++ * perform required initialization. ++ * ++ * The object can be created either by declaring it in the ++ * DPL file, or by calling this function. ++ * ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent calls to ++ * this specific object. For objects that are created using the ++ * DPL file, call dpdmai_open() function to get an authentication ++ * token first. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpdmai_cfg *cfg, ++ uint16_t *token); ++ ++/** ++ * dpdmai_destroy() - Destroy the DPDMAI object and release all its resources. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMAI object ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpdmai_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpdmai_enable() - Enable the DPDMAI, allow sending and receiving frames. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMAI object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpdmai_disable() - Disable the DPDMAI, stop sending and receiving frames. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMAI object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpdmai_is_enabled() - Check if the DPDMAI is enabled. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMAI object ++ * @en: Returns '1' if object is enabled; '0' otherwise ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en); ++ ++/** ++ * dpdmai_reset() - Reset the DPDMAI, returns the object to initial state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMAI object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * struct dpdmai_irq_cfg - IRQ configuration ++ * @addr: Address that must be written to signal a message-based interrupt ++ * @val: Value to write into irq_addr address ++ * @irq_num: A user defined number associated with this IRQ ++ */ ++struct dpdmai_irq_cfg { ++ uint64_t addr; ++ uint32_t val; ++ int irq_num; ++}; ++ ++/** ++ * dpdmai_set_irq() - Set IRQ information for the DPDMAI to trigger an interrupt. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMAI object ++ * @irq_index: Identifies the interrupt index to configure ++ * @irq_cfg: IRQ configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpdmai_irq_cfg *irq_cfg); ++ ++/** ++ * dpdmai_get_irq() - Get IRQ information from the DPDMAI ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMAI object ++ * @irq_index: The interrupt index to configure ++ * @type: Interrupt type: 0 represents message interrupt ++ * type (both irq_addr and irq_val are valid) ++ * @irq_cfg: IRQ attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpdmai_irq_cfg *irq_cfg); ++ ++/** ++ * dpdmai_set_irq_enable() - Set overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMAI object ++ * @irq_index: The interrupt index to configure ++ * @en: Interrupt state - enable = 1, disable = 0 ++ * ++ * Allows GPP software to control when interrupts are generated. ++ * Each interrupt can have up to 32 causes. The enable/disable control's the ++ * overall interrupt state. if the interrupt is disabled no causes will cause ++ * an interrupt ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en); ++ ++/** ++ * dpdmai_get_irq_enable() - Get overall interrupt state ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMAI object ++ * @irq_index: The interrupt index to configure ++ * @en: Returned Interrupt state - enable = 1, disable = 0 ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en); ++ ++/** ++ * dpdmai_set_irq_mask() - Set interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMAI object ++ * @irq_index: The interrupt index to configure ++ * @mask: event mask to trigger interrupt; ++ * each bit: ++ * 0 = ignore event ++ * 1 = consider event for asserting IRQ ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask); ++ ++/** ++ * dpdmai_get_irq_mask() - Get interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMAI object ++ * @irq_index: The interrupt index to configure ++ * @mask: Returned event mask to trigger interrupt ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask); ++ ++/** ++ * dpdmai_get_irq_status() - Get the current status of any pending interrupts ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMAI object ++ * @irq_index: The interrupt index to configure ++ * @status: Returned interrupts status - one bit per cause: ++ * 0 = no interrupt pending ++ * 1 = interrupt pending ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status); ++ ++/** ++ * dpdmai_clear_irq_status() - Clear a pending interrupt's status ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMAI object ++ * @irq_index: The interrupt index to configure ++ * @status: bits to clear (W1C) - one bit per cause: ++ * 0 = don't change ++ * 1 = clear status bit ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status); ++ ++/** ++ * struct dpdmai_attr - Structure representing DPDMAI attributes ++ * @id: DPDMAI object ID ++ * @version: DPDMAI version ++ * @num_of_priorities: number of priorities ++ */ ++struct dpdmai_attr { ++ int id; ++ /** ++ * struct version - DPDMAI version ++ * @major: DPDMAI major version ++ * @minor: DPDMAI minor version ++ */ ++ struct { ++ uint16_t major; ++ uint16_t minor; ++ } version; ++ uint8_t num_of_priorities; ++}; ++ ++/** ++ * dpdmai_get_attributes() - Retrieve DPDMAI attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMAI object ++ * @attr: Returned object's attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpdmai_attr *attr); ++ ++/** ++ * enum dpdmai_dest - DPDMAI destination types ++ * @DPDMAI_DEST_NONE: Unassigned destination; The queue is set in parked mode ++ * and does not generate FQDAN notifications; user is expected to dequeue ++ * from the queue based on polling or other user-defined method ++ * @DPDMAI_DEST_DPIO: The queue is set in schedule mode and generates FQDAN ++ * notifications to the specified DPIO; user is expected to dequeue ++ * from the queue only after notification is received ++ * @DPDMAI_DEST_DPCON: The queue is set in schedule mode and does not generate ++ * FQDAN notifications, but is connected to the specified DPCON object; ++ * user is expected to dequeue from the DPCON channel ++ */ ++enum dpdmai_dest { ++ DPDMAI_DEST_NONE = 0, ++ DPDMAI_DEST_DPIO = 1, ++ DPDMAI_DEST_DPCON = 2 ++}; ++ ++/** ++ * struct dpdmai_dest_cfg - Structure representing DPDMAI destination parameters ++ * @dest_type: Destination type ++ * @dest_id: Either DPIO ID or DPCON ID, depending on the destination type ++ * @priority: Priority selection within the DPIO or DPCON channel; valid values ++ * are 0-1 or 0-7, depending on the number of priorities in that ++ * channel; not relevant for 'DPDMAI_DEST_NONE' option ++ */ ++struct dpdmai_dest_cfg { ++ enum dpdmai_dest dest_type; ++ int dest_id; ++ uint8_t priority; ++}; ++ ++/* DPDMAI queue modification options */ ++ ++/** ++ * Select to modify the user's context associated with the queue ++ */ ++#define DPDMAI_QUEUE_OPT_USER_CTX 0x00000001 ++ ++/** ++ * Select to modify the queue's destination ++ */ ++#define DPDMAI_QUEUE_OPT_DEST 0x00000002 ++ ++/** ++ * struct dpdmai_rx_queue_cfg - DPDMAI RX queue configuration ++ * @options: Flags representing the suggested modifications to the queue; ++ * Use any combination of 'DPDMAI_QUEUE_OPT_' flags ++ * @user_ctx: User context value provided in the frame descriptor of each ++ * dequeued frame; ++ * valid only if 'DPDMAI_QUEUE_OPT_USER_CTX' is contained in 'options' ++ * @dest_cfg: Queue destination parameters; ++ * valid only if 'DPDMAI_QUEUE_OPT_DEST' is contained in 'options' ++ */ ++struct dpdmai_rx_queue_cfg { ++ uint32_t options; ++ uint64_t user_ctx; ++ struct dpdmai_dest_cfg dest_cfg; ++ ++}; ++ ++/** ++ * dpdmai_set_rx_queue() - Set Rx queue configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMAI object ++ * @priority: Select the queue relative to number of ++ * priorities configured at DPDMAI creation; use ++ * DPDMAI_ALL_QUEUES to configure all Rx queues ++ * identically. ++ * @cfg: Rx queue configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_set_rx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t priority, ++ const struct dpdmai_rx_queue_cfg *cfg); ++ ++/** ++ * struct dpdmai_rx_queue_attr - Structure representing attributes of Rx queues ++ * @user_ctx: User context value provided in the frame descriptor of each ++ * dequeued frame ++ * @dest_cfg: Queue destination configuration ++ * @fqid: Virtual FQID value to be used for dequeue operations ++ */ ++struct dpdmai_rx_queue_attr { ++ uint64_t user_ctx; ++ struct dpdmai_dest_cfg dest_cfg; ++ uint32_t fqid; ++}; ++ ++/** ++ * dpdmai_get_rx_queue() - Retrieve Rx queue attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMAI object ++ * @priority: Select the queue relative to number of ++ * priorities configured at DPDMAI creation ++ * @attr: Returned Rx queue attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_get_rx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t priority, ++ struct dpdmai_rx_queue_attr *attr); ++ ++/** ++ * struct dpdmai_tx_queue_attr - Structure representing attributes of Tx queues ++ * @fqid: Virtual FQID to be used for sending frames to DMA hardware ++ */ ++ ++struct dpdmai_tx_queue_attr { ++ uint32_t fqid; ++}; ++ ++/** ++ * dpdmai_get_tx_queue() - Retrieve Tx queue attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMAI object ++ * @priority: Select the queue relative to number of ++ * priorities configured at DPDMAI creation ++ * @attr: Returned Tx queue attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_get_tx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t priority, ++ struct dpdmai_tx_queue_attr *attr); ++ ++#endif /* __FSL_DPDMAI_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpdmai_cmd.h b/drivers/net/dpaa2/mc/fsl_dpdmai_cmd.h +new file mode 100644 +index 0000000..7c4a31a +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpdmai_cmd.h +@@ -0,0 +1,191 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_DPDMAI_CMD_H ++#define _FSL_DPDMAI_CMD_H ++ ++/* DPDMAI Version */ ++#define DPDMAI_VER_MAJOR 2 ++#define DPDMAI_VER_MINOR 2 ++ ++/* Command IDs */ ++#define DPDMAI_CMDID_CLOSE 0x800 ++#define DPDMAI_CMDID_OPEN 0x80E ++#define DPDMAI_CMDID_CREATE 0x90E ++#define DPDMAI_CMDID_DESTROY 0x900 ++ ++#define DPDMAI_CMDID_ENABLE 0x002 ++#define DPDMAI_CMDID_DISABLE 0x003 ++#define DPDMAI_CMDID_GET_ATTR 0x004 ++#define DPDMAI_CMDID_RESET 0x005 ++#define DPDMAI_CMDID_IS_ENABLED 0x006 ++ ++#define DPDMAI_CMDID_SET_IRQ 0x010 ++#define DPDMAI_CMDID_GET_IRQ 0x011 ++#define DPDMAI_CMDID_SET_IRQ_ENABLE 0x012 ++#define DPDMAI_CMDID_GET_IRQ_ENABLE 0x013 ++#define DPDMAI_CMDID_SET_IRQ_MASK 0x014 ++#define DPDMAI_CMDID_GET_IRQ_MASK 0x015 ++#define DPDMAI_CMDID_GET_IRQ_STATUS 0x016 ++#define DPDMAI_CMDID_CLEAR_IRQ_STATUS 0x017 ++ ++#define DPDMAI_CMDID_SET_RX_QUEUE 0x1A0 ++#define DPDMAI_CMDID_GET_RX_QUEUE 0x1A1 ++#define DPDMAI_CMDID_GET_TX_QUEUE 0x1A2 ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_CMD_OPEN(cmd, dpdmai_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpdmai_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_CMD_CREATE(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 8, 8, uint8_t, cfg->priorities[0]);\ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, cfg->priorities[1]);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_RSP_IS_ENABLED(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, irq_index);\ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, irq_cfg->val);\ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\ ++ MC_CMD_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_CMD_GET_IRQ(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_RSP_GET_IRQ(cmd, type, irq_cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\ ++ MC_RSP_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, type); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_CMD_SET_IRQ_ENABLE(cmd, irq_index, enable_state) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, enable_state); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_CMD_GET_IRQ_ENABLE(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_RSP_GET_IRQ_ENABLE(cmd, enable_state) \ ++ MC_RSP_OP(cmd, 0, 0, 8, uint8_t, enable_state) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, mask); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_CMD_GET_IRQ_MASK(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_RSP_GET_IRQ_MASK(cmd, mask) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mask) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_RSP_GET_IRQ_STATUS(cmd, status) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, status) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_RSP_GET_ATTR(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, attr->id); \ ++ MC_RSP_OP(cmd, 0, 32, 8, uint8_t, attr->num_of_priorities); \ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->version.major);\ ++ MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->version.minor);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_CMD_SET_RX_QUEUE(cmd, priority, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, cfg->dest_cfg.dest_id); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->dest_cfg.priority); \ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, priority); \ ++ MC_CMD_OP(cmd, 0, 48, 4, enum dpdmai_dest, cfg->dest_cfg.dest_type); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->user_ctx); \ ++ MC_CMD_OP(cmd, 2, 0, 32, uint32_t, cfg->options);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_CMD_GET_RX_QUEUE(cmd, priority) \ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, priority) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_RSP_GET_RX_QUEUE(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, attr->dest_cfg.dest_id);\ ++ MC_RSP_OP(cmd, 0, 32, 8, uint8_t, attr->dest_cfg.priority);\ ++ MC_RSP_OP(cmd, 0, 48, 4, enum dpdmai_dest, attr->dest_cfg.dest_type);\ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, attr->user_ctx);\ ++ MC_RSP_OP(cmd, 2, 0, 32, uint32_t, attr->fqid);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_CMD_GET_TX_QUEUE(cmd, priority) \ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, priority) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_RSP_GET_TX_QUEUE(cmd, attr) \ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, attr->fqid) ++ ++#endif /* _FSL_DPDMAI_CMD_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpdmux.h b/drivers/net/dpaa2/mc/fsl_dpdmux.h +new file mode 100644 +index 0000000..455a042 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpdmux.h +@@ -0,0 +1,724 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPDMUX_H ++#define __FSL_DPDMUX_H ++ ++#include ++ ++struct fsl_mc_io; ++ ++/* Data Path Demux API ++ * Contains API for handling DPDMUX topology and functionality ++ */ ++ ++/** ++ * dpdmux_open() - Open a control session for the specified object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @dpdmux_id: DPDMUX unique ID ++ * @token: Returned token; use in subsequent API calls ++ * ++ * This function can be used to open a control session for an ++ * already created object; an object may have been declared in ++ * the DPL or by calling the dpdmux_create() function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent commands for ++ * this specific object. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpdmux_id, ++ uint16_t *token); ++ ++/** ++ * dpdmux_close() - Close the control session of the object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * ++ * After this function is called, no further operations are ++ * allowed on the object without opening a new control session. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * DPDMUX general options ++ */ ++ ++/** ++ * Enable bridging between internal interfaces ++ */ ++#define DPDMUX_OPT_BRIDGE_EN 0x0000000000000002ULL ++ ++#define DPDMUX_IRQ_INDEX_IF 0x0000 ++#define DPDMUX_IRQ_INDEX 0x0001 ++ ++/** ++ * IRQ event - Indicates that the link state changed ++ */ ++#define DPDMUX_IRQ_EVENT_LINK_CHANGED 0x0001 ++ ++/** ++ * enum dpdmux_manip - DPDMUX manipulation operations ++ * @DPDMUX_MANIP_NONE: No manipulation on frames ++ * @DPDMUX_MANIP_ADD_REMOVE_S_VLAN: Add S-VLAN on egress, remove it on ingress ++ */ ++enum dpdmux_manip { ++ DPDMUX_MANIP_NONE = 0x0, ++ DPDMUX_MANIP_ADD_REMOVE_S_VLAN = 0x1 ++}; ++ ++/** ++ * enum dpdmux_method - DPDMUX method options ++ * @DPDMUX_METHOD_NONE: no DPDMUX method ++ * @DPDMUX_METHOD_C_VLAN_MAC: DPDMUX based on C-VLAN and MAC address ++ * @DPDMUX_METHOD_MAC: DPDMUX based on MAC address ++ * @DPDMUX_METHOD_C_VLAN: DPDMUX based on C-VLAN ++ * @DPDMUX_METHOD_S_VLAN: DPDMUX based on S-VLAN ++ */ ++enum dpdmux_method { ++ DPDMUX_METHOD_NONE = 0x0, ++ DPDMUX_METHOD_C_VLAN_MAC = 0x1, ++ DPDMUX_METHOD_MAC = 0x2, ++ DPDMUX_METHOD_C_VLAN = 0x3, ++ DPDMUX_METHOD_S_VLAN = 0x4 ++}; ++ ++/** ++ * struct dpdmux_cfg - DPDMUX configuration parameters ++ * @method: Defines the operation method for the DPDMUX address table ++ * @manip: Required manipulation operation ++ * @num_ifs: Number of interfaces (excluding the uplink interface) ++ * @adv: Advanced parameters; default is all zeros; ++ * use this structure to change default settings ++ */ ++struct dpdmux_cfg { ++ enum dpdmux_method method; ++ enum dpdmux_manip manip; ++ uint16_t num_ifs; ++ /** ++ * struct adv - Advanced parameters ++ * @options: DPDMUX options - combination of 'DPDMUX_OPT_' flags ++ * @max_dmat_entries: Maximum entries in DPDMUX address table ++ * 0 - indicates default: 64 entries per interface. ++ * @max_mc_groups: Number of multicast groups in DPDMUX table ++ * 0 - indicates default: 32 multicast groups ++ * @max_vlan_ids: max vlan ids allowed in the system - ++ * relevant only case of working in mac+vlan method. ++ * 0 - indicates default 16 vlan ids. ++ */ ++ struct { ++ uint64_t options; ++ uint16_t max_dmat_entries; ++ uint16_t max_mc_groups; ++ uint16_t max_vlan_ids; ++ } adv; ++}; ++ ++/** ++ * dpdmux_create() - Create the DPDMUX object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @cfg: Configuration structure ++ * @token: Returned token; use in subsequent API calls ++ * ++ * Create the DPDMUX object, allocate required resources and ++ * perform required initialization. ++ * ++ * The object can be created either by declaring it in the ++ * DPL file, or by calling this function. ++ * ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent calls to ++ * this specific object. For objects that are created using the ++ * DPL file, call dpdmux_open() function to get an authentication ++ * token first. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpdmux_cfg *cfg, ++ uint16_t *token); ++ ++/** ++ * dpdmux_destroy() - Destroy the DPDMUX object and release all its resources. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpdmux_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpdmux_enable() - Enable DPDMUX functionality ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpdmux_disable() - Disable DPDMUX functionality ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpdmux_is_enabled() - Check if the DPDMUX is enabled. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * @en: Returns '1' if object is enabled; '0' otherwise ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en); ++ ++/** ++ * dpdmux_reset() - Reset the DPDMUX, returns the object to initial state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * struct dpdmux_irq_cfg - IRQ configuration ++ * @addr: Address that must be written to signal a message-based interrupt ++ * @val: Value to write into irq_addr address ++ * @irq_num: A user defined number associated with this IRQ ++ */ ++struct dpdmux_irq_cfg { ++ uint64_t addr; ++ uint32_t val; ++ int irq_num; ++}; ++ ++/** ++ * dpdmux_set_irq() - Set IRQ information for the DPDMUX to trigger an interrupt. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * @irq_index: Identifies the interrupt index to configure ++ * @irq_cfg: IRQ configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpdmux_irq_cfg *irq_cfg); ++ ++/** ++ * dpdmux_get_irq() - Get IRQ information from the DPDMUX. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * @irq_index: The interrupt index to configure ++ * @type: Interrupt type: 0 represents message interrupt ++ * type (both irq_addr and irq_val are valid) ++ * @irq_cfg: IRQ attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpdmux_irq_cfg *irq_cfg); ++ ++/** ++ * dpdmux_set_irq_enable() - Set overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * @irq_index: The interrupt index to configure ++ * @en: Interrupt state - enable = 1, disable = 0 ++ * ++ * Allows GPP software to control when interrupts are generated. ++ * Each interrupt can have up to 32 causes. The enable/disable control's the ++ * overall interrupt state. if the interrupt is disabled no causes will cause ++ * an interrupt. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en); ++ ++/** ++ * dpdmux_get_irq_enable() - Get overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * @irq_index: The interrupt index to configure ++ * @en: Returned interrupt state - enable = 1, disable = 0 ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en); ++ ++/** ++ * dpdmux_set_irq_mask() - Set interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * @irq_index: The interrupt index to configure ++ * @mask: event mask to trigger interrupt; ++ * each bit: ++ * 0 = ignore event ++ * 1 = consider event for asserting IRQ ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask); ++ ++/** ++ * dpdmux_get_irq_mask() - Get interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * @irq_index: The interrupt index to configure ++ * @mask: Returned event mask to trigger interrupt ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask); ++ ++/** ++ * dpdmux_get_irq_status() - Get the current status of any pending interrupts. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * @irq_index: The interrupt index to configure ++ * @status: Returned interrupts status - one bit per cause: ++ * 0 = no interrupt pending ++ * 1 = interrupt pending ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status); ++ ++/** ++ * dpdmux_clear_irq_status() - Clear a pending interrupt's status ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * @irq_index: The interrupt index to configure ++ * @status: bits to clear (W1C) - one bit per cause: ++ * 0 = don't change ++ * 1 = clear status bit ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status); ++ ++/** ++ * struct dpdmux_attr - Structure representing DPDMUX attributes ++ * @id: DPDMUX object ID ++ * @version: DPDMUX version ++ * @options: Configuration options (bitmap) ++ * @method: DPDMUX address table method ++ * @manip: DPDMUX manipulation type ++ * @num_ifs: Number of interfaces (excluding the uplink interface) ++ * @mem_size: DPDMUX frame storage memory size ++ */ ++struct dpdmux_attr { ++ int id; ++ /** ++ * struct version - DPDMUX version ++ * @major: DPDMUX major version ++ * @minor: DPDMUX minor version ++ */ ++ struct { ++ uint16_t major; ++ uint16_t minor; ++ } version; ++ uint64_t options; ++ enum dpdmux_method method; ++ enum dpdmux_manip manip; ++ uint16_t num_ifs; ++ uint16_t mem_size; ++}; ++ ++/** ++ * dpdmux_get_attributes() - Retrieve DPDMUX attributes ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * @attr: Returned object's attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpdmux_attr *attr); ++ ++/** ++ * dpdmux_ul_set_max_frame_length() - Set the maximum frame length in DPDMUX ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * @max_frame_length: The required maximum frame length ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_ul_set_max_frame_length(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t max_frame_length); ++ ++/** ++ * enum dpdmux_counter_type - Counter types ++ * @DPDMUX_CNT_ING_FRAME: Counts ingress frames ++ * @DPDMUX_CNT_ING_BYTE: Counts ingress bytes ++ * @DPDMUX_CNT_ING_FLTR_FRAME: Counts filtered ingress frames ++ * @DPDMUX_CNT_ING_FRAME_DISCARD: Counts discarded ingress frames ++ * @DPDMUX_CNT_ING_MCAST_FRAME: Counts ingress multicast frames ++ * @DPDMUX_CNT_ING_MCAST_BYTE: Counts ingress multicast bytes ++ * @DPDMUX_CNT_ING_BCAST_FRAME: Counts ingress broadcast frames ++ * @DPDMUX_CNT_ING_BCAST_BYTES: Counts ingress broadcast bytes ++ * @DPDMUX_CNT_EGR_FRAME: Counts egress frames ++ * @DPDMUX_CNT_EGR_BYTE: Counts egress bytes ++ * @DPDMUX_CNT_EGR_FRAME_DISCARD: Counts discarded egress frames ++ */ ++enum dpdmux_counter_type { ++ DPDMUX_CNT_ING_FRAME = 0x0, ++ DPDMUX_CNT_ING_BYTE = 0x1, ++ DPDMUX_CNT_ING_FLTR_FRAME = 0x2, ++ DPDMUX_CNT_ING_FRAME_DISCARD = 0x3, ++ DPDMUX_CNT_ING_MCAST_FRAME = 0x4, ++ DPDMUX_CNT_ING_MCAST_BYTE = 0x5, ++ DPDMUX_CNT_ING_BCAST_FRAME = 0x6, ++ DPDMUX_CNT_ING_BCAST_BYTES = 0x7, ++ DPDMUX_CNT_EGR_FRAME = 0x8, ++ DPDMUX_CNT_EGR_BYTE = 0x9, ++ DPDMUX_CNT_EGR_FRAME_DISCARD = 0xa ++}; ++ ++/** ++ * enum dpdmux_accepted_frames_type - DPDMUX frame types ++ * @DPDMUX_ADMIT_ALL: The device accepts VLAN tagged, untagged and ++ * priority-tagged frames ++ * @DPDMUX_ADMIT_ONLY_VLAN_TAGGED: The device discards untagged frames or ++ * priority-tagged frames that are received on this ++ * interface ++ * @DPDMUX_ADMIT_ONLY_UNTAGGED: Untagged frames or priority-tagged frames ++ * received on this interface are accepted ++ */ ++enum dpdmux_accepted_frames_type { ++ DPDMUX_ADMIT_ALL = 0, ++ DPDMUX_ADMIT_ONLY_VLAN_TAGGED = 1, ++ DPDMUX_ADMIT_ONLY_UNTAGGED = 2 ++}; ++ ++/** ++ * enum dpdmux_action - DPDMUX action for un-accepted frames ++ * @DPDMUX_ACTION_DROP: Drop un-accepted frames ++ * @DPDMUX_ACTION_REDIRECT_TO_CTRL: Redirect un-accepted frames to the ++ * control interface ++ */ ++enum dpdmux_action { ++ DPDMUX_ACTION_DROP = 0, ++ DPDMUX_ACTION_REDIRECT_TO_CTRL = 1 ++}; ++ ++/** ++ * struct dpdmux_accepted_frames - Frame types configuration ++ * @type: Defines ingress accepted frames ++ * @unaccept_act: Defines action on frames not accepted ++ */ ++struct dpdmux_accepted_frames { ++ enum dpdmux_accepted_frames_type type; ++ enum dpdmux_action unaccept_act; ++}; ++ ++/** ++ * dpdmux_if_set_accepted_frames() - Set the accepted frame types ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * @if_id: Interface ID (0 for uplink, or 1-num_ifs); ++ * @cfg: Frame types configuration ++ * ++ * if 'DPDMUX_ADMIT_ONLY_VLAN_TAGGED' is set - untagged frames or ++ * priority-tagged frames are discarded. ++ * if 'DPDMUX_ADMIT_ONLY_UNTAGGED' is set - untagged frames or ++ * priority-tagged frames are accepted. ++ * if 'DPDMUX_ADMIT_ALL' is set (default mode) - all VLAN tagged, ++ * untagged and priority-tagged frame are accepted; ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_if_set_accepted_frames(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpdmux_accepted_frames *cfg); ++ ++/** ++ * struct dpdmux_if_attr - Structure representing frame types configuration ++ * @rate: Configured interface rate (in bits per second) ++ * @enabled: Indicates if interface is enabled ++ * @accept_frame_type: Indicates type of accepted frames for the interface ++ */ ++struct dpdmux_if_attr { ++ uint32_t rate; ++ int enabled; ++ enum dpdmux_accepted_frames_type accept_frame_type; ++}; ++ ++/** ++ * dpdmux_if_get_attributes() - Obtain DPDMUX interface attributes ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * @if_id: Interface ID (0 for uplink, or 1-num_ifs); ++ * @attr: Interface attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_if_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ struct dpdmux_if_attr *attr); ++ ++/** ++ * struct dpdmux_l2_rule - Structure representing L2 rule ++ * @mac_addr: MAC address ++ * @vlan_id: VLAN ID ++ */ ++struct dpdmux_l2_rule { ++ uint8_t mac_addr[6]; ++ uint16_t vlan_id; ++}; ++ ++/** ++ * dpdmux_if_remove_l2_rule() - Remove L2 rule from DPDMUX table ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * @if_id: Destination interface ID ++ * @rule: L2 rule ++ * ++ * Function removes a L2 rule from DPDMUX table ++ * or adds an interface to an existing multicast address ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_if_remove_l2_rule(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpdmux_l2_rule *rule); ++ ++/** ++ * dpdmux_if_add_l2_rule() - Add L2 rule into DPDMUX table ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * @if_id: Destination interface ID ++ * @rule: L2 rule ++ * ++ * Function adds a L2 rule into DPDMUX table ++ * or adds an interface to an existing multicast address ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_if_add_l2_rule(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpdmux_l2_rule *rule); ++ ++/** ++* dpdmux_if_get_counter() - Functions obtains specific counter of an interface ++* @mc_io: Pointer to MC portal's I/O object ++* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++* @token: Token of DPDMUX object ++* @if_id: Interface Id ++* @counter_type: counter type ++* @counter: Returned specific counter information ++* ++* Return: '0' on Success; Error code otherwise. ++*/ ++int dpdmux_if_get_counter(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ enum dpdmux_counter_type counter_type, ++ uint64_t *counter); ++ ++/** ++* dpdmux_ul_reset_counters() - Function resets the uplink counter ++* @mc_io: Pointer to MC portal's I/O object ++* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++* @token: Token of DPDMUX object ++* ++* Return: '0' on Success; Error code otherwise. ++*/ ++int dpdmux_ul_reset_counters(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * Enable auto-negotiation ++ */ ++#define DPDMUX_LINK_OPT_AUTONEG 0x0000000000000001ULL ++/** ++ * Enable half-duplex mode ++ */ ++#define DPDMUX_LINK_OPT_HALF_DUPLEX 0x0000000000000002ULL ++/** ++ * Enable pause frames ++ */ ++#define DPDMUX_LINK_OPT_PAUSE 0x0000000000000004ULL ++/** ++ * Enable a-symmetric pause frames ++ */ ++#define DPDMUX_LINK_OPT_ASYM_PAUSE 0x0000000000000008ULL ++ ++/** ++ * struct dpdmux_link_cfg - Structure representing DPDMUX link configuration ++ * @rate: Rate ++ * @options: Mask of available options; use 'DPDMUX_LINK_OPT_' values ++ */ ++struct dpdmux_link_cfg { ++ uint32_t rate; ++ uint64_t options; ++}; ++ ++/** ++ * dpdmux_if_set_link_cfg() - set the link configuration. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: interface id ++ * @cfg: Link configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_if_set_link_cfg(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ struct dpdmux_link_cfg *cfg); ++/** ++ * struct dpdmux_link_state - Structure representing DPDMUX link state ++ * @rate: Rate ++ * @options: Mask of available options; use 'DPDMUX_LINK_OPT_' values ++ * @up: 0 - down, 1 - up ++ */ ++struct dpdmux_link_state { ++ uint32_t rate; ++ uint64_t options; ++ int up; ++}; ++ ++/** ++ * dpdmux_if_get_link_state - Return the link state ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: interface id ++ * @state: link state ++ * ++ * @returns '0' on Success; Error code otherwise. ++ */ ++int dpdmux_if_get_link_state(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ struct dpdmux_link_state *state); ++ ++#endif /* __FSL_DPDMUX_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpdmux_cmd.h b/drivers/net/dpaa2/mc/fsl_dpdmux_cmd.h +new file mode 100644 +index 0000000..0a5cf17 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpdmux_cmd.h +@@ -0,0 +1,256 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_DPDMUX_CMD_H ++#define _FSL_DPDMUX_CMD_H ++ ++/* DPDMUX Version */ ++#define DPDMUX_VER_MAJOR 5 ++#define DPDMUX_VER_MINOR 0 ++ ++/* Command IDs */ ++#define DPDMUX_CMDID_CLOSE 0x800 ++#define DPDMUX_CMDID_OPEN 0x806 ++#define DPDMUX_CMDID_CREATE 0x906 ++#define DPDMUX_CMDID_DESTROY 0x900 ++ ++#define DPDMUX_CMDID_ENABLE 0x002 ++#define DPDMUX_CMDID_DISABLE 0x003 ++#define DPDMUX_CMDID_GET_ATTR 0x004 ++#define DPDMUX_CMDID_RESET 0x005 ++#define DPDMUX_CMDID_IS_ENABLED 0x006 ++ ++#define DPDMUX_CMDID_SET_IRQ 0x010 ++#define DPDMUX_CMDID_GET_IRQ 0x011 ++#define DPDMUX_CMDID_SET_IRQ_ENABLE 0x012 ++#define DPDMUX_CMDID_GET_IRQ_ENABLE 0x013 ++#define DPDMUX_CMDID_SET_IRQ_MASK 0x014 ++#define DPDMUX_CMDID_GET_IRQ_MASK 0x015 ++#define DPDMUX_CMDID_GET_IRQ_STATUS 0x016 ++#define DPDMUX_CMDID_CLEAR_IRQ_STATUS 0x017 ++ ++#define DPDMUX_CMDID_UL_SET_MAX_FRAME_LENGTH 0x0a1 ++ ++#define DPDMUX_CMDID_UL_RESET_COUNTERS 0x0a3 ++ ++#define DPDMUX_CMDID_IF_SET_ACCEPTED_FRAMES 0x0a7 ++#define DPDMUX_CMDID_IF_GET_ATTR 0x0a8 ++ ++#define DPDMUX_CMDID_IF_ADD_L2_RULE 0x0b0 ++#define DPDMUX_CMDID_IF_REMOVE_L2_RULE 0x0b1 ++#define DPDMUX_CMDID_IF_GET_COUNTER 0x0b2 ++#define DPDMUX_CMDID_IF_SET_LINK_CFG 0x0b3 ++#define DPDMUX_CMDID_IF_GET_LINK_STATE 0x0b4 ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_CMD_OPEN(cmd, dpdmux_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpdmux_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_CMD_CREATE(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, enum dpdmux_method, cfg->method);\ ++ MC_CMD_OP(cmd, 0, 8, 8, enum dpdmux_manip, cfg->manip);\ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->num_ifs);\ ++ MC_CMD_OP(cmd, 1, 0, 16, uint16_t, cfg->adv.max_dmat_entries);\ ++ MC_CMD_OP(cmd, 1, 16, 16, uint16_t, cfg->adv.max_mc_groups);\ ++ MC_CMD_OP(cmd, 1, 32, 16, uint16_t, cfg->adv.max_vlan_ids);\ ++ MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->adv.options);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_RSP_IS_ENABLED(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, irq_index);\ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, irq_cfg->val);\ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\ ++ MC_CMD_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_CMD_GET_IRQ(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_RSP_GET_IRQ(cmd, type, irq_cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr); \ ++ MC_RSP_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, type); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_CMD_SET_IRQ_ENABLE(cmd, irq_index, en) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, en);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_CMD_GET_IRQ_ENABLE(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_RSP_GET_IRQ_ENABLE(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 8, uint8_t, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, mask); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_CMD_GET_IRQ_MASK(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_RSP_GET_IRQ_MASK(cmd, mask) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mask) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_RSP_GET_IRQ_STATUS(cmd, status) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, status) \ ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index); \ ++} while (0) ++ ++#define DPDMUX_RSP_GET_ATTR(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 8, enum dpdmux_method, attr->method);\ ++ MC_RSP_OP(cmd, 0, 8, 8, enum dpdmux_manip, attr->manip);\ ++ MC_RSP_OP(cmd, 0, 16, 16, uint16_t, attr->num_ifs);\ ++ MC_RSP_OP(cmd, 0, 32, 16, uint16_t, attr->mem_size);\ ++ MC_RSP_OP(cmd, 2, 0, 32, int, attr->id);\ ++ MC_RSP_OP(cmd, 3, 0, 64, uint64_t, attr->options);\ ++ MC_RSP_OP(cmd, 4, 0, 16, uint16_t, attr->version.major);\ ++ MC_RSP_OP(cmd, 4, 16, 16, uint16_t, attr->version.minor);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_CMD_UL_SET_MAX_FRAME_LENGTH(cmd, max_frame_length) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, max_frame_length) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_CMD_IF_SET_ACCEPTED_FRAMES(cmd, if_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 16, 4, enum dpdmux_accepted_frames_type, cfg->type);\ ++ MC_CMD_OP(cmd, 0, 20, 4, enum dpdmux_unaccepted_frames_action, \ ++ cfg->unaccept_act);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_CMD_IF_GET_ATTR(cmd, if_id) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_RSP_IF_GET_ATTR(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 56, 4, enum dpdmux_accepted_frames_type, \ ++ attr->accept_frame_type);\ ++ MC_RSP_OP(cmd, 0, 24, 1, int, attr->enabled);\ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, attr->rate);\ ++} while (0) ++ ++#define DPDMUX_CMD_IF_REMOVE_L2_RULE(cmd, if_id, l2_rule) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, l2_rule->mac_addr[5]);\ ++ MC_CMD_OP(cmd, 0, 24, 8, uint8_t, l2_rule->mac_addr[4]);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, l2_rule->mac_addr[3]);\ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, l2_rule->mac_addr[2]);\ ++ MC_CMD_OP(cmd, 0, 48, 8, uint8_t, l2_rule->mac_addr[1]);\ ++ MC_CMD_OP(cmd, 0, 56, 8, uint8_t, l2_rule->mac_addr[0]);\ ++ MC_CMD_OP(cmd, 1, 32, 16, uint16_t, l2_rule->vlan_id);\ ++} while (0) ++ ++#define DPDMUX_CMD_IF_ADD_L2_RULE(cmd, if_id, l2_rule) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, l2_rule->mac_addr[5]);\ ++ MC_CMD_OP(cmd, 0, 24, 8, uint8_t, l2_rule->mac_addr[4]);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, l2_rule->mac_addr[3]);\ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, l2_rule->mac_addr[2]);\ ++ MC_CMD_OP(cmd, 0, 48, 8, uint8_t, l2_rule->mac_addr[1]);\ ++ MC_CMD_OP(cmd, 0, 56, 8, uint8_t, l2_rule->mac_addr[0]);\ ++ MC_CMD_OP(cmd, 1, 32, 16, uint16_t, l2_rule->vlan_id);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_CMD_IF_GET_COUNTER(cmd, if_id, counter_type) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 16, 8, enum dpdmux_counter_type, counter_type);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_RSP_IF_GET_COUNTER(cmd, counter) \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, counter) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_CMD_IF_SET_LINK_CFG(cmd, if_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 1, 0, 32, uint32_t, cfg->rate);\ ++ MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->options);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_CMD_IF_GET_LINK_STATE(cmd, if_id) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_RSP_IF_GET_LINK_STATE(cmd, state) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 32, 1, int, state->up);\ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, state->rate);\ ++ MC_RSP_OP(cmd, 2, 0, 64, uint64_t, state->options);\ ++} while (0) ++ ++#endif /* _FSL_DPDMUX_CMD_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpio.h b/drivers/net/dpaa2/mc/fsl_dpio.h +new file mode 100644 +index 0000000..88a492f +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpio.h +@@ -0,0 +1,460 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPIO_H ++#define __FSL_DPIO_H ++ ++/* Data Path I/O Portal API ++ * Contains initialization APIs and runtime control APIs for DPIO ++ */ ++ ++struct fsl_mc_io; ++ ++/** ++ * dpio_open() - Open a control session for the specified object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @dpio_id: DPIO unique ID ++ * @token: Returned token; use in subsequent API calls ++ * ++ * This function can be used to open a control session for an ++ * already created object; an object may have been declared in ++ * the DPL or by calling the dpio_create() function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent commands for ++ * this specific object. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpio_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpio_id, ++ uint16_t *token); ++ ++/** ++ * dpio_close() - Close the control session of the object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpio_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * enum dpio_channel_mode - DPIO notification channel mode ++ * @DPIO_NO_CHANNEL: No support for notification channel ++ * @DPIO_LOCAL_CHANNEL: Notifications on data availability can be received by a ++ * dedicated channel in the DPIO; user should point the queue's ++ * destination in the relevant interface to this DPIO ++ */ ++enum dpio_channel_mode { ++ DPIO_NO_CHANNEL = 0, ++ DPIO_LOCAL_CHANNEL = 1, ++}; ++ ++/** ++ * struct dpio_cfg - Structure representing DPIO configuration ++ * @channel_mode: Notification channel mode ++ * @num_priorities: Number of priorities for the notification channel (1-8); ++ * relevant only if 'channel_mode = DPIO_LOCAL_CHANNEL' ++ */ ++struct dpio_cfg { ++ enum dpio_channel_mode channel_mode; ++ uint8_t num_priorities; ++}; ++ ++/** ++ * dpio_create() - Create the DPIO object. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @cfg: Configuration structure ++ * @token: Returned token; use in subsequent API calls ++ * ++ * Create the DPIO object, allocate required resources and ++ * perform required initialization. ++ * ++ * The object can be created either by declaring it in the ++ * DPL file, or by calling this function. ++ * ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent calls to ++ * this specific object. For objects that are created using the ++ * DPL file, call dpio_open() function to get an authentication ++ * token first. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpio_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpio_cfg *cfg, ++ uint16_t *token); ++ ++/** ++ * dpio_destroy() - Destroy the DPIO object and release all its resources. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * ++ * Return: '0' on Success; Error code otherwise ++ */ ++int dpio_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpio_enable() - Enable the DPIO, allow I/O portal operations. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * ++ * Return: '0' on Success; Error code otherwise ++ */ ++int dpio_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpio_disable() - Disable the DPIO, stop any I/O portal operation. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * ++ * Return: '0' on Success; Error code otherwise ++ */ ++int dpio_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpio_is_enabled() - Check if the DPIO is enabled. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * @en: Returns '1' if object is enabled; '0' otherwise ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpio_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en); ++ ++/** ++ * dpio_reset() - Reset the DPIO, returns the object to initial state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpio_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpio_set_stashing_destination() - Set the stashing destination. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * @sdest: stashing destination value ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpio_set_stashing_destination(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t sdest); ++ ++/** ++ * dpio_get_stashing_destination() - Get the stashing destination.. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * @sdest: Returns the stashing destination value ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpio_get_stashing_destination(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t *sdest); ++ ++/** ++ * dpio_add_static_dequeue_channel() - Add a static dequeue channel. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * @dpcon_id: DPCON object ID ++ * @channel_index: Returned channel index to be used in qbman API ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpio_add_static_dequeue_channel(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpcon_id, ++ uint8_t *channel_index); ++ ++/** ++ * dpio_remove_static_dequeue_channel() - Remove a static dequeue channel. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * @dpcon_id: DPCON object ID ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpio_remove_static_dequeue_channel(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpcon_id); ++ ++/** ++ * DPIO IRQ Index and Events ++ */ ++ ++/** ++ * Irq software-portal index ++ */ ++#define DPIO_IRQ_SWP_INDEX 0 ++ ++/** ++ * struct dpio_irq_cfg - IRQ configuration ++ * @addr: Address that must be written to signal a message-based interrupt ++ * @val: Value to write into irq_addr address ++ * @irq_num: A user defined number associated with this IRQ ++ */ ++struct dpio_irq_cfg { ++ uint64_t addr; ++ uint32_t val; ++ int irq_num; ++}; ++ ++/** ++ * dpio_set_irq() - Set IRQ information for the DPIO to trigger an interrupt. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * @irq_index: Identifies the interrupt index to configure ++ * @irq_cfg: IRQ configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpio_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpio_irq_cfg *irq_cfg); ++ ++/** ++ * dpio_get_irq() - Get IRQ information from the DPIO. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * @irq_index: The interrupt index to configure ++ * @type: Interrupt type: 0 represents message interrupt ++ * type (both irq_addr and irq_val are valid) ++ * @irq_cfg: IRQ attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpio_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpio_irq_cfg *irq_cfg); ++ ++/** ++ * dpio_set_irq_enable() - Set overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * @irq_index: The interrupt index to configure ++ * @en: Interrupt state - enable = 1, disable = 0 ++ * ++ * Allows GPP software to control when interrupts are generated. ++ * Each interrupt can have up to 32 causes. The enable/disable control's the ++ * overall interrupt state. if the interrupt is disabled no causes will cause ++ * an interrupt. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpio_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en); ++ ++/** ++ * dpio_get_irq_enable() - Get overall interrupt state ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * @irq_index: The interrupt index to configure ++ * @en: Returned interrupt state - enable = 1, disable = 0 ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpio_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en); ++ ++/** ++ * dpio_set_irq_mask() - Set interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * @irq_index: The interrupt index to configure ++ * @mask: event mask to trigger interrupt; ++ * each bit: ++ * 0 = ignore event ++ * 1 = consider event for asserting IRQ ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpio_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask); ++ ++/** ++ * dpio_get_irq_mask() - Get interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * @irq_index: The interrupt index to configure ++ * @mask: Returned event mask to trigger interrupt ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpio_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask); ++ ++/** ++ * dpio_get_irq_status() - Get the current status of any pending interrupts. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * @irq_index: The interrupt index to configure ++ * @status: Returned interrupts status - one bit per cause: ++ * 0 = no interrupt pending ++ * 1 = interrupt pending ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpio_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status); ++ ++/** ++ * dpio_clear_irq_status() - Clear a pending interrupt's status ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * @irq_index: The interrupt index to configure ++ * @status: bits to clear (W1C) - one bit per cause: ++ * 0 = don't change ++ * 1 = clear status bit ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpio_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status); ++ ++/** ++ * struct dpio_attr - Structure representing DPIO attributes ++ * @id: DPIO object ID ++ * @version: DPIO version ++ * @qbman_portal_ce_offset: offset of the software portal cache-enabled area ++ * @qbman_portal_ci_offset: offset of the software portal cache-inhibited area ++ * @qbman_portal_id: Software portal ID ++ * @channel_mode: Notification channel mode ++ * @num_priorities: Number of priorities for the notification channel (1-8); ++ * relevant only if 'channel_mode = DPIO_LOCAL_CHANNEL' ++ * @qbman_version: QBMAN version ++ */ ++struct dpio_attr { ++ int id; ++ /** ++ * struct version - DPIO version ++ * @major: DPIO major version ++ * @minor: DPIO minor version ++ */ ++ struct { ++ uint16_t major; ++ uint16_t minor; ++ } version; ++ uint64_t qbman_portal_ce_offset; ++ uint64_t qbman_portal_ci_offset; ++ uint16_t qbman_portal_id; ++ enum dpio_channel_mode channel_mode; ++ uint8_t num_priorities; ++ uint32_t qbman_version; ++}; ++ ++/** ++ * dpio_get_attributes() - Retrieve DPIO attributes ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * @attr: Returned object's attributes ++ * ++ * Return: '0' on Success; Error code otherwise ++ */ ++int dpio_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpio_attr *attr); ++#endif /* __FSL_DPIO_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpio_cmd.h b/drivers/net/dpaa2/mc/fsl_dpio_cmd.h +new file mode 100644 +index 0000000..f339cd6 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpio_cmd.h +@@ -0,0 +1,184 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_DPIO_CMD_H ++#define _FSL_DPIO_CMD_H ++ ++/* DPIO Version */ ++#define DPIO_VER_MAJOR 3 ++#define DPIO_VER_MINOR 2 ++ ++/* Command IDs */ ++#define DPIO_CMDID_CLOSE 0x800 ++#define DPIO_CMDID_OPEN 0x803 ++#define DPIO_CMDID_CREATE 0x903 ++#define DPIO_CMDID_DESTROY 0x900 ++ ++#define DPIO_CMDID_ENABLE 0x002 ++#define DPIO_CMDID_DISABLE 0x003 ++#define DPIO_CMDID_GET_ATTR 0x004 ++#define DPIO_CMDID_RESET 0x005 ++#define DPIO_CMDID_IS_ENABLED 0x006 ++ ++#define DPIO_CMDID_SET_IRQ 0x010 ++#define DPIO_CMDID_GET_IRQ 0x011 ++#define DPIO_CMDID_SET_IRQ_ENABLE 0x012 ++#define DPIO_CMDID_GET_IRQ_ENABLE 0x013 ++#define DPIO_CMDID_SET_IRQ_MASK 0x014 ++#define DPIO_CMDID_GET_IRQ_MASK 0x015 ++#define DPIO_CMDID_GET_IRQ_STATUS 0x016 ++#define DPIO_CMDID_CLEAR_IRQ_STATUS 0x017 ++ ++#define DPIO_CMDID_SET_STASHING_DEST 0x120 ++#define DPIO_CMDID_GET_STASHING_DEST 0x121 ++#define DPIO_CMDID_ADD_STATIC_DEQUEUE_CHANNEL 0x122 ++#define DPIO_CMDID_REMOVE_STATIC_DEQUEUE_CHANNEL 0x123 ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_CMD_OPEN(cmd, dpio_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpio_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_CMD_CREATE(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 16, 2, enum dpio_channel_mode, \ ++ cfg->channel_mode);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->num_priorities);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_RSP_IS_ENABLED(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, irq_index);\ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, irq_cfg->val);\ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\ ++ MC_CMD_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_CMD_GET_IRQ(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_RSP_GET_IRQ(cmd, type, irq_cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr); \ ++ MC_RSP_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, type); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_CMD_SET_IRQ_ENABLE(cmd, irq_index, en) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, en); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_CMD_GET_IRQ_ENABLE(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_RSP_GET_IRQ_ENABLE(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 8, uint8_t, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, mask); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_CMD_GET_IRQ_MASK(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_RSP_GET_IRQ_MASK(cmd, mask) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mask) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_RSP_GET_IRQ_STATUS(cmd, status) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, status) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_RSP_GET_ATTR(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, attr->id);\ ++ MC_RSP_OP(cmd, 0, 32, 16, uint16_t, attr->qbman_portal_id);\ ++ MC_RSP_OP(cmd, 0, 48, 8, uint8_t, attr->num_priorities);\ ++ MC_RSP_OP(cmd, 0, 56, 4, enum dpio_channel_mode, attr->channel_mode);\ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, attr->qbman_portal_ce_offset);\ ++ MC_RSP_OP(cmd, 2, 0, 64, uint64_t, attr->qbman_portal_ci_offset);\ ++ MC_RSP_OP(cmd, 3, 0, 16, uint16_t, attr->version.major);\ ++ MC_RSP_OP(cmd, 3, 16, 16, uint16_t, attr->version.minor);\ ++ MC_RSP_OP(cmd, 3, 32, 32, uint32_t, attr->qbman_version);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_CMD_SET_STASHING_DEST(cmd, sdest) \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, sdest) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_RSP_GET_STASHING_DEST(cmd, sdest) \ ++ MC_RSP_OP(cmd, 0, 0, 8, uint8_t, sdest) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_CMD_ADD_STATIC_DEQUEUE_CHANNEL(cmd, dpcon_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpcon_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_RSP_ADD_STATIC_DEQUEUE_CHANNEL(cmd, channel_index) \ ++ MC_RSP_OP(cmd, 0, 0, 8, uint8_t, channel_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_CMD_REMOVE_STATIC_DEQUEUE_CHANNEL(cmd, dpcon_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpcon_id) ++#endif /* _FSL_DPIO_CMD_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpkg.h b/drivers/net/dpaa2/mc/fsl_dpkg.h +new file mode 100644 +index 0000000..b2bceaf +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpkg.h +@@ -0,0 +1,174 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPKG_H_ ++#define __FSL_DPKG_H_ ++ ++#include ++ ++/* Data Path Key Generator API ++ * Contains initialization APIs and runtime APIs for the Key Generator ++ */ ++ ++/** Key Generator properties */ ++ ++/** ++ * Number of masks per key extraction ++ */ ++#define DPKG_NUM_OF_MASKS 4 ++/** ++ * Number of extractions per key profile ++ */ ++#define DPKG_MAX_NUM_OF_EXTRACTS 10 ++ ++/** ++ * enum dpkg_extract_from_hdr_type - Selecting extraction by header types ++ * @DPKG_FROM_HDR: Extract selected bytes from header, by offset ++ * @DPKG_FROM_FIELD: Extract selected bytes from header, by offset from field ++ * @DPKG_FULL_FIELD: Extract a full field ++ */ ++enum dpkg_extract_from_hdr_type { ++ DPKG_FROM_HDR = 0, ++ DPKG_FROM_FIELD = 1, ++ DPKG_FULL_FIELD = 2 ++}; ++ ++/** ++ * enum dpkg_extract_type - Enumeration for selecting extraction type ++ * @DPKG_EXTRACT_FROM_HDR: Extract from the header ++ * @DPKG_EXTRACT_FROM_DATA: Extract from data not in specific header ++ * @DPKG_EXTRACT_FROM_PARSE: Extract from parser-result; ++ * e.g. can be used to extract header existence; ++ * please refer to 'Parse Result definition' section in the parser BG ++ */ ++enum dpkg_extract_type { ++ DPKG_EXTRACT_FROM_HDR = 0, ++ DPKG_EXTRACT_FROM_DATA = 1, ++ DPKG_EXTRACT_FROM_PARSE = 3 ++}; ++ ++/** ++ * struct dpkg_mask - A structure for defining a single extraction mask ++ * @mask: Byte mask for the extracted content ++ * @offset: Offset within the extracted content ++ */ ++struct dpkg_mask { ++ uint8_t mask; ++ uint8_t offset; ++}; ++ ++/** ++ * struct dpkg_extract - A structure for defining a single extraction ++ * @type: Determines how the union below is interpreted: ++ * DPKG_EXTRACT_FROM_HDR: selects 'from_hdr'; ++ * DPKG_EXTRACT_FROM_DATA: selects 'from_data'; ++ * DPKG_EXTRACT_FROM_PARSE: selects 'from_parse' ++ * @extract: Selects extraction method ++ * @num_of_byte_masks: Defines the number of valid entries in the array below; ++ * This is also the number of bytes to be used as masks ++ * @masks: Masks parameters ++ */ ++struct dpkg_extract { ++ enum dpkg_extract_type type; ++ /** ++ * union extract - Selects extraction method ++ * @from_hdr - Used when 'type = DPKG_EXTRACT_FROM_HDR' ++ * @from_data - Used when 'type = DPKG_EXTRACT_FROM_DATA' ++ * @from_parse - Used when 'type = DPKG_EXTRACT_FROM_PARSE' ++ */ ++ union { ++ /** ++ * struct from_hdr - Used when 'type = DPKG_EXTRACT_FROM_HDR' ++ * @prot: Any of the supported headers ++ * @type: Defines the type of header extraction: ++ * DPKG_FROM_HDR: use size & offset below; ++ * DPKG_FROM_FIELD: use field, size and offset below; ++ * DPKG_FULL_FIELD: use field below ++ * @field: One of the supported fields (NH_FLD_) ++ * ++ * @size: Size in bytes ++ * @offset: Byte offset ++ * @hdr_index: Clear for cases not listed below; ++ * Used for protocols that may have more than a single ++ * header, 0 indicates an outer header; ++ * Supported protocols (possible values): ++ * NET_PROT_VLAN (0, HDR_INDEX_LAST); ++ * NET_PROT_MPLS (0, 1, HDR_INDEX_LAST); ++ * NET_PROT_IP(0, HDR_INDEX_LAST); ++ * NET_PROT_IPv4(0, HDR_INDEX_LAST); ++ * NET_PROT_IPv6(0, HDR_INDEX_LAST); ++ */ ++ ++ struct { ++ enum net_prot prot; ++ enum dpkg_extract_from_hdr_type type; ++ uint32_t field; ++ uint8_t size; ++ uint8_t offset; ++ uint8_t hdr_index; ++ } from_hdr; ++ /** ++ * struct from_data - Used when 'type = DPKG_EXTRACT_FROM_DATA' ++ * @size: Size in bytes ++ * @offset: Byte offset ++ */ ++ struct { ++ uint8_t size; ++ uint8_t offset; ++ } from_data; ++ ++ /** ++ * struct from_parse - Used when 'type = DPKG_EXTRACT_FROM_PARSE' ++ * @size: Size in bytes ++ * @offset: Byte offset ++ */ ++ struct { ++ uint8_t size; ++ uint8_t offset; ++ } from_parse; ++ } extract; ++ ++ uint8_t num_of_byte_masks; ++ struct dpkg_mask masks[DPKG_NUM_OF_MASKS]; ++}; ++ ++/** ++ * struct dpkg_profile_cfg - A structure for defining a full Key Generation ++ * profile (rule) ++ * @num_extracts: Defines the number of valid entries in the array below ++ * @extracts: Array of required extractions ++ */ ++struct dpkg_profile_cfg { ++ uint8_t num_extracts; ++ struct dpkg_extract extracts[DPKG_MAX_NUM_OF_EXTRACTS]; ++}; ++ ++#endif /* __FSL_DPKG_H_ */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpmac.h b/drivers/net/dpaa2/mc/fsl_dpmac.h +new file mode 100644 +index 0000000..ad27772 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpmac.h +@@ -0,0 +1,593 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPMAC_H ++#define __FSL_DPMAC_H ++ ++/* Data Path MAC API ++ * Contains initialization APIs and runtime control APIs for DPMAC ++ */ ++ ++struct fsl_mc_io; ++ ++/** ++ * dpmac_open() - Open a control session for the specified object. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @dpmac_id: DPMAC unique ID ++ * @token: Returned token; use in subsequent API calls ++ * ++ * This function can be used to open a control session for an ++ * already created object; an object may have been declared in ++ * the DPL or by calling the dpmac_create function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent commands for ++ * this specific object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmac_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpmac_id, ++ uint16_t *token); ++ ++/** ++ * dpmac_close() - Close the control session of the object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMAC object ++ * ++ * After this function is called, no further operations are ++ * allowed on the object without opening a new control session. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmac_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * enum dpmac_link_type - DPMAC link type ++ * @DPMAC_LINK_TYPE_NONE: No link ++ * @DPMAC_LINK_TYPE_FIXED: Link is fixed type ++ * @DPMAC_LINK_TYPE_PHY: Link by PHY ID ++ * @DPMAC_LINK_TYPE_BACKPLANE: Backplane link type ++ */ ++enum dpmac_link_type { ++ DPMAC_LINK_TYPE_NONE, ++ DPMAC_LINK_TYPE_FIXED, ++ DPMAC_LINK_TYPE_PHY, ++ DPMAC_LINK_TYPE_BACKPLANE ++}; ++ ++/** ++ * enum dpmac_eth_if - DPMAC Ethrnet interface ++ * @DPMAC_ETH_IF_MII: MII interface ++ * @DPMAC_ETH_IF_RMII: RMII interface ++ * @DPMAC_ETH_IF_SMII: SMII interface ++ * @DPMAC_ETH_IF_GMII: GMII interface ++ * @DPMAC_ETH_IF_RGMII: RGMII interface ++ * @DPMAC_ETH_IF_SGMII: SGMII interface ++ * @DPMAC_ETH_IF_QSGMII: QSGMII interface ++ * @DPMAC_ETH_IF_XAUI: XAUI interface ++ * @DPMAC_ETH_IF_XFI: XFI interface ++ */ ++enum dpmac_eth_if { ++ DPMAC_ETH_IF_MII, ++ DPMAC_ETH_IF_RMII, ++ DPMAC_ETH_IF_SMII, ++ DPMAC_ETH_IF_GMII, ++ DPMAC_ETH_IF_RGMII, ++ DPMAC_ETH_IF_SGMII, ++ DPMAC_ETH_IF_QSGMII, ++ DPMAC_ETH_IF_XAUI, ++ DPMAC_ETH_IF_XFI ++}; ++ ++/** ++ * struct dpmac_cfg - Structure representing DPMAC configuration ++ * @mac_id: Represents the Hardware MAC ID; in case of multiple WRIOP, ++ * the MAC IDs are continuous. ++ * For example: 2 WRIOPs, 16 MACs in each: ++ * MAC IDs for the 1st WRIOP: 1-16, ++ * MAC IDs for the 2nd WRIOP: 17-32. ++ */ ++struct dpmac_cfg { ++ int mac_id; ++}; ++ ++/** ++ * dpmac_create() - Create the DPMAC object. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @cfg: Configuration structure ++ * @token: Returned token; use in subsequent API calls ++ * ++ * Create the DPMAC object, allocate required resources and ++ * perform required initialization. ++ * ++ * The object can be created either by declaring it in the ++ * DPL file, or by calling this function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent calls to ++ * this specific object. For objects that are created using the ++ * DPL file, call dpmac_open function to get an authentication ++ * token first. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmac_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpmac_cfg *cfg, ++ uint16_t *token); ++ ++/** ++ * dpmac_destroy() - Destroy the DPMAC object and release all its resources. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMAC object ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpmac_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * DPMAC IRQ Index and Events ++ */ ++ ++/** ++ * IRQ index ++ */ ++#define DPMAC_IRQ_INDEX 0 ++/** ++ * IRQ event - indicates a change in link state ++ */ ++#define DPMAC_IRQ_EVENT_LINK_CFG_REQ 0x00000001 ++/** ++ * IRQ event - Indicates that the link state changed ++ */ ++#define DPMAC_IRQ_EVENT_LINK_CHANGED 0x00000002 ++ ++/** ++ * struct dpmac_irq_cfg - IRQ configuration ++ * @addr: Address that must be written to signal a message-based interrupt ++ * @val: Value to write into irq_addr address ++ * @irq_num: A user defined number associated with this IRQ ++ */ ++struct dpmac_irq_cfg { ++ uint64_t addr; ++ uint32_t val; ++ int irq_num; ++}; ++ ++/** ++ * dpmac_set_irq() - Set IRQ information for the DPMAC to trigger an interrupt. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMAC object ++ * @irq_index: Identifies the interrupt index to configure ++ * @irq_cfg: IRQ configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmac_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpmac_irq_cfg *irq_cfg); ++ ++/** ++ * dpmac_get_irq() - Get IRQ information from the DPMAC. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMAC object ++ * @irq_index: The interrupt index to configure ++ * @type: Interrupt type: 0 represents message interrupt ++ * type (both irq_addr and irq_val are valid) ++ * @irq_cfg: IRQ attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmac_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpmac_irq_cfg *irq_cfg); ++ ++/** ++ * dpmac_set_irq_enable() - Set overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMAC object ++ * @irq_index: The interrupt index to configure ++ * @en: Interrupt state - enable = 1, disable = 0 ++ * ++ * Allows GPP software to control when interrupts are generated. ++ * Each interrupt can have up to 32 causes. The enable/disable control's the ++ * overall interrupt state. if the interrupt is disabled no causes will cause ++ * an interrupt. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmac_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en); ++ ++/** ++ * dpmac_get_irq_enable() - Get overall interrupt state ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMAC object ++ * @irq_index: The interrupt index to configure ++ * @en: Returned interrupt state - enable = 1, disable = 0 ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmac_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en); ++ ++/** ++ * dpmac_set_irq_mask() - Set interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMAC object ++ * @irq_index: The interrupt index to configure ++ * @mask: Event mask to trigger interrupt; ++ * each bit: ++ * 0 = ignore event ++ * 1 = consider event for asserting IRQ ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmac_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask); ++ ++/** ++ * dpmac_get_irq_mask() - Get interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMAC object ++ * @irq_index: The interrupt index to configure ++ * @mask: Returned event mask to trigger interrupt ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmac_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask); ++ ++/** ++ * dpmac_get_irq_status() - Get the current status of any pending interrupts. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMAC object ++ * @irq_index: The interrupt index to configure ++ * @status: Returned interrupts status - one bit per cause: ++ * 0 = no interrupt pending ++ * 1 = interrupt pending ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmac_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status); ++ ++/** ++ * dpmac_clear_irq_status() - Clear a pending interrupt's status ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMAC object ++ * @irq_index: The interrupt index to configure ++ * @status: Bits to clear (W1C) - one bit per cause: ++ * 0 = don't change ++ * 1 = clear status bit ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmac_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status); ++ ++/** ++ * struct dpmac_attr - Structure representing DPMAC attributes ++ * @id: DPMAC object ID ++ * @phy_id: PHY ID ++ * @link_type: link type ++ * @eth_if: Ethernet interface ++ * @max_rate: Maximum supported rate - in Mbps ++ * @version: DPMAC version ++ */ ++struct dpmac_attr { ++ int id; ++ int phy_id; ++ enum dpmac_link_type link_type; ++ enum dpmac_eth_if eth_if; ++ uint32_t max_rate; ++ /** ++ * struct version - Structure representing DPMAC version ++ * @major: DPMAC major version ++ * @minor: DPMAC minor version ++ */ ++ struct { ++ uint16_t major; ++ uint16_t minor; ++ } version; ++}; ++ ++/** ++ * dpmac_get_attributes - Retrieve DPMAC attributes. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMAC object ++ * @attr: Returned object's attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmac_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpmac_attr *attr); ++ ++/** ++ * struct dpmac_mdio_cfg - DPMAC MDIO read/write parameters ++ * @phy_addr: MDIO device address ++ * @reg: Address of the register within the Clause 45 PHY device from which data ++ * is to be read ++ * @data: Data read/write from/to MDIO ++ */ ++struct dpmac_mdio_cfg { ++ uint8_t phy_addr; ++ uint8_t reg; ++ uint16_t data; ++}; ++ ++/** ++ * dpmac_mdio_read() - Perform MDIO read transaction ++ * @mc_io: Pointer to opaque I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMAC object ++ * @cfg: Structure with MDIO transaction parameters ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmac_mdio_read(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpmac_mdio_cfg *cfg); ++ ++/** ++ * dpmac_mdio_write() - Perform MDIO write transaction ++ * @mc_io: Pointer to opaque I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMAC object ++ * @cfg: Structure with MDIO transaction parameters ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmac_mdio_write(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpmac_mdio_cfg *cfg); ++ ++/** ++ * DPMAC link configuration/state options ++ */ ++ ++/** ++ * Enable auto-negotiation ++ */ ++#define DPMAC_LINK_OPT_AUTONEG 0x0000000000000001ULL ++/** ++ * Enable half-duplex mode ++ */ ++#define DPMAC_LINK_OPT_HALF_DUPLEX 0x0000000000000002ULL ++/** ++ * Enable pause frames ++ */ ++#define DPMAC_LINK_OPT_PAUSE 0x0000000000000004ULL ++/** ++ * Enable a-symmetric pause frames ++ */ ++#define DPMAC_LINK_OPT_ASYM_PAUSE 0x0000000000000008ULL ++ ++/** ++ * struct dpmac_link_cfg - Structure representing DPMAC link configuration ++ * @rate: Link's rate - in Mbps ++ * @options: Enable/Disable DPMAC link cfg features (bitmap) ++ */ ++struct dpmac_link_cfg { ++ uint32_t rate; ++ uint64_t options; ++}; ++ ++/** ++ * dpmac_get_link_cfg() - Get Ethernet link configuration ++ * @mc_io: Pointer to opaque I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMAC object ++ * @cfg: Returned structure with the link configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmac_get_link_cfg(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpmac_link_cfg *cfg); ++ ++/** ++ * struct dpmac_link_state - DPMAC link configuration request ++ * @rate: Rate in Mbps ++ * @options: Enable/Disable DPMAC link cfg features (bitmap) ++ * @up: Link state ++ */ ++struct dpmac_link_state { ++ uint32_t rate; ++ uint64_t options; ++ int up; ++}; ++ ++/** ++ * dpmac_set_link_state() - Set the Ethernet link status ++ * @mc_io: Pointer to opaque I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMAC object ++ * @link_state: Link state configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmac_set_link_state(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpmac_link_state *link_state); ++ ++/** ++ * enum dpmac_counter - DPMAC counter types ++ * @DPMAC_CNT_ING_FRAME_64: counts 64-bytes frames, good or bad. ++ * @DPMAC_CNT_ING_FRAME_127: counts 65- to 127-bytes frames, good or bad. ++ * @DPMAC_CNT_ING_FRAME_255: counts 128- to 255-bytes frames, good or bad. ++ * @DPMAC_CNT_ING_FRAME_511: counts 256- to 511-bytes frames, good or bad. ++ * @DPMAC_CNT_ING_FRAME_1023: counts 512- to 1023-bytes frames, good or bad. ++ * @DPMAC_CNT_ING_FRAME_1518: counts 1024- to 1518-bytes frames, good or bad. ++ * @DPMAC_CNT_ING_FRAME_1519_MAX: counts 1519-bytes frames and larger ++ * (up to max frame length specified), ++ * good or bad. ++ * @DPMAC_CNT_ING_FRAG: counts frames which are shorter than 64 bytes received ++ * with a wrong CRC ++ * @DPMAC_CNT_ING_JABBER: counts frames longer than the maximum frame length ++ * specified, with a bad frame check sequence. ++ * @DPMAC_CNT_ING_FRAME_DISCARD: counts dropped frames due to internal errors. ++ * Occurs when a receive FIFO overflows. ++ * Includes also frames truncated as a result of ++ * the receive FIFO overflow. ++ * @DPMAC_CNT_ING_ALIGN_ERR: counts frames with an alignment error ++ * (optional used for wrong SFD). ++ * @DPMAC_CNT_EGR_UNDERSIZED: counts frames transmitted that was less than 64 ++ * bytes long with a good CRC. ++ * @DPMAC_CNT_ING_OVERSIZED: counts frames longer than the maximum frame length ++ * specified, with a good frame check sequence. ++ * @DPMAC_CNT_ING_VALID_PAUSE_FRAME: counts valid pause frames (regular and PFC) ++ * @DPMAC_CNT_EGR_VALID_PAUSE_FRAME: counts valid pause frames transmitted ++ * (regular and PFC). ++ * @DPMAC_CNT_ING_BYTE: counts bytes received except preamble for all valid ++ * frames and valid pause frames. ++ * @DPMAC_CNT_ING_MCAST_FRAME: counts received multicast frames. ++ * @DPMAC_CNT_ING_BCAST_FRAME: counts received broadcast frames. ++ * @DPMAC_CNT_ING_ALL_FRAME: counts each good or bad frames received. ++ * @DPMAC_CNT_ING_UCAST_FRAME: counts received unicast frames. ++ * @DPMAC_CNT_ING_ERR_FRAME: counts frames received with an error ++ * (except for undersized/fragment frame). ++ * @DPMAC_CNT_EGR_BYTE: counts bytes transmitted except preamble for all valid ++ * frames and valid pause frames transmitted. ++ * @DPMAC_CNT_EGR_MCAST_FRAME: counts transmitted multicast frames. ++ * @DPMAC_CNT_EGR_BCAST_FRAME: counts transmitted broadcast frames. ++ * @DPMAC_CNT_EGR_UCAST_FRAME: counts transmitted unicast frames. ++ * @DPMAC_CNT_EGR_ERR_FRAME: counts frames transmitted with an error. ++ * @DPMAC_CNT_ING_GOOD_FRAME: counts frames received without error, including ++ * pause frames. ++ * @DPMAC_CNT_ENG_GOOD_FRAME: counts frames transmitted without error, including ++ * pause frames. ++ */ ++enum dpmac_counter { ++ DPMAC_CNT_ING_FRAME_64, ++ DPMAC_CNT_ING_FRAME_127, ++ DPMAC_CNT_ING_FRAME_255, ++ DPMAC_CNT_ING_FRAME_511, ++ DPMAC_CNT_ING_FRAME_1023, ++ DPMAC_CNT_ING_FRAME_1518, ++ DPMAC_CNT_ING_FRAME_1519_MAX, ++ DPMAC_CNT_ING_FRAG, ++ DPMAC_CNT_ING_JABBER, ++ DPMAC_CNT_ING_FRAME_DISCARD, ++ DPMAC_CNT_ING_ALIGN_ERR, ++ DPMAC_CNT_EGR_UNDERSIZED, ++ DPMAC_CNT_ING_OVERSIZED, ++ DPMAC_CNT_ING_VALID_PAUSE_FRAME, ++ DPMAC_CNT_EGR_VALID_PAUSE_FRAME, ++ DPMAC_CNT_ING_BYTE, ++ DPMAC_CNT_ING_MCAST_FRAME, ++ DPMAC_CNT_ING_BCAST_FRAME, ++ DPMAC_CNT_ING_ALL_FRAME, ++ DPMAC_CNT_ING_UCAST_FRAME, ++ DPMAC_CNT_ING_ERR_FRAME, ++ DPMAC_CNT_EGR_BYTE, ++ DPMAC_CNT_EGR_MCAST_FRAME, ++ DPMAC_CNT_EGR_BCAST_FRAME, ++ DPMAC_CNT_EGR_UCAST_FRAME, ++ DPMAC_CNT_EGR_ERR_FRAME, ++ DPMAC_CNT_ING_GOOD_FRAME, ++ DPMAC_CNT_ENG_GOOD_FRAME ++}; ++ ++/** ++ * dpmac_get_counter() - Read a specific DPMAC counter ++ * @mc_io: Pointer to opaque I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMAC object ++ * @type: The requested counter ++ * @counter: Returned counter value ++ * ++ * Return: The requested counter; '0' otherwise. ++ */ ++int dpmac_get_counter(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ enum dpmac_counter type, ++ uint64_t *counter); ++ ++#endif /* __FSL_DPMAC_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpmac_cmd.h b/drivers/net/dpaa2/mc/fsl_dpmac_cmd.h +new file mode 100644 +index 0000000..dc00590 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpmac_cmd.h +@@ -0,0 +1,195 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_DPMAC_CMD_H ++#define _FSL_DPMAC_CMD_H ++ ++/* DPMAC Version */ ++#define DPMAC_VER_MAJOR 3 ++#define DPMAC_VER_MINOR 2 ++ ++/* Command IDs */ ++#define DPMAC_CMDID_CLOSE 0x800 ++#define DPMAC_CMDID_OPEN 0x80c ++#define DPMAC_CMDID_CREATE 0x90c ++#define DPMAC_CMDID_DESTROY 0x900 ++ ++#define DPMAC_CMDID_GET_ATTR 0x004 ++#define DPMAC_CMDID_RESET 0x005 ++ ++#define DPMAC_CMDID_SET_IRQ 0x010 ++#define DPMAC_CMDID_GET_IRQ 0x011 ++#define DPMAC_CMDID_SET_IRQ_ENABLE 0x012 ++#define DPMAC_CMDID_GET_IRQ_ENABLE 0x013 ++#define DPMAC_CMDID_SET_IRQ_MASK 0x014 ++#define DPMAC_CMDID_GET_IRQ_MASK 0x015 ++#define DPMAC_CMDID_GET_IRQ_STATUS 0x016 ++#define DPMAC_CMDID_CLEAR_IRQ_STATUS 0x017 ++ ++#define DPMAC_CMDID_MDIO_READ 0x0c0 ++#define DPMAC_CMDID_MDIO_WRITE 0x0c1 ++#define DPMAC_CMDID_GET_LINK_CFG 0x0c2 ++#define DPMAC_CMDID_SET_LINK_STATE 0x0c3 ++#define DPMAC_CMDID_GET_COUNTER 0x0c4 ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_CMD_CREATE(cmd, cfg) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, cfg->mac_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_CMD_OPEN(cmd, dpmac_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpmac_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, irq_index);\ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, irq_cfg->val);\ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr); \ ++ MC_CMD_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_CMD_GET_IRQ(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_RSP_GET_IRQ(cmd, type, irq_cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr); \ ++ MC_RSP_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, type); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_CMD_SET_IRQ_ENABLE(cmd, irq_index, en) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, en); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_CMD_GET_IRQ_ENABLE(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_RSP_GET_IRQ_ENABLE(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 8, uint8_t, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, mask);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_CMD_GET_IRQ_MASK(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_RSP_GET_IRQ_MASK(cmd, mask) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mask) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_RSP_GET_IRQ_STATUS(cmd, status) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, status) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_RSP_GET_ATTRIBUTES(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, attr->phy_id);\ ++ MC_RSP_OP(cmd, 0, 32, 32, int, attr->id);\ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->version.major);\ ++ MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->version.minor);\ ++ MC_RSP_OP(cmd, 1, 32, 8, enum dpmac_link_type, attr->link_type);\ ++ MC_RSP_OP(cmd, 1, 40, 8, enum dpmac_eth_if, attr->eth_if);\ ++ MC_RSP_OP(cmd, 2, 0, 32, uint32_t, attr->max_rate);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_CMD_MDIO_READ(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, cfg->phy_addr); \ ++ MC_CMD_OP(cmd, 0, 8, 8, uint8_t, cfg->reg); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_RSP_MDIO_READ(cmd, data) \ ++ MC_RSP_OP(cmd, 0, 16, 16, uint16_t, data) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_CMD_MDIO_WRITE(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, cfg->phy_addr); \ ++ MC_CMD_OP(cmd, 0, 8, 8, uint8_t, cfg->reg); \ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->data); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_RSP_GET_LINK_CFG(cmd, cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 64, uint64_t, cfg->options); \ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, cfg->rate); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_CMD_SET_LINK_STATE(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 64, uint64_t, cfg->options); \ ++ MC_CMD_OP(cmd, 1, 0, 32, uint32_t, cfg->rate); \ ++ MC_CMD_OP(cmd, 2, 0, 1, int, cfg->up); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_CMD_GET_COUNTER(cmd, type) \ ++ MC_CMD_OP(cmd, 0, 0, 8, enum dpmac_counter, type) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_RSP_GET_COUNTER(cmd, counter) \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, counter) ++ ++#endif /* _FSL_DPMAC_CMD_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpmcp.h b/drivers/net/dpaa2/mc/fsl_dpmcp.h +new file mode 100644 +index 0000000..80f238e +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpmcp.h +@@ -0,0 +1,332 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPMCP_H ++#define __FSL_DPMCP_H ++ ++/* Data Path Management Command Portal API ++ * Contains initialization APIs and runtime control APIs for DPMCP ++ */ ++ ++struct fsl_mc_io; ++ ++/** ++ * dpmcp_open() - Open a control session for the specified object. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @dpmcp_id: DPMCP unique ID ++ * @token: Returned token; use in subsequent API calls ++ * ++ * This function can be used to open a control session for an ++ * already created object; an object may have been declared in ++ * the DPL or by calling the dpmcp_create function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent commands for ++ * this specific object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmcp_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpmcp_id, ++ uint16_t *token); ++ ++/** ++ * Get portal ID from pool ++ */ ++#define DPMCP_GET_PORTAL_ID_FROM_POOL (-1) ++ ++/** ++ * dpmcp_close() - Close the control session of the object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMCP object ++ * ++ * After this function is called, no further operations are ++ * allowed on the object without opening a new control session. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmcp_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * struct dpmcp_cfg - Structure representing DPMCP configuration ++ * @portal_id: Portal ID; 'DPMCP_GET_PORTAL_ID_FROM_POOL' to get the portal ID ++ * from pool ++ */ ++struct dpmcp_cfg { ++ int portal_id; ++}; ++ ++/** ++ * dpmcp_create() - Create the DPMCP object. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @cfg: Configuration structure ++ * @token: Returned token; use in subsequent API calls ++ * ++ * Create the DPMCP object, allocate required resources and ++ * perform required initialization. ++ * ++ * The object can be created either by declaring it in the ++ * DPL file, or by calling this function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent calls to ++ * this specific object. For objects that are created using the ++ * DPL file, call dpmcp_open function to get an authentication ++ * token first. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmcp_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpmcp_cfg *cfg, ++ uint16_t *token); ++ ++/** ++ * dpmcp_destroy() - Destroy the DPMCP object and release all its resources. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMCP object ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpmcp_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpmcp_reset() - Reset the DPMCP, returns the object to initial state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMCP object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmcp_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * IRQ ++ */ ++ ++/** ++ * IRQ Index ++ */ ++#define DPMCP_IRQ_INDEX 0 ++/** ++ * irq event - Indicates that the link state changed ++ */ ++#define DPMCP_IRQ_EVENT_CMD_DONE 0x00000001 ++ ++/** ++ * struct dpmcp_irq_cfg - IRQ configuration ++ * @addr: Address that must be written to signal a message-based interrupt ++ * @val: Value to write into irq_addr address ++ * @irq_num: A user defined number associated with this IRQ ++ */ ++struct dpmcp_irq_cfg { ++ uint64_t addr; ++ uint32_t val; ++ int irq_num; ++}; ++ ++/** ++ * dpmcp_set_irq() - Set IRQ information for the DPMCP to trigger an interrupt. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMCP object ++ * @irq_index: Identifies the interrupt index to configure ++ * @irq_cfg: IRQ configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmcp_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpmcp_irq_cfg *irq_cfg); ++ ++/** ++ * dpmcp_get_irq() - Get IRQ information from the DPMCP. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMCP object ++ * @irq_index: The interrupt index to configure ++ * @type: Interrupt type: 0 represents message interrupt ++ * type (both irq_addr and irq_val are valid) ++ * @irq_cfg: IRQ attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmcp_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpmcp_irq_cfg *irq_cfg); ++ ++/** ++ * dpmcp_set_irq_enable() - Set overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMCP object ++ * @irq_index: The interrupt index to configure ++ * @en: Interrupt state - enable = 1, disable = 0 ++ * ++ * Allows GPP software to control when interrupts are generated. ++ * Each interrupt can have up to 32 causes. The enable/disable control's the ++ * overall interrupt state. if the interrupt is disabled no causes will cause ++ * an interrupt. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmcp_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en); ++ ++/** ++ * dpmcp_get_irq_enable() - Get overall interrupt state ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMCP object ++ * @irq_index: The interrupt index to configure ++ * @en: Returned interrupt state - enable = 1, disable = 0 ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmcp_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en); ++ ++/** ++ * dpmcp_set_irq_mask() - Set interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMCP object ++ * @irq_index: The interrupt index to configure ++ * @mask: Event mask to trigger interrupt; ++ * each bit: ++ * 0 = ignore event ++ * 1 = consider event for asserting IRQ ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmcp_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask); ++ ++/** ++ * dpmcp_get_irq_mask() - Get interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMCP object ++ * @irq_index: The interrupt index to configure ++ * @mask: Returned event mask to trigger interrupt ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmcp_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask); ++ ++/** ++ * dpmcp_get_irq_status() - Get the current status of any pending interrupts. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMCP object ++ * @irq_index: The interrupt index to configure ++ * @status: Returned interrupts status - one bit per cause: ++ * 0 = no interrupt pending ++ * 1 = interrupt pending ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmcp_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status); ++ ++/** ++ * struct dpmcp_attr - Structure representing DPMCP attributes ++ * @id: DPMCP object ID ++ * @version: DPMCP version ++ */ ++struct dpmcp_attr { ++ int id; ++ /** ++ * struct version - Structure representing DPMCP version ++ * @major: DPMCP major version ++ * @minor: DPMCP minor version ++ */ ++ struct { ++ uint16_t major; ++ uint16_t minor; ++ } version; ++}; ++ ++/** ++ * dpmcp_get_attributes - Retrieve DPMCP attributes. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMCP object ++ * @attr: Returned object's attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmcp_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpmcp_attr *attr); ++ ++#endif /* __FSL_DPMCP_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpmcp_cmd.h b/drivers/net/dpaa2/mc/fsl_dpmcp_cmd.h +new file mode 100644 +index 0000000..8f710bd +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpmcp_cmd.h +@@ -0,0 +1,135 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_DPMCP_CMD_H ++#define _FSL_DPMCP_CMD_H ++ ++/* DPMCP Version */ ++#define DPMCP_VER_MAJOR 3 ++#define DPMCP_VER_MINOR 0 ++ ++/* Command IDs */ ++#define DPMCP_CMDID_CLOSE 0x800 ++#define DPMCP_CMDID_OPEN 0x80b ++#define DPMCP_CMDID_CREATE 0x90b ++#define DPMCP_CMDID_DESTROY 0x900 ++ ++#define DPMCP_CMDID_GET_ATTR 0x004 ++#define DPMCP_CMDID_RESET 0x005 ++ ++#define DPMCP_CMDID_SET_IRQ 0x010 ++#define DPMCP_CMDID_GET_IRQ 0x011 ++#define DPMCP_CMDID_SET_IRQ_ENABLE 0x012 ++#define DPMCP_CMDID_GET_IRQ_ENABLE 0x013 ++#define DPMCP_CMDID_SET_IRQ_MASK 0x014 ++#define DPMCP_CMDID_GET_IRQ_MASK 0x015 ++#define DPMCP_CMDID_GET_IRQ_STATUS 0x016 ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMCP_CMD_OPEN(cmd, dpmcp_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpmcp_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMCP_CMD_CREATE(cmd, cfg) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, cfg->portal_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMCP_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, irq_index);\ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, irq_cfg->val);\ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr); \ ++ MC_CMD_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMCP_CMD_GET_IRQ(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMCP_RSP_GET_IRQ(cmd, type, irq_cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr); \ ++ MC_RSP_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, type); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMCP_CMD_SET_IRQ_ENABLE(cmd, irq_index, en) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, en); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMCP_CMD_GET_IRQ_ENABLE(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMCP_RSP_GET_IRQ_ENABLE(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 8, uint8_t, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMCP_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, mask);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMCP_CMD_GET_IRQ_MASK(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMCP_RSP_GET_IRQ_MASK(cmd, mask) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mask) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMCP_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMCP_RSP_GET_IRQ_STATUS(cmd, status) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, status) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMCP_RSP_GET_ATTRIBUTES(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 32, 32, int, attr->id);\ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->version.major);\ ++ MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->version.minor);\ ++} while (0) ++ ++#endif /* _FSL_DPMCP_CMD_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpmng.h b/drivers/net/dpaa2/mc/fsl_dpmng.h +new file mode 100644 +index 0000000..4468dea +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpmng.h +@@ -0,0 +1,74 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPMNG_H ++#define __FSL_DPMNG_H ++ ++/* Management Complex General API ++ * Contains general API for the Management Complex firmware ++ */ ++ ++struct fsl_mc_io; ++ ++/** ++ * Management Complex firmware version information ++ */ ++#define MC_VER_MAJOR 9 ++#define MC_VER_MINOR 0 ++ ++/** ++ * struct mc_versoin ++ * @major: Major version number: incremented on API compatibility changes ++ * @minor: Minor version number: incremented on API additions (that are ++ * backward compatible); reset when major version is incremented ++ * @revision: Internal revision number: incremented on implementation changes ++ * and/or bug fixes that have no impact on API ++ */ ++struct mc_version { ++ uint32_t major; ++ uint32_t minor; ++ uint32_t revision; ++}; ++ ++/** ++ * mc_get_version() - Retrieves the Management Complex firmware ++ * version information ++ * @mc_io: Pointer to opaque I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @mc_ver_info: Returned version information structure ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int mc_get_version(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ struct mc_version *mc_ver_info); ++ ++#endif /* __FSL_DPMNG_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpmng_cmd.h b/drivers/net/dpaa2/mc/fsl_dpmng_cmd.h +new file mode 100644 +index 0000000..c34ca3a +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpmng_cmd.h +@@ -0,0 +1,46 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPMNG_CMD_H ++#define __FSL_DPMNG_CMD_H ++ ++/* Command IDs */ ++#define DPMNG_CMDID_GET_VERSION 0x831 ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMNG_RSP_GET_VERSION(cmd, mc_ver_info) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mc_ver_info->revision); \ ++ MC_RSP_OP(cmd, 0, 32, 32, uint32_t, mc_ver_info->major); \ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, mc_ver_info->minor); \ ++} while (0) ++ ++#endif /* __FSL_DPMNG_CMD_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpni.h b/drivers/net/dpaa2/mc/fsl_dpni.h +new file mode 100644 +index 0000000..c820086 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpni.h +@@ -0,0 +1,2581 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPNI_H ++#define __FSL_DPNI_H ++ ++#include ++ ++struct fsl_mc_io; ++ ++/** ++ * Data Path Network Interface API ++ * Contains initialization APIs and runtime control APIs for DPNI ++ */ ++ ++/** General DPNI macros */ ++ ++/** ++ * Maximum number of traffic classes ++ */ ++#define DPNI_MAX_TC 8 ++/** ++ * Maximum number of buffer pools per DPNI ++ */ ++#define DPNI_MAX_DPBP 8 ++/** ++ * Maximum number of storage-profiles per DPNI ++ */ ++#define DPNI_MAX_SP 2 ++ ++/** ++ * All traffic classes considered; see dpni_set_rx_flow() ++ */ ++#define DPNI_ALL_TCS (uint8_t)(-1) ++/** ++ * All flows within traffic class considered; see dpni_set_rx_flow() ++ */ ++#define DPNI_ALL_TC_FLOWS (uint16_t)(-1) ++/** ++ * Generate new flow ID; see dpni_set_tx_flow() ++ */ ++#define DPNI_NEW_FLOW_ID (uint16_t)(-1) ++/* use for common tx-conf queue; see dpni_set_tx_conf_() */ ++#define DPNI_COMMON_TX_CONF (uint16_t)(-1) ++ ++/** ++ * dpni_open() - Open a control session for the specified object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @dpni_id: DPNI unique ID ++ * @token: Returned token; use in subsequent API calls ++ * ++ * This function can be used to open a control session for an ++ * already created object; an object may have been declared in ++ * the DPL or by calling the dpni_create() function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent commands for ++ * this specific object. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpni_id, ++ uint16_t *token); ++ ++/** ++ * dpni_close() - Close the control session of the object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * ++ * After this function is called, no further operations are ++ * allowed on the object without opening a new control session. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/* DPNI configuration options */ ++ ++/** ++ * Allow different distribution key profiles for different traffic classes; ++ * if not set, a single key profile is assumed ++ */ ++#define DPNI_OPT_ALLOW_DIST_KEY_PER_TC 0x00000001 ++ ++/** ++ * Disable all non-error transmit confirmation; error frames are reported ++ * back to a common Tx error queue ++ */ ++#define DPNI_OPT_TX_CONF_DISABLED 0x00000002 ++ ++/** ++ * Disable per-sender private Tx confirmation/error queue ++ */ ++#define DPNI_OPT_PRIVATE_TX_CONF_ERROR_DISABLED 0x00000004 ++ ++/** ++ * Support distribution based on hashed key; ++ * allows statistical distribution over receive queues in a traffic class ++ */ ++#define DPNI_OPT_DIST_HASH 0x00000010 ++ ++/** ++ * DEPRECATED - if this flag is selected and and all new 'max_fs_entries' are ++ * '0' then backward compatibility is preserved; ++ * Support distribution based on flow steering; ++ * allows explicit control of distribution over receive queues in a traffic ++ * class ++ */ ++#define DPNI_OPT_DIST_FS 0x00000020 ++ ++/** ++ * Unicast filtering support ++ */ ++#define DPNI_OPT_UNICAST_FILTER 0x00000080 ++/** ++ * Multicast filtering support ++ */ ++#define DPNI_OPT_MULTICAST_FILTER 0x00000100 ++/** ++ * VLAN filtering support ++ */ ++#define DPNI_OPT_VLAN_FILTER 0x00000200 ++/** ++ * Support IP reassembly on received packets ++ */ ++#define DPNI_OPT_IPR 0x00000800 ++/** ++ * Support IP fragmentation on transmitted packets ++ */ ++#define DPNI_OPT_IPF 0x00001000 ++/** ++ * VLAN manipulation support ++ */ ++#define DPNI_OPT_VLAN_MANIPULATION 0x00010000 ++/** ++ * Support masking of QoS lookup keys ++ */ ++#define DPNI_OPT_QOS_MASK_SUPPORT 0x00020000 ++/** ++ * Support masking of Flow Steering lookup keys ++ */ ++#define DPNI_OPT_FS_MASK_SUPPORT 0x00040000 ++ ++/** ++ * struct dpni_extended_cfg - Structure representing extended DPNI configuration ++ * @tc_cfg: TCs configuration ++ * @ipr_cfg: IP reassembly configuration ++ */ ++struct dpni_extended_cfg { ++ /** ++ * struct tc_cfg - TC configuration ++ * @max_dist: Maximum distribution size for Rx traffic class; ++ * supported values: 1,2,3,4,6,7,8,12,14,16,24,28,32,48,56,64,96, ++ * 112,128,192,224,256,384,448,512,768,896,1024; ++ * value '0' will be treated as '1'. ++ * other unsupported values will be round down to the nearest ++ * supported value. ++ * @max_fs_entries: Maximum FS entries for Rx traffic class; ++ * '0' means no support for this TC; ++ */ ++ struct { ++ uint16_t max_dist; ++ uint16_t max_fs_entries; ++ } tc_cfg[DPNI_MAX_TC]; ++ /** ++ * struct ipr_cfg - Structure representing IP reassembly configuration ++ * @max_reass_frm_size: Maximum size of the reassembled frame ++ * @min_frag_size_ipv4: Minimum fragment size of IPv4 fragments ++ * @min_frag_size_ipv6: Minimum fragment size of IPv6 fragments ++ * @max_open_frames_ipv4: Maximum concurrent IPv4 packets in reassembly ++ * process ++ * @max_open_frames_ipv6: Maximum concurrent IPv6 packets in reassembly ++ * process ++ */ ++ struct { ++ uint16_t max_reass_frm_size; ++ uint16_t min_frag_size_ipv4; ++ uint16_t min_frag_size_ipv6; ++ uint16_t max_open_frames_ipv4; ++ uint16_t max_open_frames_ipv6; ++ } ipr_cfg; ++}; ++ ++/** ++ * dpni_prepare_extended_cfg() - function prepare extended parameters ++ * @cfg: extended structure ++ * @ext_cfg_buf: Zeroed 256 bytes of memory before mapping it to DMA ++ * ++ * This function has to be called before dpni_create() ++ */ ++int dpni_prepare_extended_cfg(const struct dpni_extended_cfg *cfg, ++ uint8_t *ext_cfg_buf); ++ ++/** ++ * struct dpni_cfg - Structure representing DPNI configuration ++ * @mac_addr: Primary MAC address ++ * @adv: Advanced parameters; default is all zeros; ++ * use this structure to change default settings ++ */ ++struct dpni_cfg { ++ uint8_t mac_addr[6]; ++ /** ++ * struct adv - Advanced parameters ++ * @options: Mask of available options; use 'DPNI_OPT_' values ++ * @start_hdr: Selects the packet starting header for parsing; ++ * 'NET_PROT_NONE' is treated as default: 'NET_PROT_ETH' ++ * @max_senders: Maximum number of different senders; used as the number ++ * of dedicated Tx flows; Non-power-of-2 values are rounded ++ * up to the next power-of-2 value as hardware demands it; ++ * '0' will be treated as '1' ++ * @max_tcs: Maximum number of traffic classes (for both Tx and Rx); ++ * '0' will e treated as '1' ++ * @max_unicast_filters: Maximum number of unicast filters; ++ * '0' is treated as '16' ++ * @max_multicast_filters: Maximum number of multicast filters; ++ * '0' is treated as '64' ++ * @max_qos_entries: if 'max_tcs > 1', declares the maximum entries in ++ * the QoS table; '0' is treated as '64' ++ * @max_qos_key_size: Maximum key size for the QoS look-up; ++ * '0' is treated as '24' which is enough for IPv4 ++ * 5-tuple ++ * @max_dist_key_size: Maximum key size for the distribution; ++ * '0' is treated as '24' which is enough for IPv4 5-tuple ++ * @max_policers: Maximum number of policers; ++ * should be between '0' and max_tcs ++ * @max_congestion_ctrl: Maximum number of congestion control groups ++ * (CGs); covers early drop and congestion notification ++ * requirements; ++ * should be between '0' and ('max_tcs' + 'max_senders') ++ * @ext_cfg_iova: I/O virtual address of 256 bytes DMA-able memory ++ * filled with the extended configuration by calling ++ * dpni_prepare_extended_cfg() ++ */ ++ struct { ++ uint32_t options; ++ enum net_prot start_hdr; ++ uint8_t max_senders; ++ uint8_t max_tcs; ++ uint8_t max_unicast_filters; ++ uint8_t max_multicast_filters; ++ uint8_t max_vlan_filters; ++ uint8_t max_qos_entries; ++ uint8_t max_qos_key_size; ++ uint8_t max_dist_key_size; ++ uint8_t max_policers; ++ uint8_t max_congestion_ctrl; ++ uint64_t ext_cfg_iova; ++ } adv; ++}; ++ ++/** ++ * dpni_create() - Create the DPNI object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @cfg: Configuration structure ++ * @token: Returned token; use in subsequent API calls ++ * ++ * Create the DPNI object, allocate required resources and ++ * perform required initialization. ++ * ++ * The object can be created either by declaring it in the ++ * DPL file, or by calling this function. ++ * ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent calls to ++ * this specific object. For objects that are created using the ++ * DPL file, call dpni_open() function to get an authentication ++ * token first. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpni_cfg *cfg, ++ uint16_t *token); ++ ++/** ++ * dpni_destroy() - Destroy the DPNI object and release all its resources. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpni_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * struct dpni_pools_cfg - Structure representing buffer pools configuration ++ * @num_dpbp: Number of DPBPs ++ * @pools: Array of buffer pools parameters; The number of valid entries ++ * must match 'num_dpbp' value ++ */ ++struct dpni_pools_cfg { ++ uint8_t num_dpbp; ++ /** ++ * struct pools - Buffer pools parameters ++ * @dpbp_id: DPBP object ID ++ * @buffer_size: Buffer size ++ * @backup_pool: Backup pool ++ */ ++ struct { ++ int dpbp_id; ++ uint16_t buffer_size; ++ int backup_pool; ++ } pools[DPNI_MAX_DPBP]; ++}; ++ ++/** ++ * dpni_set_pools() - Set buffer pools configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @cfg: Buffer pools configuration ++ * ++ * mandatory for DPNI operation ++ * warning:Allowed only when DPNI is disabled ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_pools(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_pools_cfg *cfg); ++ ++/** ++ * dpni_enable() - Enable the DPNI, allow sending and receiving frames. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpni_disable() - Disable the DPNI, stop sending and receiving frames. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpni_is_enabled() - Check if the DPNI is enabled. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @en: Returns '1' if object is enabled; '0' otherwise ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en); ++ ++/** ++ * dpni_reset() - Reset the DPNI, returns the object to initial state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * DPNI IRQ Index and Events ++ */ ++ ++/** ++ * IRQ index ++ */ ++#define DPNI_IRQ_INDEX 0 ++/** ++ * IRQ event - indicates a change in link state ++ */ ++#define DPNI_IRQ_EVENT_LINK_CHANGED 0x00000001 ++ ++/** ++ * struct dpni_irq_cfg - IRQ configuration ++ * @addr: Address that must be written to signal a message-based interrupt ++ * @val: Value to write into irq_addr address ++ * @irq_num: A user defined number associated with this IRQ ++ */ ++struct dpni_irq_cfg { ++ uint64_t addr; ++ uint32_t val; ++ int irq_num; ++}; ++ ++/** ++ * dpni_set_irq() - Set IRQ information for the DPNI to trigger an interrupt. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @irq_index: Identifies the interrupt index to configure ++ * @irq_cfg: IRQ configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpni_irq_cfg *irq_cfg); ++ ++/** ++ * dpni_get_irq() - Get IRQ information from the DPNI. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @irq_index: The interrupt index to configure ++ * @type: Interrupt type: 0 represents message interrupt ++ * type (both irq_addr and irq_val are valid) ++ * @irq_cfg: IRQ attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpni_irq_cfg *irq_cfg); ++ ++/** ++ * dpni_set_irq_enable() - Set overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @irq_index: The interrupt index to configure ++ * @en: Interrupt state: - enable = 1, disable = 0 ++ * ++ * Allows GPP software to control when interrupts are generated. ++ * Each interrupt can have up to 32 causes. The enable/disable control's the ++ * overall interrupt state. if the interrupt is disabled no causes will cause ++ * an interrupt. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en); ++ ++/** ++ * dpni_get_irq_enable() - Get overall interrupt state ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @irq_index: The interrupt index to configure ++ * @en: Returned interrupt state - enable = 1, disable = 0 ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en); ++ ++/** ++ * dpni_set_irq_mask() - Set interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @irq_index: The interrupt index to configure ++ * @mask: event mask to trigger interrupt; ++ * each bit: ++ * 0 = ignore event ++ * 1 = consider event for asserting IRQ ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask); ++ ++/** ++ * dpni_get_irq_mask() - Get interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @irq_index: The interrupt index to configure ++ * @mask: Returned event mask to trigger interrupt ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask); ++ ++/** ++ * dpni_get_irq_status() - Get the current status of any pending interrupts. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @irq_index: The interrupt index to configure ++ * @status: Returned interrupts status - one bit per cause: ++ * 0 = no interrupt pending ++ * 1 = interrupt pending ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status); ++ ++/** ++ * dpni_clear_irq_status() - Clear a pending interrupt's status ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @irq_index: The interrupt index to configure ++ * @status: bits to clear (W1C) - one bit per cause: ++ * 0 = don't change ++ * 1 = clear status bit ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status); ++ ++/** ++ * struct dpni_attr - Structure representing DPNI attributes ++ * @id: DPNI object ID ++ * @version: DPNI version ++ * @start_hdr: Indicates the packet starting header for parsing ++ * @options: Mask of available options; reflects the value as was given in ++ * object's creation ++ * @max_senders: Maximum number of different senders; used as the number ++ * of dedicated Tx flows; ++ * @max_tcs: Maximum number of traffic classes (for both Tx and Rx) ++ * @max_unicast_filters: Maximum number of unicast filters ++ * @max_multicast_filters: Maximum number of multicast filters ++ * @max_vlan_filters: Maximum number of VLAN filters ++ * @max_qos_entries: if 'max_tcs > 1', declares the maximum entries in QoS table ++ * @max_qos_key_size: Maximum key size for the QoS look-up ++ * @max_dist_key_size: Maximum key size for the distribution look-up ++ * @max_policers: Maximum number of policers; ++ * @max_congestion_ctrl: Maximum number of congestion control groups (CGs); ++ * @ext_cfg_iova: I/O virtual address of 256 bytes DMA-able memory; ++ * call dpni_extract_extended_cfg() to extract the extended configuration ++ */ ++struct dpni_attr { ++ int id; ++ /** ++ * struct version - DPNI version ++ * @major: DPNI major version ++ * @minor: DPNI minor version ++ */ ++ struct { ++ uint16_t major; ++ uint16_t minor; ++ } version; ++ enum net_prot start_hdr; ++ uint32_t options; ++ uint8_t max_senders; ++ uint8_t max_tcs; ++ uint8_t max_unicast_filters; ++ uint8_t max_multicast_filters; ++ uint8_t max_vlan_filters; ++ uint8_t max_qos_entries; ++ uint8_t max_qos_key_size; ++ uint8_t max_dist_key_size; ++ uint8_t max_policers; ++ uint8_t max_congestion_ctrl; ++ uint64_t ext_cfg_iova; ++}; ++ ++/** ++ * dpni_get_attributes() - Retrieve DPNI attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @attr: Object's attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpni_attr *attr); ++ ++/** ++ * dpni_extract_extended_cfg() - extract the extended parameters ++ * @cfg: extended structure ++ * @ext_cfg_buf: 256 bytes of DMA-able memory ++ * ++ * This function has to be called after dpni_get_attributes() ++ */ ++int dpni_extract_extended_cfg(struct dpni_extended_cfg *cfg, ++ const uint8_t *ext_cfg_buf); ++ ++/** ++ * DPNI errors ++ */ ++ ++/** ++ * Extract out of frame header error ++ */ ++#define DPNI_ERROR_EOFHE 0x00020000 ++/** ++ * Frame length error ++ */ ++#define DPNI_ERROR_FLE 0x00002000 ++/** ++ * Frame physical error ++ */ ++#define DPNI_ERROR_FPE 0x00001000 ++/** ++ * Parsing header error ++ */ ++#define DPNI_ERROR_PHE 0x00000020 ++/** ++ * Parser L3 checksum error ++ */ ++#define DPNI_ERROR_L3CE 0x00000004 ++/** ++ * Parser L3 checksum error ++ */ ++#define DPNI_ERROR_L4CE 0x00000001 ++ ++/** ++ * enum dpni_error_action - Defines DPNI behavior for errors ++ * @DPNI_ERROR_ACTION_DISCARD: Discard the frame ++ * @DPNI_ERROR_ACTION_CONTINUE: Continue with the normal flow ++ * @DPNI_ERROR_ACTION_SEND_TO_ERROR_QUEUE: Send the frame to the error queue ++ */ ++enum dpni_error_action { ++ DPNI_ERROR_ACTION_DISCARD = 0, ++ DPNI_ERROR_ACTION_CONTINUE = 1, ++ DPNI_ERROR_ACTION_SEND_TO_ERROR_QUEUE = 2 ++}; ++ ++/** ++ * struct dpni_error_cfg - Structure representing DPNI errors treatment ++ * @errors: Errors mask; use 'DPNI_ERROR__ ++ * @error_action: The desired action for the errors mask ++ * @set_frame_annotation: Set to '1' to mark the errors in frame annotation ++ * status (FAS); relevant only for the non-discard action ++ */ ++struct dpni_error_cfg { ++ uint32_t errors; ++ enum dpni_error_action error_action; ++ int set_frame_annotation; ++}; ++ ++/** ++ * dpni_set_errors_behavior() - Set errors behavior ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @cfg: Errors configuration ++ * ++ * this function may be called numerous times with different ++ * error masks ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_errors_behavior(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpni_error_cfg *cfg); ++ ++/** ++ * DPNI buffer layout modification options ++ */ ++ ++/** ++ * Select to modify the time-stamp setting ++ */ ++#define DPNI_BUF_LAYOUT_OPT_TIMESTAMP 0x00000001 ++/** ++ * Select to modify the parser-result setting; not applicable for Tx ++ */ ++#define DPNI_BUF_LAYOUT_OPT_PARSER_RESULT 0x00000002 ++/** ++ * Select to modify the frame-status setting ++ */ ++#define DPNI_BUF_LAYOUT_OPT_FRAME_STATUS 0x00000004 ++/** ++ * Select to modify the private-data-size setting ++ */ ++#define DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE 0x00000008 ++/** ++ * Select to modify the data-alignment setting ++ */ ++#define DPNI_BUF_LAYOUT_OPT_DATA_ALIGN 0x00000010 ++/** ++ * Select to modify the data-head-room setting ++ */ ++#define DPNI_BUF_LAYOUT_OPT_DATA_HEAD_ROOM 0x00000020 ++/** ++ * Select to modify the data-tail-room setting ++ */ ++#define DPNI_BUF_LAYOUT_OPT_DATA_TAIL_ROOM 0x00000040 ++ ++/** ++ * struct dpni_buffer_layout - Structure representing DPNI buffer layout ++ * @options: Flags representing the suggested modifications to the buffer ++ * layout; Use any combination of 'DPNI_BUF_LAYOUT_OPT_' flags ++ * @pass_timestamp: Pass timestamp value ++ * @pass_parser_result: Pass parser results ++ * @pass_frame_status: Pass frame status ++ * @private_data_size: Size kept for private data (in bytes) ++ * @data_align: Data alignment ++ * @data_head_room: Data head room ++ * @data_tail_room: Data tail room ++ */ ++struct dpni_buffer_layout { ++ uint32_t options; ++ int pass_timestamp; ++ int pass_parser_result; ++ int pass_frame_status; ++ uint16_t private_data_size; ++ uint16_t data_align; ++ uint16_t data_head_room; ++ uint16_t data_tail_room; ++}; ++ ++/** ++ * dpni_get_rx_buffer_layout() - Retrieve Rx buffer layout attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @layout: Returns buffer layout attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_rx_buffer_layout(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpni_buffer_layout *layout); ++ ++/** ++ * dpni_set_rx_buffer_layout() - Set Rx buffer layout configuration. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @layout: Buffer layout configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ * ++ * @warning Allowed only when DPNI is disabled ++ */ ++int dpni_set_rx_buffer_layout(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_buffer_layout *layout); ++ ++/** ++ * dpni_get_tx_buffer_layout() - Retrieve Tx buffer layout attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @layout: Returns buffer layout attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_tx_buffer_layout(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpni_buffer_layout *layout); ++ ++/** ++ * dpni_set_tx_buffer_layout() - Set Tx buffer layout configuration. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @layout: Buffer layout configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ * ++ * @warning Allowed only when DPNI is disabled ++ */ ++int dpni_set_tx_buffer_layout(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_buffer_layout *layout); ++ ++/** ++ * dpni_get_tx_conf_buffer_layout() - Retrieve Tx confirmation buffer layout ++ * attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @layout: Returns buffer layout attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_tx_conf_buffer_layout(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpni_buffer_layout *layout); ++ ++/** ++ * dpni_set_tx_conf_buffer_layout() - Set Tx confirmation buffer layout ++ * configuration. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @layout: Buffer layout configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ * ++ * @warning Allowed only when DPNI is disabled ++ */ ++int dpni_set_tx_conf_buffer_layout(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_buffer_layout *layout); ++ ++/** ++ * dpni_set_l3_chksum_validation() - Enable/disable L3 checksum validation ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @en: Set to '1' to enable; '0' to disable ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_l3_chksum_validation(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en); ++ ++/** ++ * dpni_get_l3_chksum_validation() - Get L3 checksum validation mode ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @en: Returns '1' if enabled; '0' otherwise ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_l3_chksum_validation(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en); ++ ++/** ++ * dpni_set_l4_chksum_validation() - Enable/disable L4 checksum validation ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @en: Set to '1' to enable; '0' to disable ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_l4_chksum_validation(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en); ++ ++/** ++ * dpni_get_l4_chksum_validation() - Get L4 checksum validation mode ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @en: Returns '1' if enabled; '0' otherwise ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_l4_chksum_validation(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en); ++ ++/** ++ * dpni_get_qdid() - Get the Queuing Destination ID (QDID) that should be used ++ * for enqueue operations ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @qdid: Returned virtual QDID value that should be used as an argument ++ * in all enqueue operations ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_qdid(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t *qdid); ++ ++/** ++ * struct dpni_sp_info - Structure representing DPNI storage-profile information ++ * (relevant only for DPNI owned by AIOP) ++ * @spids: array of storage-profiles ++ */ ++struct dpni_sp_info { ++ uint16_t spids[DPNI_MAX_SP]; ++}; ++ ++/** ++ * dpni_get_spids() - Get the AIOP storage profile IDs associated with the DPNI ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @sp_info: Returned AIOP storage-profile information ++ * ++ * Return: '0' on Success; Error code otherwise. ++ * ++ * @warning Only relevant for DPNI that belongs to AIOP container. ++ */ ++int dpni_get_sp_info(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpni_sp_info *sp_info); ++ ++/** ++ * dpni_get_tx_data_offset() - Get the Tx data offset (from start of buffer) ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @data_offset: Tx data offset (from start of buffer) ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_tx_data_offset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t *data_offset); ++ ++/** ++ * enum dpni_counter - DPNI counter types ++ * @DPNI_CNT_ING_FRAME: Counts ingress frames ++ * @DPNI_CNT_ING_BYTE: Counts ingress bytes ++ * @DPNI_CNT_ING_FRAME_DROP: Counts ingress frames dropped due to explicit ++ * 'drop' setting ++ * @DPNI_CNT_ING_FRAME_DISCARD: Counts ingress frames discarded due to errors ++ * @DPNI_CNT_ING_MCAST_FRAME: Counts ingress multicast frames ++ * @DPNI_CNT_ING_MCAST_BYTE: Counts ingress multicast bytes ++ * @DPNI_CNT_ING_BCAST_FRAME: Counts ingress broadcast frames ++ * @DPNI_CNT_ING_BCAST_BYTES: Counts ingress broadcast bytes ++ * @DPNI_CNT_EGR_FRAME: Counts egress frames ++ * @DPNI_CNT_EGR_BYTE: Counts egress bytes ++ * @DPNI_CNT_EGR_FRAME_DISCARD: Counts egress frames discarded due to errors ++ */ ++enum dpni_counter { ++ DPNI_CNT_ING_FRAME = 0x0, ++ DPNI_CNT_ING_BYTE = 0x1, ++ DPNI_CNT_ING_FRAME_DROP = 0x2, ++ DPNI_CNT_ING_FRAME_DISCARD = 0x3, ++ DPNI_CNT_ING_MCAST_FRAME = 0x4, ++ DPNI_CNT_ING_MCAST_BYTE = 0x5, ++ DPNI_CNT_ING_BCAST_FRAME = 0x6, ++ DPNI_CNT_ING_BCAST_BYTES = 0x7, ++ DPNI_CNT_EGR_FRAME = 0x8, ++ DPNI_CNT_EGR_BYTE = 0x9, ++ DPNI_CNT_EGR_FRAME_DISCARD = 0xa ++}; ++ ++/** ++ * dpni_get_counter() - Read a specific DPNI counter ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @counter: The requested counter ++ * @value: Returned counter's current value ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_counter(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ enum dpni_counter counter, ++ uint64_t *value); ++ ++/** ++ * dpni_set_counter() - Set (or clear) a specific DPNI counter ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @counter: The requested counter ++ * @value: New counter value; typically pass '0' for resetting ++ * the counter. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_counter(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ enum dpni_counter counter, ++ uint64_t value); ++ ++/** ++ * Enable auto-negotiation ++ */ ++#define DPNI_LINK_OPT_AUTONEG 0x0000000000000001ULL ++/** ++ * Enable half-duplex mode ++ */ ++#define DPNI_LINK_OPT_HALF_DUPLEX 0x0000000000000002ULL ++/** ++ * Enable pause frames ++ */ ++#define DPNI_LINK_OPT_PAUSE 0x0000000000000004ULL ++/** ++ * Enable a-symmetric pause frames ++ */ ++#define DPNI_LINK_OPT_ASYM_PAUSE 0x0000000000000008ULL ++ ++/** ++ * struct - Structure representing DPNI link configuration ++ * @rate: Rate ++ * @options: Mask of available options; use 'DPNI_LINK_OPT_' values ++ */ ++struct dpni_link_cfg { ++ uint32_t rate; ++ uint64_t options; ++}; ++ ++/** ++ * dpni_set_link_cfg() - set the link configuration. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @cfg: Link configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_link_cfg(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_link_cfg *cfg); ++ ++/** ++ * struct dpni_link_state - Structure representing DPNI link state ++ * @rate: Rate ++ * @options: Mask of available options; use 'DPNI_LINK_OPT_' values ++ * @up: Link state; '0' for down, '1' for up ++ */ ++struct dpni_link_state { ++ uint32_t rate; ++ uint64_t options; ++ int up; ++}; ++ ++/** ++ * dpni_get_link_state() - Return the link state (either up or down) ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @state: Returned link state; ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_link_state(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpni_link_state *state); ++ ++/** ++ * struct dpni_tx_shaping - Structure representing DPNI tx shaping configuration ++ * @rate_limit: rate in Mbps ++ * @max_burst_size: burst size in bytes (up to 64KB) ++ */ ++struct dpni_tx_shaping_cfg { ++ uint32_t rate_limit; ++ uint16_t max_burst_size; ++}; ++ ++/** ++ * dpni_set_tx_shaping() - Set the transmit shaping ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @tx_shaper: tx shaping configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_tx_shaping(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_tx_shaping_cfg *tx_shaper); ++ ++/** ++ * dpni_set_max_frame_length() - Set the maximum received frame length. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @max_frame_length: Maximum received frame length (in ++ * bytes); frame is discarded if its ++ * length exceeds this value ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_max_frame_length(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t max_frame_length); ++ ++/** ++ * dpni_get_max_frame_length() - Get the maximum received frame length. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @max_frame_length: Maximum received frame length (in ++ * bytes); frame is discarded if its ++ * length exceeds this value ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_max_frame_length(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t *max_frame_length); ++ ++/** ++ * dpni_set_mtu() - Set the MTU for the interface. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @mtu: MTU length (in bytes) ++ * ++ * MTU determines the maximum fragment size for performing IP ++ * fragmentation on egress packets. ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_mtu(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t mtu); ++ ++/** ++ * dpni_get_mtu() - Get the MTU. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @mtu: Returned MTU length (in bytes) ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_mtu(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t *mtu); ++ ++/** ++ * dpni_set_multicast_promisc() - Enable/disable multicast promiscuous mode ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @en: Set to '1' to enable; '0' to disable ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_multicast_promisc(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en); ++ ++/** ++ * dpni_get_multicast_promisc() - Get multicast promiscuous mode ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @en: Returns '1' if enabled; '0' otherwise ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_multicast_promisc(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en); ++ ++/** ++ * dpni_set_unicast_promisc() - Enable/disable unicast promiscuous mode ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @en: Set to '1' to enable; '0' to disable ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_unicast_promisc(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en); ++ ++/** ++ * dpni_get_unicast_promisc() - Get unicast promiscuous mode ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @en: Returns '1' if enabled; '0' otherwise ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_unicast_promisc(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en); ++ ++/** ++ * dpni_set_primary_mac_addr() - Set the primary MAC address ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @mac_addr: MAC address to set as primary address ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_primary_mac_addr(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const uint8_t mac_addr[6]); ++ ++/** ++ * dpni_get_primary_mac_addr() - Get the primary MAC address ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @mac_addr: Returned MAC address ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_primary_mac_addr(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t mac_addr[6]); ++ ++/** ++ * dpni_add_mac_addr() - Add MAC address filter ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @mac_addr: MAC address to add ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_add_mac_addr(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const uint8_t mac_addr[6]); ++ ++/** ++ * dpni_remove_mac_addr() - Remove MAC address filter ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @mac_addr: MAC address to remove ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_remove_mac_addr(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const uint8_t mac_addr[6]); ++ ++/** ++ * dpni_clear_mac_filters() - Clear all unicast and/or multicast MAC filters ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @unicast: Set to '1' to clear unicast addresses ++ * @multicast: Set to '1' to clear multicast addresses ++ * ++ * The primary MAC address is not cleared by this operation. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_clear_mac_filters(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int unicast, ++ int multicast); ++ ++/** ++ * dpni_set_vlan_filters() - Enable/disable VLAN filtering mode ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @en: Set to '1' to enable; '0' to disable ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_vlan_filters(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en); ++ ++/** ++ * dpni_add_vlan_id() - Add VLAN ID filter ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @vlan_id: VLAN ID to add ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_add_vlan_id(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id); ++ ++/** ++ * dpni_remove_vlan_id() - Remove VLAN ID filter ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @vlan_id: VLAN ID to remove ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_remove_vlan_id(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id); ++ ++/** ++ * dpni_clear_vlan_filters() - Clear all VLAN filters ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_clear_vlan_filters(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * enum dpni_tx_schedule_mode - DPNI Tx scheduling mode ++ * @DPNI_TX_SCHED_STRICT_PRIORITY: strict priority ++ * @DPNI_TX_SCHED_WEIGHTED: weighted based scheduling ++ */ ++enum dpni_tx_schedule_mode { ++ DPNI_TX_SCHED_STRICT_PRIORITY, ++ DPNI_TX_SCHED_WEIGHTED, ++}; ++ ++/** ++ * struct dpni_tx_schedule_cfg - Structure representing Tx ++ * scheduling configuration ++ * @mode: scheduling mode ++ * @delta_bandwidth: Bandwidth represented in weights from 100 to 10000; ++ * not applicable for 'strict-priority' mode; ++ */ ++struct dpni_tx_schedule_cfg { ++ enum dpni_tx_schedule_mode mode; ++ uint16_t delta_bandwidth; ++}; ++ ++/** ++ * struct dpni_tx_selection_cfg - Structure representing transmission ++ * selection configuration ++ * @tc_sched: an array of traffic-classes ++ */ ++struct dpni_tx_selection_cfg { ++ struct dpni_tx_schedule_cfg tc_sched[DPNI_MAX_TC]; ++}; ++ ++/** ++ * dpni_set_tx_selection() - Set transmission selection configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @cfg: transmission selection configuration ++ * ++ * warning: Allowed only when DPNI is disabled ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_tx_selection(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_tx_selection_cfg *cfg); ++ ++/** ++ * enum dpni_dist_mode - DPNI distribution mode ++ * @DPNI_DIST_MODE_NONE: No distribution ++ * @DPNI_DIST_MODE_HASH: Use hash distribution; only relevant if ++ * the 'DPNI_OPT_DIST_HASH' option was set at DPNI creation ++ * @DPNI_DIST_MODE_FS: Use explicit flow steering; only relevant if ++ * the 'DPNI_OPT_DIST_FS' option was set at DPNI creation ++ */ ++enum dpni_dist_mode { ++ DPNI_DIST_MODE_NONE = 0, ++ DPNI_DIST_MODE_HASH = 1, ++ DPNI_DIST_MODE_FS = 2 ++}; ++ ++/** ++ * enum dpni_fs_miss_action - DPNI Flow Steering miss action ++ * @DPNI_FS_MISS_DROP: In case of no-match, drop the frame ++ * @DPNI_FS_MISS_EXPLICIT_FLOWID: In case of no-match, use explicit flow-id ++ * @DPNI_FS_MISS_HASH: In case of no-match, distribute using hash ++ */ ++enum dpni_fs_miss_action { ++ DPNI_FS_MISS_DROP = 0, ++ DPNI_FS_MISS_EXPLICIT_FLOWID = 1, ++ DPNI_FS_MISS_HASH = 2 ++}; ++ ++/** ++ * struct dpni_fs_tbl_cfg - Flow Steering table configuration ++ * @miss_action: Miss action selection ++ * @default_flow_id: Used when 'miss_action = DPNI_FS_MISS_EXPLICIT_FLOWID' ++ */ ++struct dpni_fs_tbl_cfg { ++ enum dpni_fs_miss_action miss_action; ++ uint16_t default_flow_id; ++}; ++ ++/** ++ * dpni_prepare_key_cfg() - function prepare extract parameters ++ * @cfg: defining a full Key Generation profile (rule) ++ * @key_cfg_buf: Zeroed 256 bytes of memory before mapping it to DMA ++ * ++ * This function has to be called before the following functions: ++ * - dpni_set_rx_tc_dist() ++ * - dpni_set_qos_table() ++ */ ++int dpni_prepare_key_cfg(const struct dpkg_profile_cfg *cfg, ++ uint8_t *key_cfg_buf); ++ ++/** ++ * struct dpni_rx_tc_dist_cfg - Rx traffic class distribution configuration ++ * @dist_size: Set the distribution size; ++ * supported values: 1,2,3,4,6,7,8,12,14,16,24,28,32,48,56,64,96, ++ * 112,128,192,224,256,384,448,512,768,896,1024 ++ * @dist_mode: Distribution mode ++ * @key_cfg_iova: I/O virtual address of 256 bytes DMA-able memory filled with ++ * the extractions to be used for the distribution key by calling ++ * dpni_prepare_key_cfg() relevant only when ++ * 'dist_mode != DPNI_DIST_MODE_NONE', otherwise it can be '0' ++ * @fs_cfg: Flow Steering table configuration; only relevant if ++ * 'dist_mode = DPNI_DIST_MODE_FS' ++ */ ++struct dpni_rx_tc_dist_cfg { ++ uint16_t dist_size; ++ enum dpni_dist_mode dist_mode; ++ uint64_t key_cfg_iova; ++ struct dpni_fs_tbl_cfg fs_cfg; ++}; ++ ++/** ++ * dpni_set_rx_tc_dist() - Set Rx traffic class distribution configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @tc_id: Traffic class selection (0-7) ++ * @cfg: Traffic class distribution configuration ++ * ++ * warning: if 'dist_mode != DPNI_DIST_MODE_NONE', call dpni_prepare_key_cfg() ++ * first to prepare the key_cfg_iova parameter ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpni_set_rx_tc_dist(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ const struct dpni_rx_tc_dist_cfg *cfg); ++ ++/** ++ * Set to select color aware mode (otherwise - color blind) ++ */ ++#define DPNI_POLICER_OPT_COLOR_AWARE 0x00000001 ++/** ++ * Set to discard frame with RED color ++ */ ++#define DPNI_POLICER_OPT_DISCARD_RED 0x00000002 ++ ++/** ++ * enum dpni_policer_mode - selecting the policer mode ++ * @DPNI_POLICER_MODE_NONE: Policer is disabled ++ * @DPNI_POLICER_MODE_PASS_THROUGH: Policer pass through ++ * @DPNI_POLICER_MODE_RFC_2698: Policer algorithm RFC 2698 ++ * @DPNI_POLICER_MODE_RFC_4115: Policer algorithm RFC 4115 ++ */ ++enum dpni_policer_mode { ++ DPNI_POLICER_MODE_NONE = 0, ++ DPNI_POLICER_MODE_PASS_THROUGH, ++ DPNI_POLICER_MODE_RFC_2698, ++ DPNI_POLICER_MODE_RFC_4115 ++}; ++ ++/** ++ * enum dpni_policer_unit - DPNI policer units ++ * @DPNI_POLICER_UNIT_BYTES: bytes units ++ * @DPNI_POLICER_UNIT_FRAMES: frames units ++ */ ++enum dpni_policer_unit { ++ DPNI_POLICER_UNIT_BYTES = 0, ++ DPNI_POLICER_UNIT_FRAMES ++}; ++ ++/** ++ * enum dpni_policer_color - selecting the policer color ++ * @DPNI_POLICER_COLOR_GREEN: Green color ++ * @DPNI_POLICER_COLOR_YELLOW: Yellow color ++ * @DPNI_POLICER_COLOR_RED: Red color ++ */ ++enum dpni_policer_color { ++ DPNI_POLICER_COLOR_GREEN = 0, ++ DPNI_POLICER_COLOR_YELLOW, ++ DPNI_POLICER_COLOR_RED ++}; ++ ++/** ++ * struct dpni_rx_tc_policing_cfg - Policer configuration ++ * @options: Mask of available options; use 'DPNI_POLICER_OPT_' values ++ * @mode: policer mode ++ * @default_color: For pass-through mode the policer re-colors with this ++ * color any incoming packets. For Color aware non-pass-through mode: ++ * policer re-colors with this color all packets with FD[DROPP]>2. ++ * @units: Bytes or Packets ++ * @cir: Committed information rate (CIR) in Kbps or packets/second ++ * @cbs: Committed burst size (CBS) in bytes or packets ++ * @eir: Peak information rate (PIR, rfc2698) in Kbps or packets/second ++ * Excess information rate (EIR, rfc4115) in Kbps or packets/second ++ * @ebs: Peak burst size (PBS, rfc2698) in bytes or packets ++ * Excess burst size (EBS, rfc4115) in bytes or packets ++ */ ++struct dpni_rx_tc_policing_cfg { ++ uint32_t options; ++ enum dpni_policer_mode mode; ++ enum dpni_policer_unit units; ++ enum dpni_policer_color default_color; ++ uint32_t cir; ++ uint32_t cbs; ++ uint32_t eir; ++ uint32_t ebs; ++}; ++ ++/** ++ * dpni_set_rx_tc_policing() - Set Rx traffic class policing configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @tc_id: Traffic class selection (0-7) ++ * @cfg: Traffic class policing configuration ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpni_set_rx_tc_policing(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ const struct dpni_rx_tc_policing_cfg *cfg); ++ ++/** ++ * dpni_get_rx_tc_policing() - Get Rx traffic class policing configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @tc_id: Traffic class selection (0-7) ++ * @cfg: Traffic class policing configuration ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpni_get_rx_tc_policing(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ struct dpni_rx_tc_policing_cfg *cfg); ++ ++/** ++ * enum dpni_congestion_unit - DPNI congestion units ++ * @DPNI_CONGESTION_UNIT_BYTES: bytes units ++ * @DPNI_CONGESTION_UNIT_FRAMES: frames units ++ */ ++enum dpni_congestion_unit { ++ DPNI_CONGESTION_UNIT_BYTES = 0, ++ DPNI_CONGESTION_UNIT_FRAMES ++}; ++ ++/** ++ * enum dpni_early_drop_mode - DPNI early drop mode ++ * @DPNI_EARLY_DROP_MODE_NONE: early drop is disabled ++ * @DPNI_EARLY_DROP_MODE_TAIL: early drop in taildrop mode ++ * @DPNI_EARLY_DROP_MODE_WRED: early drop in WRED mode ++ */ ++enum dpni_early_drop_mode { ++ DPNI_EARLY_DROP_MODE_NONE = 0, ++ DPNI_EARLY_DROP_MODE_TAIL, ++ DPNI_EARLY_DROP_MODE_WRED ++}; ++ ++/** ++ * struct dpni_wred_cfg - WRED configuration ++ * @max_threshold: maximum threshold that packets may be discarded. Above this ++ * threshold all packets are discarded; must be less than 2^39; ++ * approximated to be expressed as (x+256)*2^(y-1) due to HW ++ * implementation. ++ * @min_threshold: minimum threshold that packets may be discarded at ++ * @drop_probability: probability that a packet will be discarded (1-100, ++ * associated with the max_threshold). ++ */ ++struct dpni_wred_cfg { ++ uint64_t max_threshold; ++ uint64_t min_threshold; ++ uint8_t drop_probability; ++}; ++ ++/** ++ * struct dpni_early_drop_cfg - early-drop configuration ++ * @mode: drop mode ++ * @units: units type ++ * @green: WRED - 'green' configuration ++ * @yellow: WRED - 'yellow' configuration ++ * @red: WRED - 'red' configuration ++ * @tail_drop_threshold: tail drop threshold ++ */ ++struct dpni_early_drop_cfg { ++ enum dpni_early_drop_mode mode; ++ enum dpni_congestion_unit units; ++ ++ struct dpni_wred_cfg green; ++ struct dpni_wred_cfg yellow; ++ struct dpni_wred_cfg red; ++ ++ uint32_t tail_drop_threshold; ++}; ++ ++/** ++ * dpni_prepare_early_drop() - prepare an early drop. ++ * @cfg: Early-drop configuration ++ * @early_drop_buf: Zeroed 256 bytes of memory before mapping it to DMA ++ * ++ * This function has to be called before dpni_set_rx_tc_early_drop or ++ * dpni_set_tx_tc_early_drop ++ * ++ */ ++void dpni_prepare_early_drop(const struct dpni_early_drop_cfg *cfg, ++ uint8_t *early_drop_buf); ++ ++/** ++ * dpni_extract_early_drop() - extract the early drop configuration. ++ * @cfg: Early-drop configuration ++ * @early_drop_buf: Zeroed 256 bytes of memory before mapping it to DMA ++ * ++ * This function has to be called after dpni_get_rx_tc_early_drop or ++ * dpni_get_tx_tc_early_drop ++ * ++ */ ++void dpni_extract_early_drop(struct dpni_early_drop_cfg *cfg, ++ const uint8_t *early_drop_buf); ++ ++/** ++ * dpni_set_rx_tc_early_drop() - Set Rx traffic class early-drop configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @tc_id: Traffic class selection (0-7) ++ * @early_drop_iova: I/O virtual address of 256 bytes DMA-able memory filled ++ * with the early-drop configuration by calling dpni_prepare_early_drop() ++ * ++ * warning: Before calling this function, call dpni_prepare_early_drop() to ++ * prepare the early_drop_iova parameter ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpni_set_rx_tc_early_drop(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ uint64_t early_drop_iova); ++ ++/** ++ * dpni_get_rx_tc_early_drop() - Get Rx traffic class early-drop configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @tc_id: Traffic class selection (0-7) ++ * @early_drop_iova: I/O virtual address of 256 bytes DMA-able memory ++ * ++ * warning: After calling this function, call dpni_extract_early_drop() to ++ * get the early drop configuration ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpni_get_rx_tc_early_drop(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ uint64_t early_drop_iova); ++ ++/** ++ * dpni_set_tx_tc_early_drop() - Set Tx traffic class early-drop configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @tc_id: Traffic class selection (0-7) ++ * @early_drop_iova: I/O virtual address of 256 bytes DMA-able memory filled ++ * with the early-drop configuration by calling dpni_prepare_early_drop() ++ * ++ * warning: Before calling this function, call dpni_prepare_early_drop() to ++ * prepare the early_drop_iova parameter ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpni_set_tx_tc_early_drop(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ uint64_t early_drop_iova); ++ ++/** ++ * dpni_get_tx_tc_early_drop() - Get Tx traffic class early-drop configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @tc_id: Traffic class selection (0-7) ++ * @early_drop_iova: I/O virtual address of 256 bytes DMA-able memory ++ * ++ * warning: After calling this function, call dpni_extract_early_drop() to ++ * get the early drop configuration ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpni_get_tx_tc_early_drop(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ uint64_t early_drop_iova); ++ ++/** ++ * enum dpni_dest - DPNI destination types ++ * @DPNI_DEST_NONE: Unassigned destination; The queue is set in parked mode and ++ * does not generate FQDAN notifications; user is expected to ++ * dequeue from the queue based on polling or other user-defined ++ * method ++ * @DPNI_DEST_DPIO: The queue is set in schedule mode and generates FQDAN ++ * notifications to the specified DPIO; user is expected to dequeue ++ * from the queue only after notification is received ++ * @DPNI_DEST_DPCON: The queue is set in schedule mode and does not generate ++ * FQDAN notifications, but is connected to the specified DPCON ++ * object; user is expected to dequeue from the DPCON channel ++ */ ++enum dpni_dest { ++ DPNI_DEST_NONE = 0, ++ DPNI_DEST_DPIO = 1, ++ DPNI_DEST_DPCON = 2 ++}; ++ ++/** ++ * struct dpni_dest_cfg - Structure representing DPNI destination parameters ++ * @dest_type: Destination type ++ * @dest_id: Either DPIO ID or DPCON ID, depending on the destination type ++ * @priority: Priority selection within the DPIO or DPCON channel; valid values ++ * are 0-1 or 0-7, depending on the number of priorities in that ++ * channel; not relevant for 'DPNI_DEST_NONE' option ++ */ ++struct dpni_dest_cfg { ++ enum dpni_dest dest_type; ++ int dest_id; ++ uint8_t priority; ++}; ++ ++/* DPNI congestion options */ ++ ++/** ++ * CSCN message is written to message_iova once entering a ++ * congestion state (see 'threshold_entry') ++ */ ++#define DPNI_CONG_OPT_WRITE_MEM_ON_ENTER 0x00000001 ++/** ++ * CSCN message is written to message_iova once exiting a ++ * congestion state (see 'threshold_exit') ++ */ ++#define DPNI_CONG_OPT_WRITE_MEM_ON_EXIT 0x00000002 ++/** ++ * CSCN write will attempt to allocate into a cache (coherent write); ++ * valid only if 'DPNI_CONG_OPT_WRITE_MEM_' is selected ++ */ ++#define DPNI_CONG_OPT_COHERENT_WRITE 0x00000004 ++/** ++ * if 'dest_cfg.dest_type != DPNI_DEST_NONE' CSCN message is sent to ++ * DPIO/DPCON's WQ channel once entering a congestion state ++ * (see 'threshold_entry') ++ */ ++#define DPNI_CONG_OPT_NOTIFY_DEST_ON_ENTER 0x00000008 ++/** ++ * if 'dest_cfg.dest_type != DPNI_DEST_NONE' CSCN message is sent to ++ * DPIO/DPCON's WQ channel once exiting a congestion state ++ * (see 'threshold_exit') ++ */ ++#define DPNI_CONG_OPT_NOTIFY_DEST_ON_EXIT 0x00000010 ++/** ++ * if 'dest_cfg.dest_type != DPNI_DEST_NONE' when the CSCN is written to the ++ * sw-portal's DQRR, the DQRI interrupt is asserted immediately (if enabled) ++ */ ++#define DPNI_CONG_OPT_INTR_COALESCING_DISABLED 0x00000020 ++ ++/** ++ * struct dpni_congestion_notification_cfg - congestion notification ++ * configuration ++ * @units: units type ++ * @threshold_entry: above this threshold we enter a congestion state. ++ * set it to '0' to disable it ++ * @threshold_exit: below this threshold we exit the congestion state. ++ * @message_ctx: The context that will be part of the CSCN message ++ * @message_iova: I/O virtual address (must be in DMA-able memory), ++ * must be 16B aligned; valid only if 'DPNI_CONG_OPT_WRITE_MEM_' is ++ * contained in 'options' ++ * @dest_cfg: CSCN can be send to either DPIO or DPCON WQ channel ++ * @options: Mask of available options; use 'DPNI_CONG_OPT_' values ++ */ ++ ++struct dpni_congestion_notification_cfg { ++ enum dpni_congestion_unit units; ++ uint32_t threshold_entry; ++ uint32_t threshold_exit; ++ uint64_t message_ctx; ++ uint64_t message_iova; ++ struct dpni_dest_cfg dest_cfg; ++ uint16_t options; ++}; ++ ++/** ++ * dpni_set_rx_tc_congestion_notification() - Set Rx traffic class congestion ++ * notification configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @tc_id: Traffic class selection (0-7) ++ * @cfg: congestion notification configuration ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpni_set_rx_tc_congestion_notification(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ const struct dpni_congestion_notification_cfg *cfg); ++ ++/** ++ * dpni_get_rx_tc_congestion_notification() - Get Rx traffic class congestion ++ * notification configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @tc_id: Traffic class selection (0-7) ++ * @cfg: congestion notification configuration ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpni_get_rx_tc_congestion_notification(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ struct dpni_congestion_notification_cfg *cfg); ++ ++/** ++ * dpni_set_tx_tc_congestion_notification() - Set Tx traffic class congestion ++ * notification configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @tc_id: Traffic class selection (0-7) ++ * @cfg: congestion notification configuration ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpni_set_tx_tc_congestion_notification(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ const struct dpni_congestion_notification_cfg *cfg); ++ ++/** ++ * dpni_get_tx_tc_congestion_notification() - Get Tx traffic class congestion ++ * notification configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @tc_id: Traffic class selection (0-7) ++ * @cfg: congestion notification configuration ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpni_get_tx_tc_congestion_notification(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ struct dpni_congestion_notification_cfg *cfg); ++ ++/** ++ * enum dpni_flc_type - DPNI FLC types ++ * @DPNI_FLC_USER_DEFINED: select the FLC to be used for user defined value ++ * @DPNI_FLC_STASH: select the FLC to be used for stash control ++ */ ++enum dpni_flc_type { ++ DPNI_FLC_USER_DEFINED = 0, ++ DPNI_FLC_STASH = 1, ++}; ++ ++/** ++ * enum dpni_stash_size - DPNI FLC stashing size ++ * @DPNI_STASH_SIZE_0B: no stash ++ * @DPNI_STASH_SIZE_64B: stashes 64 bytes ++ * @DPNI_STASH_SIZE_128B: stashes 128 bytes ++ * @DPNI_STASH_SIZE_192B: stashes 192 bytes ++ */ ++enum dpni_stash_size { ++ DPNI_STASH_SIZE_0B = 0, ++ DPNI_STASH_SIZE_64B = 1, ++ DPNI_STASH_SIZE_128B = 2, ++ DPNI_STASH_SIZE_192B = 3, ++}; ++ ++/* DPNI FLC stash options */ ++ ++/** ++ * stashes the whole annotation area (up to 192 bytes) ++ */ ++#define DPNI_FLC_STASH_FRAME_ANNOTATION 0x00000001 ++ ++/** ++ * struct dpni_flc_cfg - Structure representing DPNI FLC configuration ++ * @flc_type: FLC type ++ * @options: Mask of available options; ++ * use 'DPNI_FLC_STASH_' values ++ * @frame_data_size: Size of frame data to be stashed ++ * @flow_context_size: Size of flow context to be stashed ++ * @flow_context: 1. In case flc_type is 'DPNI_FLC_USER_DEFINED': ++ * this value will be provided in the frame descriptor ++ * (FD[FLC]) ++ * 2. In case flc_type is 'DPNI_FLC_STASH': ++ * this value will be I/O virtual address of the ++ * flow-context; ++ * Must be cacheline-aligned and DMA-able memory ++ */ ++struct dpni_flc_cfg { ++ enum dpni_flc_type flc_type; ++ uint32_t options; ++ enum dpni_stash_size frame_data_size; ++ enum dpni_stash_size flow_context_size; ++ uint64_t flow_context; ++}; ++ ++/** ++ * DPNI queue modification options ++ */ ++ ++/** ++ * Select to modify the user's context associated with the queue ++ */ ++#define DPNI_QUEUE_OPT_USER_CTX 0x00000001 ++/** ++ * Select to modify the queue's destination ++ */ ++#define DPNI_QUEUE_OPT_DEST 0x00000002 ++/** Select to modify the flow-context parameters; ++ * not applicable for Tx-conf/Err queues as the FD comes from the user ++ */ ++#define DPNI_QUEUE_OPT_FLC 0x00000004 ++/** ++ * Select to modify the queue's order preservation ++ */ ++#define DPNI_QUEUE_OPT_ORDER_PRESERVATION 0x00000008 ++/* Select to modify the queue's tail-drop threshold */ ++#define DPNI_QUEUE_OPT_TAILDROP_THRESHOLD 0x00000010 ++ ++/** ++ * struct dpni_queue_cfg - Structure representing queue configuration ++ * @options: Flags representing the suggested modifications to the queue; ++ * Use any combination of 'DPNI_QUEUE_OPT_' flags ++ * @user_ctx: User context value provided in the frame descriptor of each ++ * dequeued frame; valid only if 'DPNI_QUEUE_OPT_USER_CTX' ++ * is contained in 'options' ++ * @dest_cfg: Queue destination parameters; ++ * valid only if 'DPNI_QUEUE_OPT_DEST' is contained in 'options' ++ * @flc_cfg: Flow context configuration; in case the TC's distribution ++ * is either NONE or HASH the FLC's settings of flow#0 are used. ++ * in the case of FS (flow-steering) the flow's FLC settings ++ * are used. ++ * valid only if 'DPNI_QUEUE_OPT_FLC' is contained in 'options' ++ * @order_preservation_en: enable/disable order preservation; ++ * valid only if 'DPNI_QUEUE_OPT_ORDER_PRESERVATION' is contained ++ * in 'options' ++ * @tail_drop_threshold: set the queue's tail drop threshold in bytes; ++ * '0' value disable the threshold; maximum value is 0xE000000; ++ * valid only if 'DPNI_QUEUE_OPT_TAILDROP_THRESHOLD' is contained ++ * in 'options' ++ */ ++struct dpni_queue_cfg { ++ uint32_t options; ++ uint64_t user_ctx; ++ struct dpni_dest_cfg dest_cfg; ++ struct dpni_flc_cfg flc_cfg; ++ int order_preservation_en; ++ uint32_t tail_drop_threshold; ++}; ++ ++/** ++ * struct dpni_queue_attr - Structure representing queue attributes ++ * @user_ctx: User context value provided in the frame descriptor of each ++ * dequeued frame ++ * @dest_cfg: Queue destination configuration ++ * @flc_cfg: Flow context configuration ++ * @order_preservation_en: enable/disable order preservation ++ * @tail_drop_threshold: queue's tail drop threshold in bytes; ++ * @fqid: Virtual fqid value to be used for dequeue operations ++ */ ++struct dpni_queue_attr { ++ uint64_t user_ctx; ++ struct dpni_dest_cfg dest_cfg; ++ struct dpni_flc_cfg flc_cfg; ++ int order_preservation_en; ++ uint32_t tail_drop_threshold; ++ ++ uint32_t fqid; ++}; ++ ++/** ++ * DPNI Tx flow modification options ++ */ ++ ++/** ++ * Select to modify the settings for dedicate Tx confirmation/error ++ */ ++#define DPNI_TX_FLOW_OPT_TX_CONF_ERROR 0x00000001 ++/** ++ * Select to modify the L3 checksum generation setting ++ */ ++#define DPNI_TX_FLOW_OPT_L3_CHKSUM_GEN 0x00000010 ++/** ++ * Select to modify the L4 checksum generation setting ++ */ ++#define DPNI_TX_FLOW_OPT_L4_CHKSUM_GEN 0x00000020 ++ ++/** ++ * struct dpni_tx_flow_cfg - Structure representing Tx flow configuration ++ * @options: Flags representing the suggested modifications to the Tx flow; ++ * Use any combination 'DPNI_TX_FLOW_OPT_' flags ++ * @use_common_tx_conf_queue: Set to '1' to use the common (default) Tx ++ * confirmation and error queue; Set to '0' to use the private ++ * Tx confirmation and error queue; valid only if ++ * 'DPNI_OPT_PRIVATE_TX_CONF_ERROR_DISABLED' wasn't set at DPNI creation ++ * and 'DPNI_TX_FLOW_OPT_TX_CONF_ERROR' is contained in 'options' ++ * @l3_chksum_gen: Set to '1' to enable L3 checksum generation; '0' to disable; ++ * valid only if 'DPNI_TX_FLOW_OPT_L3_CHKSUM_GEN' is contained in 'options' ++ * @l4_chksum_gen: Set to '1' to enable L4 checksum generation; '0' to disable; ++ * valid only if 'DPNI_TX_FLOW_OPT_L4_CHKSUM_GEN' is contained in 'options' ++ */ ++struct dpni_tx_flow_cfg { ++ uint32_t options; ++ int use_common_tx_conf_queue; ++ int l3_chksum_gen; ++ int l4_chksum_gen; ++}; ++ ++/** ++ * dpni_set_tx_flow() - Set Tx flow configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @flow_id: Provides (or returns) the sender's flow ID; ++ * for each new sender set (*flow_id) to 'DPNI_NEW_FLOW_ID' to generate ++ * a new flow_id; this ID should be used as the QDBIN argument ++ * in enqueue operations ++ * @cfg: Tx flow configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_tx_flow(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t *flow_id, ++ const struct dpni_tx_flow_cfg *cfg); ++ ++/** ++ * struct dpni_tx_flow_attr - Structure representing Tx flow attributes ++ * @use_common_tx_conf_queue: '1' if using common (default) Tx confirmation and ++ * error queue; '0' if using private Tx confirmation and error queue ++ * @l3_chksum_gen: '1' if L3 checksum generation is enabled; '0' if disabled ++ * @l4_chksum_gen: '1' if L4 checksum generation is enabled; '0' if disabled ++ */ ++struct dpni_tx_flow_attr { ++ int use_common_tx_conf_queue; ++ int l3_chksum_gen; ++ int l4_chksum_gen; ++}; ++ ++/** ++ * dpni_get_tx_flow() - Get Tx flow attributes ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @flow_id: The sender's flow ID, as returned by the ++ * dpni_set_tx_flow() function ++ * @attr: Returned Tx flow attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_tx_flow(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t flow_id, ++ struct dpni_tx_flow_attr *attr); ++ ++/** ++ * struct dpni_tx_conf_cfg - Structure representing Tx conf configuration ++ * @errors_only: Set to '1' to report back only error frames; ++ * Set to '0' to confirm transmission/error for all transmitted frames; ++ * @queue_cfg: Queue configuration ++ */ ++struct dpni_tx_conf_cfg { ++ int errors_only; ++ struct dpni_queue_cfg queue_cfg; ++}; ++ ++/** ++ * dpni_set_tx_conf() - Set Tx confirmation and error queue configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @flow_id: The sender's flow ID, as returned by the ++ * dpni_set_tx_flow() function; ++ * use 'DPNI_COMMON_TX_CONF' for common tx-conf ++ * @cfg: Queue configuration ++ * ++ * If either 'DPNI_OPT_TX_CONF_DISABLED' or ++ * 'DPNI_OPT_PRIVATE_TX_CONF_ERROR_DISABLED' were selected at DPNI creation, ++ * this function can ONLY be used with 'flow_id == DPNI_COMMON_TX_CONF'; ++ * i.e. only serve the common tx-conf-err queue; ++ * if 'DPNI_OPT_TX_CONF_DISABLED' was selected, only error frames are reported ++ * back - successfully transmitted frames are not confirmed. Otherwise, all ++ * transmitted frames are sent for confirmation. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_tx_conf(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t flow_id, ++ const struct dpni_tx_conf_cfg *cfg); ++ ++/** ++ * struct dpni_tx_conf_attr - Structure representing Tx conf attributes ++ * @errors_only: '1' if only error frames are reported back; '0' if all ++ * transmitted frames are confirmed ++ * @queue_attr: Queue attributes ++ */ ++struct dpni_tx_conf_attr { ++ int errors_only; ++ struct dpni_queue_attr queue_attr; ++}; ++ ++/** ++ * dpni_get_tx_conf() - Get Tx confirmation and error queue attributes ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @flow_id: The sender's flow ID, as returned by the ++ * dpni_set_tx_flow() function; ++ * use 'DPNI_COMMON_TX_CONF' for common tx-conf ++ * @attr: Returned tx-conf attributes ++ * ++ * If either 'DPNI_OPT_TX_CONF_DISABLED' or ++ * 'DPNI_OPT_PRIVATE_TX_CONF_ERROR_DISABLED' were selected at DPNI creation, ++ * this function can ONLY be used with 'flow_id == DPNI_COMMON_TX_CONF'; ++ * i.e. only serve the common tx-conf-err queue; ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_tx_conf(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t flow_id, ++ struct dpni_tx_conf_attr *attr); ++ ++/** ++ * dpni_set_tx_conf_congestion_notification() - Set Tx conf congestion ++ * notification configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @flow_id: The sender's flow ID, as returned by the ++ * dpni_set_tx_flow() function; ++ * use 'DPNI_COMMON_TX_CONF' for common tx-conf ++ * @cfg: congestion notification configuration ++ * ++ * If either 'DPNI_OPT_TX_CONF_DISABLED' or ++ * 'DPNI_OPT_PRIVATE_TX_CONF_ERROR_DISABLED' were selected at DPNI creation, ++ * this function can ONLY be used with 'flow_id == DPNI_COMMON_TX_CONF'; ++ * i.e. only serve the common tx-conf-err queue; ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpni_set_tx_conf_congestion_notification(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t flow_id, ++ const struct dpni_congestion_notification_cfg *cfg); ++ ++/** ++ * dpni_get_tx_conf_congestion_notification() - Get Tx conf congestion ++ * notification configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @flow_id: The sender's flow ID, as returned by the ++ * dpni_set_tx_flow() function; ++ * use 'DPNI_COMMON_TX_CONF' for common tx-conf ++ * @cfg: congestion notification ++ * ++ * If either 'DPNI_OPT_TX_CONF_DISABLED' or ++ * 'DPNI_OPT_PRIVATE_TX_CONF_ERROR_DISABLED' were selected at DPNI creation, ++ * this function can ONLY be used with 'flow_id == DPNI_COMMON_TX_CONF'; ++ * i.e. only serve the common tx-conf-err queue; ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpni_get_tx_conf_congestion_notification(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t flow_id, ++ struct dpni_congestion_notification_cfg *cfg); ++ ++/** ++ * dpni_set_tx_conf_revoke() - Tx confirmation revocation ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @revoke: revoke or not ++ * ++ * This function is useful only when 'DPNI_OPT_TX_CONF_DISABLED' is not ++ * selected at DPNI creation. ++ * Calling this function with 'revoke' set to '1' disables all transmit ++ * confirmation (including the private confirmation queues), regardless of ++ * previous settings; Note that in this case, Tx error frames are still ++ * enqueued to the general transmit errors queue. ++ * Calling this function with 'revoke' set to '0' restores the previous ++ * settings for both general and private transmit confirmation. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_tx_conf_revoke(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int revoke); ++ ++/** ++ * dpni_set_rx_flow() - Set Rx flow configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @tc_id: Traffic class selection (0-7); ++ * use 'DPNI_ALL_TCS' to set all TCs and all flows ++ * @flow_id: Rx flow id within the traffic class; use ++ * 'DPNI_ALL_TC_FLOWS' to set all flows within ++ * this tc_id; ignored if tc_id is set to ++ * 'DPNI_ALL_TCS'; ++ * @cfg: Rx flow configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_rx_flow(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ uint16_t flow_id, ++ const struct dpni_queue_cfg *cfg); ++ ++/** ++ * dpni_get_rx_flow() - Get Rx flow attributes ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @tc_id: Traffic class selection (0-7) ++ * @flow_id: Rx flow id within the traffic class ++ * @attr: Returned Rx flow attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_rx_flow(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ uint16_t flow_id, ++ struct dpni_queue_attr *attr); ++ ++/** ++ * dpni_set_rx_err_queue() - Set Rx error queue configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @cfg: Queue configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_rx_err_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_queue_cfg *cfg); ++ ++/** ++ * dpni_get_rx_err_queue() - Get Rx error queue attributes ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @attr: Returned Queue attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_rx_err_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpni_queue_attr *attr); ++ ++/** ++ * struct dpni_qos_tbl_cfg - Structure representing QOS table configuration ++ * @key_cfg_iova: I/O virtual address of 256 bytes DMA-able memory filled with ++ * key extractions to be used as the QoS criteria by calling ++ * dpni_prepare_key_cfg() ++ * @discard_on_miss: Set to '1' to discard frames in case of no match (miss); ++ * '0' to use the 'default_tc' in such cases ++ * @default_tc: Used in case of no-match and 'discard_on_miss'= 0 ++ */ ++struct dpni_qos_tbl_cfg { ++ uint64_t key_cfg_iova; ++ int discard_on_miss; ++ uint8_t default_tc; ++}; ++ ++/** ++ * dpni_set_qos_table() - Set QoS mapping table ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @cfg: QoS table configuration ++ * ++ * This function and all QoS-related functions require that ++ *'max_tcs > 1' was set at DPNI creation. ++ * ++ * warning: Before calling this function, call dpni_prepare_key_cfg() to ++ * prepare the key_cfg_iova parameter ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_qos_table(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_qos_tbl_cfg *cfg); ++ ++/** ++ * struct dpni_rule_cfg - Rule configuration for table lookup ++ * @key_iova: I/O virtual address of the key (must be in DMA-able memory) ++ * @mask_iova: I/O virtual address of the mask (must be in DMA-able memory) ++ * @key_size: key and mask size (in bytes) ++ */ ++struct dpni_rule_cfg { ++ uint64_t key_iova; ++ uint64_t mask_iova; ++ uint8_t key_size; ++}; ++ ++/** ++ * dpni_add_qos_entry() - Add QoS mapping entry (to select a traffic class) ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @cfg: QoS rule to add ++ * @tc_id: Traffic class selection (0-7) ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_add_qos_entry(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_rule_cfg *cfg, ++ uint8_t tc_id); ++ ++/** ++ * dpni_remove_qos_entry() - Remove QoS mapping entry ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @cfg: QoS rule to remove ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_remove_qos_entry(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_rule_cfg *cfg); ++ ++/** ++ * dpni_clear_qos_table() - Clear all QoS mapping entries ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * ++ * Following this function call, all frames are directed to ++ * the default traffic class (0) ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_clear_qos_table(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpni_add_fs_entry() - Add Flow Steering entry for a specific traffic class ++ * (to select a flow ID) ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @tc_id: Traffic class selection (0-7) ++ * @cfg: Flow steering rule to add ++ * @flow_id: Flow id selection (must be smaller than the ++ * distribution size of the traffic class) ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_add_fs_entry(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ const struct dpni_rule_cfg *cfg, ++ uint16_t flow_id); ++ ++/** ++ * dpni_remove_fs_entry() - Remove Flow Steering entry from a specific ++ * traffic class ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @tc_id: Traffic class selection (0-7) ++ * @cfg: Flow steering rule to remove ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_remove_fs_entry(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ const struct dpni_rule_cfg *cfg); ++ ++/** ++ * dpni_clear_fs_entries() - Clear all Flow Steering entries of a specific ++ * traffic class ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @tc_id: Traffic class selection (0-7) ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_clear_fs_entries(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id); ++ ++/** ++ * dpni_set_vlan_insertion() - Enable/disable VLAN insertion for egress frames ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @en: Set to '1' to enable; '0' to disable ++ * ++ * Requires that the 'DPNI_OPT_VLAN_MANIPULATION' option is set ++ * at DPNI creation. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_vlan_insertion(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en); ++ ++/** ++ * dpni_set_vlan_removal() - Enable/disable VLAN removal for ingress frames ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @en: Set to '1' to enable; '0' to disable ++ * ++ * Requires that the 'DPNI_OPT_VLAN_MANIPULATION' option is set ++ * at DPNI creation. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_vlan_removal(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en); ++ ++/** ++ * dpni_set_ipr() - Enable/disable IP reassembly of ingress frames ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @en: Set to '1' to enable; '0' to disable ++ * ++ * Requires that the 'DPNI_OPT_IPR' option is set at DPNI creation. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_ipr(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en); ++ ++/** ++ * dpni_set_ipf() - Enable/disable IP fragmentation of egress frames ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @en: Set to '1' to enable; '0' to disable ++ * ++ * Requires that the 'DPNI_OPT_IPF' option is set at DPNI ++ * creation. Fragmentation is performed according to MTU value ++ * set by dpni_set_mtu() function ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_ipf(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en); ++ ++#endif /* __FSL_DPNI_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h +new file mode 100644 +index 0000000..c0f8af0 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h +@@ -0,0 +1,1058 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_DPNI_CMD_H ++#define _FSL_DPNI_CMD_H ++ ++/* DPNI Version */ ++#define DPNI_VER_MAJOR 6 ++#define DPNI_VER_MINOR 0 ++ ++/* Command IDs */ ++#define DPNI_CMDID_OPEN 0x801 ++#define DPNI_CMDID_CLOSE 0x800 ++#define DPNI_CMDID_CREATE 0x901 ++#define DPNI_CMDID_DESTROY 0x900 ++ ++#define DPNI_CMDID_ENABLE 0x002 ++#define DPNI_CMDID_DISABLE 0x003 ++#define DPNI_CMDID_GET_ATTR 0x004 ++#define DPNI_CMDID_RESET 0x005 ++#define DPNI_CMDID_IS_ENABLED 0x006 ++ ++#define DPNI_CMDID_SET_IRQ 0x010 ++#define DPNI_CMDID_GET_IRQ 0x011 ++#define DPNI_CMDID_SET_IRQ_ENABLE 0x012 ++#define DPNI_CMDID_GET_IRQ_ENABLE 0x013 ++#define DPNI_CMDID_SET_IRQ_MASK 0x014 ++#define DPNI_CMDID_GET_IRQ_MASK 0x015 ++#define DPNI_CMDID_GET_IRQ_STATUS 0x016 ++#define DPNI_CMDID_CLEAR_IRQ_STATUS 0x017 ++ ++#define DPNI_CMDID_SET_POOLS 0x200 ++#define DPNI_CMDID_GET_RX_BUFFER_LAYOUT 0x201 ++#define DPNI_CMDID_SET_RX_BUFFER_LAYOUT 0x202 ++#define DPNI_CMDID_GET_TX_BUFFER_LAYOUT 0x203 ++#define DPNI_CMDID_SET_TX_BUFFER_LAYOUT 0x204 ++#define DPNI_CMDID_SET_TX_CONF_BUFFER_LAYOUT 0x205 ++#define DPNI_CMDID_GET_TX_CONF_BUFFER_LAYOUT 0x206 ++#define DPNI_CMDID_SET_L3_CHKSUM_VALIDATION 0x207 ++#define DPNI_CMDID_GET_L3_CHKSUM_VALIDATION 0x208 ++#define DPNI_CMDID_SET_L4_CHKSUM_VALIDATION 0x209 ++#define DPNI_CMDID_GET_L4_CHKSUM_VALIDATION 0x20A ++#define DPNI_CMDID_SET_ERRORS_BEHAVIOR 0x20B ++#define DPNI_CMDID_SET_TX_CONF_REVOKE 0x20C ++ ++#define DPNI_CMDID_GET_QDID 0x210 ++#define DPNI_CMDID_GET_SP_INFO 0x211 ++#define DPNI_CMDID_GET_TX_DATA_OFFSET 0x212 ++#define DPNI_CMDID_GET_COUNTER 0x213 ++#define DPNI_CMDID_SET_COUNTER 0x214 ++#define DPNI_CMDID_GET_LINK_STATE 0x215 ++#define DPNI_CMDID_SET_MAX_FRAME_LENGTH 0x216 ++#define DPNI_CMDID_GET_MAX_FRAME_LENGTH 0x217 ++#define DPNI_CMDID_SET_MTU 0x218 ++#define DPNI_CMDID_GET_MTU 0x219 ++#define DPNI_CMDID_SET_LINK_CFG 0x21A ++#define DPNI_CMDID_SET_TX_SHAPING 0x21B ++ ++#define DPNI_CMDID_SET_MCAST_PROMISC 0x220 ++#define DPNI_CMDID_GET_MCAST_PROMISC 0x221 ++#define DPNI_CMDID_SET_UNICAST_PROMISC 0x222 ++#define DPNI_CMDID_GET_UNICAST_PROMISC 0x223 ++#define DPNI_CMDID_SET_PRIM_MAC 0x224 ++#define DPNI_CMDID_GET_PRIM_MAC 0x225 ++#define DPNI_CMDID_ADD_MAC_ADDR 0x226 ++#define DPNI_CMDID_REMOVE_MAC_ADDR 0x227 ++#define DPNI_CMDID_CLR_MAC_FILTERS 0x228 ++ ++#define DPNI_CMDID_SET_VLAN_FILTERS 0x230 ++#define DPNI_CMDID_ADD_VLAN_ID 0x231 ++#define DPNI_CMDID_REMOVE_VLAN_ID 0x232 ++#define DPNI_CMDID_CLR_VLAN_FILTERS 0x233 ++ ++#define DPNI_CMDID_SET_RX_TC_DIST 0x235 ++#define DPNI_CMDID_SET_TX_FLOW 0x236 ++#define DPNI_CMDID_GET_TX_FLOW 0x237 ++#define DPNI_CMDID_SET_RX_FLOW 0x238 ++#define DPNI_CMDID_GET_RX_FLOW 0x239 ++#define DPNI_CMDID_SET_RX_ERR_QUEUE 0x23A ++#define DPNI_CMDID_GET_RX_ERR_QUEUE 0x23B ++ ++#define DPNI_CMDID_SET_RX_TC_POLICING 0x23E ++#define DPNI_CMDID_SET_RX_TC_EARLY_DROP 0x23F ++ ++#define DPNI_CMDID_SET_QOS_TBL 0x240 ++#define DPNI_CMDID_ADD_QOS_ENT 0x241 ++#define DPNI_CMDID_REMOVE_QOS_ENT 0x242 ++#define DPNI_CMDID_CLR_QOS_TBL 0x243 ++#define DPNI_CMDID_ADD_FS_ENT 0x244 ++#define DPNI_CMDID_REMOVE_FS_ENT 0x245 ++#define DPNI_CMDID_CLR_FS_ENT 0x246 ++#define DPNI_CMDID_SET_VLAN_INSERTION 0x247 ++#define DPNI_CMDID_SET_VLAN_REMOVAL 0x248 ++#define DPNI_CMDID_SET_IPR 0x249 ++#define DPNI_CMDID_SET_IPF 0x24A ++ ++#define DPNI_CMDID_SET_TX_SELECTION 0x250 ++#define DPNI_CMDID_GET_RX_TC_POLICING 0x251 ++#define DPNI_CMDID_GET_RX_TC_EARLY_DROP 0x252 ++#define DPNI_CMDID_SET_RX_TC_CONGESTION_NOTIFICATION 0x253 ++#define DPNI_CMDID_GET_RX_TC_CONGESTION_NOTIFICATION 0x254 ++#define DPNI_CMDID_SET_TX_TC_CONGESTION_NOTIFICATION 0x255 ++#define DPNI_CMDID_GET_TX_TC_CONGESTION_NOTIFICATION 0x256 ++#define DPNI_CMDID_SET_TX_CONF 0x257 ++#define DPNI_CMDID_GET_TX_CONF 0x258 ++#define DPNI_CMDID_SET_TX_CONF_CONGESTION_NOTIFICATION 0x259 ++#define DPNI_CMDID_GET_TX_CONF_CONGESTION_NOTIFICATION 0x25A ++#define DPNI_CMDID_SET_TX_TC_EARLY_DROP 0x25B ++#define DPNI_CMDID_GET_TX_TC_EARLY_DROP 0x25C ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_OPEN(cmd, dpni_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpni_id) ++ ++#define DPNI_PREP_EXTENDED_CFG(ext, cfg) \ ++do { \ ++ MC_PREP_OP(ext, 0, 0, 16, uint16_t, cfg->tc_cfg[0].max_dist); \ ++ MC_PREP_OP(ext, 0, 16, 16, uint16_t, cfg->tc_cfg[0].max_fs_entries); \ ++ MC_PREP_OP(ext, 0, 32, 16, uint16_t, cfg->tc_cfg[1].max_dist); \ ++ MC_PREP_OP(ext, 0, 48, 16, uint16_t, cfg->tc_cfg[1].max_fs_entries); \ ++ MC_PREP_OP(ext, 1, 0, 16, uint16_t, cfg->tc_cfg[2].max_dist); \ ++ MC_PREP_OP(ext, 1, 16, 16, uint16_t, cfg->tc_cfg[2].max_fs_entries); \ ++ MC_PREP_OP(ext, 1, 32, 16, uint16_t, cfg->tc_cfg[3].max_dist); \ ++ MC_PREP_OP(ext, 1, 48, 16, uint16_t, cfg->tc_cfg[3].max_fs_entries); \ ++ MC_PREP_OP(ext, 2, 0, 16, uint16_t, cfg->tc_cfg[4].max_dist); \ ++ MC_PREP_OP(ext, 2, 16, 16, uint16_t, cfg->tc_cfg[4].max_fs_entries); \ ++ MC_PREP_OP(ext, 2, 32, 16, uint16_t, cfg->tc_cfg[5].max_dist); \ ++ MC_PREP_OP(ext, 2, 48, 16, uint16_t, cfg->tc_cfg[5].max_fs_entries); \ ++ MC_PREP_OP(ext, 3, 0, 16, uint16_t, cfg->tc_cfg[6].max_dist); \ ++ MC_PREP_OP(ext, 3, 16, 16, uint16_t, cfg->tc_cfg[6].max_fs_entries); \ ++ MC_PREP_OP(ext, 3, 32, 16, uint16_t, cfg->tc_cfg[7].max_dist); \ ++ MC_PREP_OP(ext, 3, 48, 16, uint16_t, cfg->tc_cfg[7].max_fs_entries); \ ++ MC_PREP_OP(ext, 4, 0, 16, uint16_t, \ ++ cfg->ipr_cfg.max_open_frames_ipv4); \ ++ MC_PREP_OP(ext, 4, 16, 16, uint16_t, \ ++ cfg->ipr_cfg.max_open_frames_ipv6); \ ++ MC_PREP_OP(ext, 4, 32, 16, uint16_t, \ ++ cfg->ipr_cfg.max_reass_frm_size); \ ++ MC_PREP_OP(ext, 5, 0, 16, uint16_t, \ ++ cfg->ipr_cfg.min_frag_size_ipv4); \ ++ MC_PREP_OP(ext, 5, 16, 16, uint16_t, \ ++ cfg->ipr_cfg.min_frag_size_ipv6); \ ++} while (0) ++ ++#define DPNI_EXT_EXTENDED_CFG(ext, cfg) \ ++do { \ ++ MC_EXT_OP(ext, 0, 0, 16, uint16_t, cfg->tc_cfg[0].max_dist); \ ++ MC_EXT_OP(ext, 0, 16, 16, uint16_t, cfg->tc_cfg[0].max_fs_entries); \ ++ MC_EXT_OP(ext, 0, 32, 16, uint16_t, cfg->tc_cfg[1].max_dist); \ ++ MC_EXT_OP(ext, 0, 48, 16, uint16_t, cfg->tc_cfg[1].max_fs_entries); \ ++ MC_EXT_OP(ext, 1, 0, 16, uint16_t, cfg->tc_cfg[2].max_dist); \ ++ MC_EXT_OP(ext, 1, 16, 16, uint16_t, cfg->tc_cfg[2].max_fs_entries); \ ++ MC_EXT_OP(ext, 1, 32, 16, uint16_t, cfg->tc_cfg[3].max_dist); \ ++ MC_EXT_OP(ext, 1, 48, 16, uint16_t, cfg->tc_cfg[3].max_fs_entries); \ ++ MC_EXT_OP(ext, 2, 0, 16, uint16_t, cfg->tc_cfg[4].max_dist); \ ++ MC_EXT_OP(ext, 2, 16, 16, uint16_t, cfg->tc_cfg[4].max_fs_entries); \ ++ MC_EXT_OP(ext, 2, 32, 16, uint16_t, cfg->tc_cfg[5].max_dist); \ ++ MC_EXT_OP(ext, 2, 48, 16, uint16_t, cfg->tc_cfg[5].max_fs_entries); \ ++ MC_EXT_OP(ext, 3, 0, 16, uint16_t, cfg->tc_cfg[6].max_dist); \ ++ MC_EXT_OP(ext, 3, 16, 16, uint16_t, cfg->tc_cfg[6].max_fs_entries); \ ++ MC_EXT_OP(ext, 3, 32, 16, uint16_t, cfg->tc_cfg[7].max_dist); \ ++ MC_EXT_OP(ext, 3, 48, 16, uint16_t, cfg->tc_cfg[7].max_fs_entries); \ ++ MC_EXT_OP(ext, 4, 0, 16, uint16_t, \ ++ cfg->ipr_cfg.max_open_frames_ipv4); \ ++ MC_EXT_OP(ext, 4, 16, 16, uint16_t, \ ++ cfg->ipr_cfg.max_open_frames_ipv6); \ ++ MC_EXT_OP(ext, 4, 32, 16, uint16_t, \ ++ cfg->ipr_cfg.max_reass_frm_size); \ ++ MC_EXT_OP(ext, 5, 0, 16, uint16_t, \ ++ cfg->ipr_cfg.min_frag_size_ipv4); \ ++ MC_EXT_OP(ext, 5, 16, 16, uint16_t, \ ++ cfg->ipr_cfg.min_frag_size_ipv6); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_CREATE(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, cfg->adv.max_tcs); \ ++ MC_CMD_OP(cmd, 0, 8, 8, uint8_t, cfg->adv.max_senders); \ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, cfg->mac_addr[5]); \ ++ MC_CMD_OP(cmd, 0, 24, 8, uint8_t, cfg->mac_addr[4]); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->mac_addr[3]); \ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, cfg->mac_addr[2]); \ ++ MC_CMD_OP(cmd, 0, 48, 8, uint8_t, cfg->mac_addr[1]); \ ++ MC_CMD_OP(cmd, 0, 56, 8, uint8_t, cfg->mac_addr[0]); \ ++ MC_CMD_OP(cmd, 1, 0, 32, uint32_t, cfg->adv.options); \ ++ MC_CMD_OP(cmd, 2, 0, 8, uint8_t, cfg->adv.max_unicast_filters); \ ++ MC_CMD_OP(cmd, 2, 8, 8, uint8_t, cfg->adv.max_multicast_filters); \ ++ MC_CMD_OP(cmd, 2, 16, 8, uint8_t, cfg->adv.max_vlan_filters); \ ++ MC_CMD_OP(cmd, 2, 24, 8, uint8_t, cfg->adv.max_qos_entries); \ ++ MC_CMD_OP(cmd, 2, 32, 8, uint8_t, cfg->adv.max_qos_key_size); \ ++ MC_CMD_OP(cmd, 2, 48, 8, uint8_t, cfg->adv.max_dist_key_size); \ ++ MC_CMD_OP(cmd, 2, 56, 8, enum net_prot, cfg->adv.start_hdr); \ ++ MC_CMD_OP(cmd, 4, 48, 8, uint8_t, cfg->adv.max_policers); \ ++ MC_CMD_OP(cmd, 4, 56, 8, uint8_t, cfg->adv.max_congestion_ctrl); \ ++ MC_CMD_OP(cmd, 5, 0, 64, uint64_t, cfg->adv.ext_cfg_iova); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_POOLS(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, cfg->num_dpbp); \ ++ MC_CMD_OP(cmd, 0, 8, 1, int, cfg->pools[0].backup_pool); \ ++ MC_CMD_OP(cmd, 0, 9, 1, int, cfg->pools[1].backup_pool); \ ++ MC_CMD_OP(cmd, 0, 10, 1, int, cfg->pools[2].backup_pool); \ ++ MC_CMD_OP(cmd, 0, 11, 1, int, cfg->pools[3].backup_pool); \ ++ MC_CMD_OP(cmd, 0, 12, 1, int, cfg->pools[4].backup_pool); \ ++ MC_CMD_OP(cmd, 0, 13, 1, int, cfg->pools[5].backup_pool); \ ++ MC_CMD_OP(cmd, 0, 14, 1, int, cfg->pools[6].backup_pool); \ ++ MC_CMD_OP(cmd, 0, 15, 1, int, cfg->pools[7].backup_pool); \ ++ MC_CMD_OP(cmd, 0, 32, 32, int, cfg->pools[0].dpbp_id); \ ++ MC_CMD_OP(cmd, 4, 32, 16, uint16_t, cfg->pools[0].buffer_size);\ ++ MC_CMD_OP(cmd, 1, 0, 32, int, cfg->pools[1].dpbp_id); \ ++ MC_CMD_OP(cmd, 4, 48, 16, uint16_t, cfg->pools[1].buffer_size);\ ++ MC_CMD_OP(cmd, 1, 32, 32, int, cfg->pools[2].dpbp_id); \ ++ MC_CMD_OP(cmd, 5, 0, 16, uint16_t, cfg->pools[2].buffer_size);\ ++ MC_CMD_OP(cmd, 2, 0, 32, int, cfg->pools[3].dpbp_id); \ ++ MC_CMD_OP(cmd, 5, 16, 16, uint16_t, cfg->pools[3].buffer_size);\ ++ MC_CMD_OP(cmd, 2, 32, 32, int, cfg->pools[4].dpbp_id); \ ++ MC_CMD_OP(cmd, 5, 32, 16, uint16_t, cfg->pools[4].buffer_size);\ ++ MC_CMD_OP(cmd, 3, 0, 32, int, cfg->pools[5].dpbp_id); \ ++ MC_CMD_OP(cmd, 5, 48, 16, uint16_t, cfg->pools[5].buffer_size);\ ++ MC_CMD_OP(cmd, 3, 32, 32, int, cfg->pools[6].dpbp_id); \ ++ MC_CMD_OP(cmd, 6, 0, 16, uint16_t, cfg->pools[6].buffer_size);\ ++ MC_CMD_OP(cmd, 4, 0, 32, int, cfg->pools[7].dpbp_id); \ ++ MC_CMD_OP(cmd, 6, 16, 16, uint16_t, cfg->pools[7].buffer_size);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_IS_ENABLED(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr); \ ++ MC_CMD_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_GET_IRQ(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_IRQ(cmd, type, irq_cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr); \ ++ MC_RSP_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, type); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_IRQ_ENABLE(cmd, irq_index, en) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, en); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_GET_IRQ_ENABLE(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_IRQ_ENABLE(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 8, uint8_t, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, mask); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_GET_IRQ_MASK(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_IRQ_MASK(cmd, mask) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mask) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_IRQ_STATUS(cmd, status) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, status) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_GET_ATTR(cmd, attr) \ ++ MC_CMD_OP(cmd, 6, 0, 64, uint64_t, attr->ext_cfg_iova) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_ATTR(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, attr->id);\ ++ MC_RSP_OP(cmd, 0, 32, 8, uint8_t, attr->max_tcs); \ ++ MC_RSP_OP(cmd, 0, 40, 8, uint8_t, attr->max_senders); \ ++ MC_RSP_OP(cmd, 0, 48, 8, enum net_prot, attr->start_hdr); \ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, attr->options); \ ++ MC_RSP_OP(cmd, 2, 0, 8, uint8_t, attr->max_unicast_filters); \ ++ MC_RSP_OP(cmd, 2, 8, 8, uint8_t, attr->max_multicast_filters);\ ++ MC_RSP_OP(cmd, 2, 16, 8, uint8_t, attr->max_vlan_filters); \ ++ MC_RSP_OP(cmd, 2, 24, 8, uint8_t, attr->max_qos_entries); \ ++ MC_RSP_OP(cmd, 2, 32, 8, uint8_t, attr->max_qos_key_size); \ ++ MC_RSP_OP(cmd, 2, 40, 8, uint8_t, attr->max_dist_key_size); \ ++ MC_RSP_OP(cmd, 4, 48, 8, uint8_t, attr->max_policers); \ ++ MC_RSP_OP(cmd, 4, 56, 8, uint8_t, attr->max_congestion_ctrl); \ ++ MC_RSP_OP(cmd, 5, 32, 16, uint16_t, attr->version.major);\ ++ MC_RSP_OP(cmd, 5, 48, 16, uint16_t, attr->version.minor);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_ERRORS_BEHAVIOR(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, cfg->errors); \ ++ MC_CMD_OP(cmd, 0, 32, 4, enum dpni_error_action, cfg->error_action); \ ++ MC_CMD_OP(cmd, 0, 36, 1, int, cfg->set_frame_annotation); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_RX_BUFFER_LAYOUT(cmd, layout) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 16, uint16_t, layout->private_data_size); \ ++ MC_RSP_OP(cmd, 0, 16, 16, uint16_t, layout->data_align); \ ++ MC_RSP_OP(cmd, 1, 0, 1, int, layout->pass_timestamp); \ ++ MC_RSP_OP(cmd, 1, 1, 1, int, layout->pass_parser_result); \ ++ MC_RSP_OP(cmd, 1, 2, 1, int, layout->pass_frame_status); \ ++ MC_RSP_OP(cmd, 1, 16, 16, uint16_t, layout->data_head_room); \ ++ MC_RSP_OP(cmd, 1, 32, 16, uint16_t, layout->data_tail_room); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_RX_BUFFER_LAYOUT(cmd, layout) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, layout->private_data_size); \ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, layout->data_align); \ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, layout->options); \ ++ MC_CMD_OP(cmd, 1, 0, 1, int, layout->pass_timestamp); \ ++ MC_CMD_OP(cmd, 1, 1, 1, int, layout->pass_parser_result); \ ++ MC_CMD_OP(cmd, 1, 2, 1, int, layout->pass_frame_status); \ ++ MC_CMD_OP(cmd, 1, 16, 16, uint16_t, layout->data_head_room); \ ++ MC_CMD_OP(cmd, 1, 32, 16, uint16_t, layout->data_tail_room); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_TX_BUFFER_LAYOUT(cmd, layout) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 16, uint16_t, layout->private_data_size); \ ++ MC_RSP_OP(cmd, 0, 16, 16, uint16_t, layout->data_align); \ ++ MC_RSP_OP(cmd, 1, 0, 1, int, layout->pass_timestamp); \ ++ MC_RSP_OP(cmd, 1, 1, 1, int, layout->pass_parser_result); \ ++ MC_RSP_OP(cmd, 1, 2, 1, int, layout->pass_frame_status); \ ++ MC_RSP_OP(cmd, 1, 16, 16, uint16_t, layout->data_head_room); \ ++ MC_RSP_OP(cmd, 1, 32, 16, uint16_t, layout->data_tail_room); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_TX_BUFFER_LAYOUT(cmd, layout) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, layout->private_data_size); \ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, layout->data_align); \ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, layout->options); \ ++ MC_CMD_OP(cmd, 1, 0, 1, int, layout->pass_timestamp); \ ++ MC_CMD_OP(cmd, 1, 1, 1, int, layout->pass_parser_result); \ ++ MC_CMD_OP(cmd, 1, 2, 1, int, layout->pass_frame_status); \ ++ MC_CMD_OP(cmd, 1, 16, 16, uint16_t, layout->data_head_room); \ ++ MC_CMD_OP(cmd, 1, 32, 16, uint16_t, layout->data_tail_room); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_TX_CONF_BUFFER_LAYOUT(cmd, layout) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 16, uint16_t, layout->private_data_size); \ ++ MC_RSP_OP(cmd, 0, 16, 16, uint16_t, layout->data_align); \ ++ MC_RSP_OP(cmd, 1, 0, 1, int, layout->pass_timestamp); \ ++ MC_RSP_OP(cmd, 1, 1, 1, int, layout->pass_parser_result); \ ++ MC_RSP_OP(cmd, 1, 2, 1, int, layout->pass_frame_status); \ ++ MC_RSP_OP(cmd, 1, 16, 16, uint16_t, layout->data_head_room); \ ++ MC_RSP_OP(cmd, 1, 32, 16, uint16_t, layout->data_tail_room); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_TX_CONF_BUFFER_LAYOUT(cmd, layout) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, layout->private_data_size); \ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, layout->data_align); \ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, layout->options); \ ++ MC_CMD_OP(cmd, 1, 0, 1, int, layout->pass_timestamp); \ ++ MC_CMD_OP(cmd, 1, 1, 1, int, layout->pass_parser_result); \ ++ MC_CMD_OP(cmd, 1, 2, 1, int, layout->pass_frame_status); \ ++ MC_CMD_OP(cmd, 1, 16, 16, uint16_t, layout->data_head_room); \ ++ MC_CMD_OP(cmd, 1, 32, 16, uint16_t, layout->data_tail_room); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_L3_CHKSUM_VALIDATION(cmd, en) \ ++ MC_CMD_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_L3_CHKSUM_VALIDATION(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_L4_CHKSUM_VALIDATION(cmd, en) \ ++ MC_CMD_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_L4_CHKSUM_VALIDATION(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_QDID(cmd, qdid) \ ++ MC_RSP_OP(cmd, 0, 0, 16, uint16_t, qdid) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_SP_INFO(cmd, sp_info) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 16, uint16_t, sp_info->spids[0]); \ ++ MC_RSP_OP(cmd, 0, 16, 16, uint16_t, sp_info->spids[1]); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_TX_DATA_OFFSET(cmd, data_offset) \ ++ MC_RSP_OP(cmd, 0, 0, 16, uint16_t, data_offset) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_GET_COUNTER(cmd, counter) \ ++ MC_CMD_OP(cmd, 0, 0, 16, enum dpni_counter, counter) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_COUNTER(cmd, value) \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, value) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_COUNTER(cmd, counter, value) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, enum dpni_counter, counter); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, value); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_LINK_CFG(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 1, 0, 32, uint32_t, cfg->rate);\ ++ MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->options);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_LINK_STATE(cmd, state) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 32, 1, int, state->up);\ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, state->rate);\ ++ MC_RSP_OP(cmd, 2, 0, 64, uint64_t, state->options);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_TX_SHAPING(cmd, tx_shaper) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, tx_shaper->max_burst_size);\ ++ MC_CMD_OP(cmd, 1, 0, 32, uint32_t, tx_shaper->rate_limit);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_MAX_FRAME_LENGTH(cmd, max_frame_length) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, max_frame_length) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_MAX_FRAME_LENGTH(cmd, max_frame_length) \ ++ MC_RSP_OP(cmd, 0, 0, 16, uint16_t, max_frame_length) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_MTU(cmd, mtu) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, mtu) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_MTU(cmd, mtu) \ ++ MC_RSP_OP(cmd, 0, 0, 16, uint16_t, mtu) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_MULTICAST_PROMISC(cmd, en) \ ++ MC_CMD_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_MULTICAST_PROMISC(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_UNICAST_PROMISC(cmd, en) \ ++ MC_CMD_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_UNICAST_PROMISC(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_PRIMARY_MAC_ADDR(cmd, mac_addr) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, mac_addr[5]); \ ++ MC_CMD_OP(cmd, 0, 24, 8, uint8_t, mac_addr[4]); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, mac_addr[3]); \ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, mac_addr[2]); \ ++ MC_CMD_OP(cmd, 0, 48, 8, uint8_t, mac_addr[1]); \ ++ MC_CMD_OP(cmd, 0, 56, 8, uint8_t, mac_addr[0]); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_PRIMARY_MAC_ADDR(cmd, mac_addr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 16, 8, uint8_t, mac_addr[5]); \ ++ MC_RSP_OP(cmd, 0, 24, 8, uint8_t, mac_addr[4]); \ ++ MC_RSP_OP(cmd, 0, 32, 8, uint8_t, mac_addr[3]); \ ++ MC_RSP_OP(cmd, 0, 40, 8, uint8_t, mac_addr[2]); \ ++ MC_RSP_OP(cmd, 0, 48, 8, uint8_t, mac_addr[1]); \ ++ MC_RSP_OP(cmd, 0, 56, 8, uint8_t, mac_addr[0]); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_ADD_MAC_ADDR(cmd, mac_addr) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, mac_addr[5]); \ ++ MC_CMD_OP(cmd, 0, 24, 8, uint8_t, mac_addr[4]); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, mac_addr[3]); \ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, mac_addr[2]); \ ++ MC_CMD_OP(cmd, 0, 48, 8, uint8_t, mac_addr[1]); \ ++ MC_CMD_OP(cmd, 0, 56, 8, uint8_t, mac_addr[0]); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_REMOVE_MAC_ADDR(cmd, mac_addr) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, mac_addr[5]); \ ++ MC_CMD_OP(cmd, 0, 24, 8, uint8_t, mac_addr[4]); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, mac_addr[3]); \ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, mac_addr[2]); \ ++ MC_CMD_OP(cmd, 0, 48, 8, uint8_t, mac_addr[1]); \ ++ MC_CMD_OP(cmd, 0, 56, 8, uint8_t, mac_addr[0]); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_CLEAR_MAC_FILTERS(cmd, unicast, multicast) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 1, int, unicast); \ ++ MC_CMD_OP(cmd, 0, 1, 1, int, multicast); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_VLAN_FILTERS(cmd, en) \ ++ MC_CMD_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_ADD_VLAN_ID(cmd, vlan_id) \ ++ MC_CMD_OP(cmd, 0, 32, 16, uint16_t, vlan_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_REMOVE_VLAN_ID(cmd, vlan_id) \ ++ MC_CMD_OP(cmd, 0, 32, 16, uint16_t, vlan_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_TX_SELECTION(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, cfg->tc_sched[0].delta_bandwidth);\ ++ MC_CMD_OP(cmd, 0, 16, 4, enum dpni_tx_schedule_mode, \ ++ cfg->tc_sched[0].mode); \ ++ MC_CMD_OP(cmd, 0, 32, 16, uint16_t, cfg->tc_sched[1].delta_bandwidth);\ ++ MC_CMD_OP(cmd, 0, 48, 4, enum dpni_tx_schedule_mode, \ ++ cfg->tc_sched[1].mode); \ ++ MC_CMD_OP(cmd, 1, 0, 16, uint16_t, cfg->tc_sched[2].delta_bandwidth);\ ++ MC_CMD_OP(cmd, 1, 16, 4, enum dpni_tx_schedule_mode, \ ++ cfg->tc_sched[2].mode); \ ++ MC_CMD_OP(cmd, 1, 32, 16, uint16_t, cfg->tc_sched[3].delta_bandwidth);\ ++ MC_CMD_OP(cmd, 1, 48, 4, enum dpni_tx_schedule_mode, \ ++ cfg->tc_sched[3].mode); \ ++ MC_CMD_OP(cmd, 2, 0, 16, uint16_t, cfg->tc_sched[4].delta_bandwidth);\ ++ MC_CMD_OP(cmd, 2, 16, 4, enum dpni_tx_schedule_mode, \ ++ cfg->tc_sched[4].mode); \ ++ MC_CMD_OP(cmd, 2, 32, 16, uint16_t, cfg->tc_sched[5].delta_bandwidth);\ ++ MC_CMD_OP(cmd, 2, 48, 4, enum dpni_tx_schedule_mode, \ ++ cfg->tc_sched[5].mode); \ ++ MC_CMD_OP(cmd, 3, 0, 16, uint16_t, cfg->tc_sched[6].delta_bandwidth);\ ++ MC_CMD_OP(cmd, 3, 16, 4, enum dpni_tx_schedule_mode, \ ++ cfg->tc_sched[6].mode); \ ++ MC_CMD_OP(cmd, 3, 32, 16, uint16_t, cfg->tc_sched[7].delta_bandwidth);\ ++ MC_CMD_OP(cmd, 3, 48, 4, enum dpni_tx_schedule_mode, \ ++ cfg->tc_sched[7].mode); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_RX_TC_DIST(cmd, tc_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, cfg->dist_size); \ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, tc_id); \ ++ MC_CMD_OP(cmd, 0, 24, 4, enum dpni_dist_mode, cfg->dist_mode); \ ++ MC_CMD_OP(cmd, 0, 28, 4, enum dpni_fs_miss_action, \ ++ cfg->fs_cfg.miss_action); \ ++ MC_CMD_OP(cmd, 0, 48, 16, uint16_t, cfg->fs_cfg.default_flow_id); \ ++ MC_CMD_OP(cmd, 6, 0, 64, uint64_t, cfg->key_cfg_iova); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_TX_FLOW(cmd, flow_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 43, 1, int, cfg->l3_chksum_gen);\ ++ MC_CMD_OP(cmd, 0, 44, 1, int, cfg->l4_chksum_gen);\ ++ MC_CMD_OP(cmd, 0, 45, 1, int, cfg->use_common_tx_conf_queue);\ ++ MC_CMD_OP(cmd, 0, 48, 16, uint16_t, flow_id);\ ++ MC_CMD_OP(cmd, 2, 0, 32, uint32_t, cfg->options);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_SET_TX_FLOW(cmd, flow_id) \ ++ MC_RSP_OP(cmd, 0, 48, 16, uint16_t, flow_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_GET_TX_FLOW(cmd, flow_id) \ ++ MC_CMD_OP(cmd, 0, 48, 16, uint16_t, flow_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_TX_FLOW(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 43, 1, int, attr->l3_chksum_gen);\ ++ MC_RSP_OP(cmd, 0, 44, 1, int, attr->l4_chksum_gen);\ ++ MC_RSP_OP(cmd, 0, 45, 1, int, attr->use_common_tx_conf_queue);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_RX_FLOW(cmd, tc_id, flow_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, cfg->dest_cfg.dest_id); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->dest_cfg.priority);\ ++ MC_CMD_OP(cmd, 0, 40, 2, enum dpni_dest, cfg->dest_cfg.dest_type);\ ++ MC_CMD_OP(cmd, 0, 42, 1, int, cfg->order_preservation_en);\ ++ MC_CMD_OP(cmd, 0, 48, 16, uint16_t, flow_id); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->user_ctx); \ ++ MC_CMD_OP(cmd, 2, 16, 8, uint8_t, tc_id); \ ++ MC_CMD_OP(cmd, 2, 32, 32, uint32_t, cfg->options); \ ++ MC_CMD_OP(cmd, 3, 0, 4, enum dpni_flc_type, cfg->flc_cfg.flc_type); \ ++ MC_CMD_OP(cmd, 3, 4, 4, enum dpni_stash_size, \ ++ cfg->flc_cfg.frame_data_size);\ ++ MC_CMD_OP(cmd, 3, 8, 4, enum dpni_stash_size, \ ++ cfg->flc_cfg.flow_context_size);\ ++ MC_CMD_OP(cmd, 3, 32, 32, uint32_t, cfg->flc_cfg.options);\ ++ MC_CMD_OP(cmd, 4, 0, 64, uint64_t, cfg->flc_cfg.flow_context);\ ++ MC_CMD_OP(cmd, 5, 0, 32, uint32_t, cfg->tail_drop_threshold); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_GET_RX_FLOW(cmd, tc_id, flow_id) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, tc_id); \ ++ MC_CMD_OP(cmd, 0, 48, 16, uint16_t, flow_id); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_RX_FLOW(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, attr->dest_cfg.dest_id); \ ++ MC_RSP_OP(cmd, 0, 32, 8, uint8_t, attr->dest_cfg.priority);\ ++ MC_RSP_OP(cmd, 0, 40, 2, enum dpni_dest, attr->dest_cfg.dest_type); \ ++ MC_RSP_OP(cmd, 0, 42, 1, int, attr->order_preservation_en);\ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, attr->user_ctx); \ ++ MC_RSP_OP(cmd, 2, 0, 32, uint32_t, attr->tail_drop_threshold); \ ++ MC_RSP_OP(cmd, 2, 32, 32, uint32_t, attr->fqid); \ ++ MC_RSP_OP(cmd, 3, 0, 4, enum dpni_flc_type, attr->flc_cfg.flc_type); \ ++ MC_RSP_OP(cmd, 3, 4, 4, enum dpni_stash_size, \ ++ attr->flc_cfg.frame_data_size);\ ++ MC_RSP_OP(cmd, 3, 8, 4, enum dpni_stash_size, \ ++ attr->flc_cfg.flow_context_size);\ ++ MC_RSP_OP(cmd, 3, 32, 32, uint32_t, attr->flc_cfg.options);\ ++ MC_RSP_OP(cmd, 4, 0, 64, uint64_t, attr->flc_cfg.flow_context);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_RX_ERR_QUEUE(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, cfg->dest_cfg.dest_id); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->dest_cfg.priority);\ ++ MC_CMD_OP(cmd, 0, 40, 2, enum dpni_dest, cfg->dest_cfg.dest_type);\ ++ MC_CMD_OP(cmd, 0, 42, 1, int, cfg->order_preservation_en);\ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->user_ctx); \ ++ MC_CMD_OP(cmd, 2, 0, 32, uint32_t, cfg->options); \ ++ MC_CMD_OP(cmd, 2, 32, 32, uint32_t, cfg->tail_drop_threshold); \ ++ MC_CMD_OP(cmd, 3, 0, 4, enum dpni_flc_type, cfg->flc_cfg.flc_type); \ ++ MC_CMD_OP(cmd, 3, 4, 4, enum dpni_stash_size, \ ++ cfg->flc_cfg.frame_data_size);\ ++ MC_CMD_OP(cmd, 3, 8, 4, enum dpni_stash_size, \ ++ cfg->flc_cfg.flow_context_size);\ ++ MC_CMD_OP(cmd, 3, 32, 32, uint32_t, cfg->flc_cfg.options);\ ++ MC_CMD_OP(cmd, 4, 0, 64, uint64_t, cfg->flc_cfg.flow_context);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_RX_ERR_QUEUE(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, attr->dest_cfg.dest_id); \ ++ MC_RSP_OP(cmd, 0, 32, 8, uint8_t, attr->dest_cfg.priority);\ ++ MC_RSP_OP(cmd, 0, 40, 2, enum dpni_dest, attr->dest_cfg.dest_type);\ ++ MC_RSP_OP(cmd, 0, 42, 1, int, attr->order_preservation_en);\ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, attr->user_ctx); \ ++ MC_RSP_OP(cmd, 2, 0, 32, uint32_t, attr->tail_drop_threshold); \ ++ MC_RSP_OP(cmd, 2, 32, 32, uint32_t, attr->fqid); \ ++ MC_RSP_OP(cmd, 3, 0, 4, enum dpni_flc_type, attr->flc_cfg.flc_type); \ ++ MC_RSP_OP(cmd, 3, 4, 4, enum dpni_stash_size, \ ++ attr->flc_cfg.frame_data_size);\ ++ MC_RSP_OP(cmd, 3, 8, 4, enum dpni_stash_size, \ ++ attr->flc_cfg.flow_context_size);\ ++ MC_RSP_OP(cmd, 3, 32, 32, uint32_t, attr->flc_cfg.options);\ ++ MC_RSP_OP(cmd, 4, 0, 64, uint64_t, attr->flc_cfg.flow_context);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_TX_CONF_REVOKE(cmd, revoke) \ ++ MC_CMD_OP(cmd, 0, 0, 1, int, revoke) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_QOS_TABLE(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->default_tc); \ ++ MC_CMD_OP(cmd, 0, 40, 1, int, cfg->discard_on_miss); \ ++ MC_CMD_OP(cmd, 6, 0, 64, uint64_t, cfg->key_cfg_iova); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_ADD_QOS_ENTRY(cmd, cfg, tc_id) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, tc_id); \ ++ MC_CMD_OP(cmd, 0, 24, 8, uint8_t, cfg->key_size); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->key_iova); \ ++ MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->mask_iova); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_REMOVE_QOS_ENTRY(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 24, 8, uint8_t, cfg->key_size); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->key_iova); \ ++ MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->mask_iova); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_ADD_FS_ENTRY(cmd, tc_id, cfg, flow_id) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, tc_id); \ ++ MC_CMD_OP(cmd, 0, 48, 16, uint16_t, flow_id); \ ++ MC_CMD_OP(cmd, 0, 24, 8, uint8_t, cfg->key_size); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->key_iova); \ ++ MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->mask_iova); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_REMOVE_FS_ENTRY(cmd, tc_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, tc_id); \ ++ MC_CMD_OP(cmd, 0, 24, 8, uint8_t, cfg->key_size); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->key_iova); \ ++ MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->mask_iova); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_CLEAR_FS_ENTRIES(cmd, tc_id) \ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, tc_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_VLAN_INSERTION(cmd, en) \ ++ MC_CMD_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_VLAN_REMOVAL(cmd, en) \ ++ MC_CMD_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_IPR(cmd, en) \ ++ MC_CMD_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_IPF(cmd, en) \ ++ MC_CMD_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_RX_TC_POLICING(cmd, tc_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 4, enum dpni_policer_mode, cfg->mode); \ ++ MC_CMD_OP(cmd, 0, 4, 4, enum dpni_policer_color, cfg->default_color); \ ++ MC_CMD_OP(cmd, 0, 8, 4, enum dpni_policer_unit, cfg->units); \ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, tc_id); \ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, cfg->options); \ ++ MC_CMD_OP(cmd, 1, 0, 32, uint32_t, cfg->cir); \ ++ MC_CMD_OP(cmd, 1, 32, 32, uint32_t, cfg->cbs); \ ++ MC_CMD_OP(cmd, 2, 0, 32, uint32_t, cfg->eir); \ ++ MC_CMD_OP(cmd, 2, 32, 32, uint32_t, cfg->ebs);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_GET_RX_TC_POLICING(cmd, tc_id) \ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, tc_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_RX_TC_POLICING(cmd, cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 4, enum dpni_policer_mode, cfg->mode); \ ++ MC_RSP_OP(cmd, 0, 4, 4, enum dpni_policer_color, cfg->default_color); \ ++ MC_RSP_OP(cmd, 0, 8, 4, enum dpni_policer_unit, cfg->units); \ ++ MC_RSP_OP(cmd, 0, 32, 32, uint32_t, cfg->options); \ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, cfg->cir); \ ++ MC_RSP_OP(cmd, 1, 32, 32, uint32_t, cfg->cbs); \ ++ MC_RSP_OP(cmd, 2, 0, 32, uint32_t, cfg->eir); \ ++ MC_RSP_OP(cmd, 2, 32, 32, uint32_t, cfg->ebs);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_PREP_EARLY_DROP(ext, cfg) \ ++do { \ ++ MC_PREP_OP(ext, 0, 0, 2, enum dpni_early_drop_mode, cfg->mode); \ ++ MC_PREP_OP(ext, 0, 2, 2, \ ++ enum dpni_congestion_unit, cfg->units); \ ++ MC_PREP_OP(ext, 0, 32, 32, uint32_t, cfg->tail_drop_threshold); \ ++ MC_PREP_OP(ext, 1, 0, 8, uint8_t, cfg->green.drop_probability); \ ++ MC_PREP_OP(ext, 2, 0, 64, uint64_t, cfg->green.max_threshold); \ ++ MC_PREP_OP(ext, 3, 0, 64, uint64_t, cfg->green.min_threshold); \ ++ MC_PREP_OP(ext, 5, 0, 8, uint8_t, cfg->yellow.drop_probability);\ ++ MC_PREP_OP(ext, 6, 0, 64, uint64_t, cfg->yellow.max_threshold); \ ++ MC_PREP_OP(ext, 7, 0, 64, uint64_t, cfg->yellow.min_threshold); \ ++ MC_PREP_OP(ext, 9, 0, 8, uint8_t, cfg->red.drop_probability); \ ++ MC_PREP_OP(ext, 10, 0, 64, uint64_t, cfg->red.max_threshold); \ ++ MC_PREP_OP(ext, 11, 0, 64, uint64_t, cfg->red.min_threshold); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_EXT_EARLY_DROP(ext, cfg) \ ++do { \ ++ MC_EXT_OP(ext, 0, 0, 2, enum dpni_early_drop_mode, cfg->mode); \ ++ MC_EXT_OP(ext, 0, 2, 2, \ ++ enum dpni_congestion_unit, cfg->units); \ ++ MC_EXT_OP(ext, 0, 32, 32, uint32_t, cfg->tail_drop_threshold); \ ++ MC_EXT_OP(ext, 1, 0, 8, uint8_t, cfg->green.drop_probability); \ ++ MC_EXT_OP(ext, 2, 0, 64, uint64_t, cfg->green.max_threshold); \ ++ MC_EXT_OP(ext, 3, 0, 64, uint64_t, cfg->green.min_threshold); \ ++ MC_EXT_OP(ext, 5, 0, 8, uint8_t, cfg->yellow.drop_probability);\ ++ MC_EXT_OP(ext, 6, 0, 64, uint64_t, cfg->yellow.max_threshold); \ ++ MC_EXT_OP(ext, 7, 0, 64, uint64_t, cfg->yellow.min_threshold); \ ++ MC_EXT_OP(ext, 9, 0, 8, uint8_t, cfg->red.drop_probability); \ ++ MC_EXT_OP(ext, 10, 0, 64, uint64_t, cfg->red.max_threshold); \ ++ MC_EXT_OP(ext, 11, 0, 64, uint64_t, cfg->red.min_threshold); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_RX_TC_EARLY_DROP(cmd, tc_id, early_drop_iova) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 8, 8, uint8_t, tc_id); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, early_drop_iova); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_GET_RX_TC_EARLY_DROP(cmd, tc_id, early_drop_iova) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 8, 8, uint8_t, tc_id); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, early_drop_iova); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_TX_TC_EARLY_DROP(cmd, tc_id, early_drop_iova) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 8, 8, uint8_t, tc_id); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, early_drop_iova); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_GET_TX_TC_EARLY_DROP(cmd, tc_id, early_drop_iova) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 8, 8, uint8_t, tc_id); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, early_drop_iova); \ ++} while (0) ++ ++#define DPNI_CMD_SET_RX_TC_CONGESTION_NOTIFICATION(cmd, tc_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 2, enum dpni_congestion_unit, cfg->units); \ ++ MC_CMD_OP(cmd, 0, 4, 4, enum dpni_dest, cfg->dest_cfg.dest_type); \ ++ MC_CMD_OP(cmd, 0, 8, 8, uint8_t, tc_id); \ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, cfg->dest_cfg.priority); \ ++ MC_CMD_OP(cmd, 1, 0, 32, uint32_t, cfg->threshold_entry); \ ++ MC_CMD_OP(cmd, 1, 32, 32, uint32_t, cfg->threshold_exit); \ ++ MC_CMD_OP(cmd, 2, 0, 16, uint16_t, cfg->options); \ ++ MC_CMD_OP(cmd, 2, 32, 32, int, cfg->dest_cfg.dest_id); \ ++ MC_CMD_OP(cmd, 3, 0, 64, uint64_t, cfg->message_ctx); \ ++ MC_CMD_OP(cmd, 4, 0, 64, uint64_t, cfg->message_iova); \ ++} while (0) ++ ++#define DPNI_CMD_GET_RX_TC_CONGESTION_NOTIFICATION(cmd, tc_id) \ ++ MC_CMD_OP(cmd, 0, 8, 8, uint8_t, tc_id) ++ ++#define DPNI_RSP_GET_RX_TC_CONGESTION_NOTIFICATION(cmd, cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 2, enum dpni_congestion_unit, cfg->units); \ ++ MC_RSP_OP(cmd, 0, 4, 4, enum dpni_dest, cfg->dest_cfg.dest_type); \ ++ MC_RSP_OP(cmd, 0, 16, 8, uint8_t, cfg->dest_cfg.priority); \ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, cfg->threshold_entry); \ ++ MC_RSP_OP(cmd, 1, 32, 32, uint32_t, cfg->threshold_exit); \ ++ MC_RSP_OP(cmd, 2, 0, 16, uint16_t, cfg->options); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, cfg->dest_cfg.dest_id); \ ++ MC_RSP_OP(cmd, 3, 0, 64, uint64_t, cfg->message_ctx); \ ++ MC_RSP_OP(cmd, 4, 0, 64, uint64_t, cfg->message_iova); \ ++} while (0) ++ ++#define DPNI_CMD_SET_TX_TC_CONGESTION_NOTIFICATION(cmd, tc_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 2, enum dpni_congestion_unit, cfg->units); \ ++ MC_CMD_OP(cmd, 0, 4, 4, enum dpni_dest, cfg->dest_cfg.dest_type); \ ++ MC_CMD_OP(cmd, 0, 8, 8, uint8_t, tc_id); \ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, cfg->dest_cfg.priority); \ ++ MC_CMD_OP(cmd, 1, 0, 32, uint32_t, cfg->threshold_entry); \ ++ MC_CMD_OP(cmd, 1, 32, 32, uint32_t, cfg->threshold_exit); \ ++ MC_CMD_OP(cmd, 2, 0, 16, uint16_t, cfg->options); \ ++ MC_CMD_OP(cmd, 2, 32, 32, int, cfg->dest_cfg.dest_id); \ ++ MC_CMD_OP(cmd, 3, 0, 64, uint64_t, cfg->message_ctx); \ ++ MC_CMD_OP(cmd, 4, 0, 64, uint64_t, cfg->message_iova); \ ++} while (0) ++ ++#define DPNI_CMD_GET_TX_TC_CONGESTION_NOTIFICATION(cmd, tc_id) \ ++ MC_CMD_OP(cmd, 0, 8, 8, uint8_t, tc_id) ++ ++#define DPNI_RSP_GET_TX_TC_CONGESTION_NOTIFICATION(cmd, cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 2, enum dpni_congestion_unit, cfg->units); \ ++ MC_RSP_OP(cmd, 0, 4, 4, enum dpni_dest, cfg->dest_cfg.dest_type); \ ++ MC_RSP_OP(cmd, 0, 16, 8, uint8_t, cfg->dest_cfg.priority); \ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, cfg->threshold_entry); \ ++ MC_RSP_OP(cmd, 1, 32, 32, uint32_t, cfg->threshold_exit); \ ++ MC_RSP_OP(cmd, 2, 0, 16, uint16_t, cfg->options); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, cfg->dest_cfg.dest_id); \ ++ MC_RSP_OP(cmd, 3, 0, 64, uint64_t, cfg->message_ctx); \ ++ MC_RSP_OP(cmd, 4, 0, 64, uint64_t, cfg->message_iova); \ ++} while (0) ++ ++#define DPNI_CMD_SET_TX_CONF(cmd, flow_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->queue_cfg.dest_cfg.priority); \ ++ MC_CMD_OP(cmd, 0, 40, 2, enum dpni_dest, \ ++ cfg->queue_cfg.dest_cfg.dest_type); \ ++ MC_CMD_OP(cmd, 0, 42, 1, int, cfg->errors_only); \ ++ MC_CMD_OP(cmd, 0, 46, 1, int, cfg->queue_cfg.order_preservation_en); \ ++ MC_CMD_OP(cmd, 0, 48, 16, uint16_t, flow_id); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->queue_cfg.user_ctx); \ ++ MC_CMD_OP(cmd, 2, 0, 32, uint32_t, cfg->queue_cfg.options); \ ++ MC_CMD_OP(cmd, 2, 32, 32, int, cfg->queue_cfg.dest_cfg.dest_id); \ ++ MC_CMD_OP(cmd, 3, 0, 32, uint32_t, \ ++ cfg->queue_cfg.tail_drop_threshold); \ ++ MC_CMD_OP(cmd, 4, 0, 4, enum dpni_flc_type, \ ++ cfg->queue_cfg.flc_cfg.flc_type); \ ++ MC_CMD_OP(cmd, 4, 4, 4, enum dpni_stash_size, \ ++ cfg->queue_cfg.flc_cfg.frame_data_size); \ ++ MC_CMD_OP(cmd, 4, 8, 4, enum dpni_stash_size, \ ++ cfg->queue_cfg.flc_cfg.flow_context_size); \ ++ MC_CMD_OP(cmd, 4, 32, 32, uint32_t, cfg->queue_cfg.flc_cfg.options); \ ++ MC_CMD_OP(cmd, 5, 0, 64, uint64_t, \ ++ cfg->queue_cfg.flc_cfg.flow_context); \ ++} while (0) ++ ++#define DPNI_CMD_GET_TX_CONF(cmd, flow_id) \ ++ MC_CMD_OP(cmd, 0, 48, 16, uint16_t, flow_id) ++ ++#define DPNI_RSP_GET_TX_CONF(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 32, 8, uint8_t, \ ++ attr->queue_attr.dest_cfg.priority); \ ++ MC_RSP_OP(cmd, 0, 40, 2, enum dpni_dest, \ ++ attr->queue_attr.dest_cfg.dest_type); \ ++ MC_RSP_OP(cmd, 0, 42, 1, int, attr->errors_only); \ ++ MC_RSP_OP(cmd, 0, 46, 1, int, \ ++ attr->queue_attr.order_preservation_en); \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, attr->queue_attr.user_ctx); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, attr->queue_attr.dest_cfg.dest_id); \ ++ MC_RSP_OP(cmd, 3, 0, 32, uint32_t, \ ++ attr->queue_attr.tail_drop_threshold); \ ++ MC_RSP_OP(cmd, 3, 32, 32, uint32_t, attr->queue_attr.fqid); \ ++ MC_RSP_OP(cmd, 4, 0, 4, enum dpni_flc_type, \ ++ attr->queue_attr.flc_cfg.flc_type); \ ++ MC_RSP_OP(cmd, 4, 4, 4, enum dpni_stash_size, \ ++ attr->queue_attr.flc_cfg.frame_data_size); \ ++ MC_RSP_OP(cmd, 4, 8, 4, enum dpni_stash_size, \ ++ attr->queue_attr.flc_cfg.flow_context_size); \ ++ MC_RSP_OP(cmd, 4, 32, 32, uint32_t, attr->queue_attr.flc_cfg.options); \ ++ MC_RSP_OP(cmd, 5, 0, 64, uint64_t, \ ++ attr->queue_attr.flc_cfg.flow_context); \ ++} while (0) ++ ++#define DPNI_CMD_SET_TX_CONF_CONGESTION_NOTIFICATION(cmd, flow_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 2, enum dpni_congestion_unit, cfg->units); \ ++ MC_CMD_OP(cmd, 0, 4, 4, enum dpni_dest, cfg->dest_cfg.dest_type); \ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, cfg->dest_cfg.priority); \ ++ MC_CMD_OP(cmd, 0, 48, 16, uint16_t, flow_id); \ ++ MC_CMD_OP(cmd, 1, 0, 32, uint32_t, cfg->threshold_entry); \ ++ MC_CMD_OP(cmd, 1, 32, 32, uint32_t, cfg->threshold_exit); \ ++ MC_CMD_OP(cmd, 2, 0, 16, uint16_t, cfg->options); \ ++ MC_CMD_OP(cmd, 2, 32, 32, int, cfg->dest_cfg.dest_id); \ ++ MC_CMD_OP(cmd, 3, 0, 64, uint64_t, cfg->message_ctx); \ ++ MC_CMD_OP(cmd, 4, 0, 64, uint64_t, cfg->message_iova); \ ++} while (0) ++ ++#define DPNI_CMD_GET_TX_CONF_CONGESTION_NOTIFICATION(cmd, flow_id) \ ++ MC_CMD_OP(cmd, 0, 48, 16, uint16_t, flow_id) ++ ++#define DPNI_RSP_GET_TX_CONF_CONGESTION_NOTIFICATION(cmd, cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 2, enum dpni_congestion_unit, cfg->units); \ ++ MC_RSP_OP(cmd, 0, 4, 4, enum dpni_dest, cfg->dest_cfg.dest_type); \ ++ MC_RSP_OP(cmd, 0, 16, 8, uint8_t, cfg->dest_cfg.priority); \ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, cfg->threshold_entry); \ ++ MC_RSP_OP(cmd, 1, 32, 32, uint32_t, cfg->threshold_exit); \ ++ MC_RSP_OP(cmd, 2, 0, 16, uint16_t, cfg->options); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, cfg->dest_cfg.dest_id); \ ++ MC_RSP_OP(cmd, 3, 0, 64, uint64_t, cfg->message_ctx); \ ++ MC_RSP_OP(cmd, 4, 0, 64, uint64_t, cfg->message_iova); \ ++} while (0) ++ ++#endif /* _FSL_DPNI_CMD_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dprc.h b/drivers/net/dpaa2/mc/fsl_dprc.h +new file mode 100644 +index 0000000..c831f46 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dprc.h +@@ -0,0 +1,1032 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_DPRC_H ++#define _FSL_DPRC_H ++ ++/* Data Path Resource Container API ++ * Contains DPRC API for managing and querying DPAA resources ++ */ ++ ++struct fsl_mc_io; ++ ++/** ++ * Set this value as the icid value in dprc_cfg structure when creating a ++ * container, in case the ICID is not selected by the user and should be ++ * allocated by the DPRC from the pool of ICIDs. ++ */ ++#define DPRC_GET_ICID_FROM_POOL (uint16_t)(~(0)) ++ ++/** ++ * Set this value as the portal_id value in dprc_cfg structure when creating a ++ * container, in case the portal ID is not specifically selected by the ++ * user and should be allocated by the DPRC from the pool of portal ids. ++ */ ++#define DPRC_GET_PORTAL_ID_FROM_POOL (int)(~(0)) ++ ++/** ++ * dprc_get_container_id() - Get container ID associated with a given portal. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @container_id: Requested container ID ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_get_container_id(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int *container_id); ++ ++/** ++ * dprc_open() - Open DPRC object for use ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @container_id: Container ID to open ++ * @token: Returned token of DPRC object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ * ++ * @warning Required before any operation on the object. ++ */ ++int dprc_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int container_id, ++ uint16_t *token); ++ ++/** ++ * dprc_close() - Close the control session of the object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * ++ * After this function is called, no further operations are ++ * allowed on the object without opening a new control session. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * Container general options ++ * ++ * These options may be selected at container creation by the container creator ++ * and can be retrieved using dprc_get_attributes() ++ */ ++ ++/** ++ * Spawn Policy Option allowed - Indicates that the new container is allowed ++ * to spawn and have its own child containers. ++ */ ++#define DPRC_CFG_OPT_SPAWN_ALLOWED 0x00000001 ++ ++/** ++ * General Container allocation policy - Indicates that the new container is ++ * allowed to allocate requested resources from its parent container; if not ++ * set, the container is only allowed to use resources in its own pools; Note ++ * that this is a container's global policy, but the parent container may ++ * override it and set specific quota per resource type. ++ */ ++#define DPRC_CFG_OPT_ALLOC_ALLOWED 0x00000002 ++ ++/** ++ * Object initialization allowed - software context associated with this ++ * container is allowed to invoke object initialization operations. ++ */ ++#define DPRC_CFG_OPT_OBJ_CREATE_ALLOWED 0x00000004 ++ ++/** ++ * Topology change allowed - software context associated with this ++ * container is allowed to invoke topology operations, such as attach/detach ++ * of network objects. ++ */ ++#define DPRC_CFG_OPT_TOPOLOGY_CHANGES_ALLOWED 0x00000008 ++ ++/** ++ * AIOP - Indicates that container belongs to AIOP. ++ */ ++#define DPRC_CFG_OPT_AIOP 0x00000020 ++ ++/** ++ * IRQ Config - Indicates that the container allowed to configure its IRQs. ++ */ ++#define DPRC_CFG_OPT_IRQ_CFG_ALLOWED 0x00000040 ++ ++/** ++ * struct dprc_cfg - Container configuration options ++ * @icid: Container's ICID; if set to 'DPRC_GET_ICID_FROM_POOL', a free ++ * ICID value is allocated by the DPRC ++ * @portal_id: Portal ID; if set to 'DPRC_GET_PORTAL_ID_FROM_POOL', a free ++ * portal ID is allocated by the DPRC ++ * @options: Combination of 'DPRC_CFG_OPT_' options ++ * @label: Object's label ++ */ ++struct dprc_cfg { ++ uint16_t icid; ++ int portal_id; ++ uint64_t options; ++ char label[16]; ++}; ++ ++/** ++ * dprc_create_container() - Create child container ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @cfg: Child container configuration ++ * @child_container_id: Returned child container ID ++ * @child_portal_offset: Returned child portal offset from MC portal base ++ * ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_create_container(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dprc_cfg *cfg, ++ int *child_container_id, ++ uint64_t *child_portal_offset); ++ ++/** ++ * dprc_destroy_container() - Destroy child container. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @child_container_id: ID of the container to destroy ++ * ++ * This function terminates the child container, so following this call the ++ * child container ID becomes invalid. ++ * ++ * Notes: ++ * - All resources and objects of the destroyed container are returned to the ++ * parent container or destroyed if were created be the destroyed container. ++ * - This function destroy all the child containers of the specified ++ * container prior to destroying the container itself. ++ * ++ * warning: Only the parent container is allowed to destroy a child policy ++ * Container 0 can't be destroyed ++ * ++ * Return: '0' on Success; Error code otherwise. ++ * ++ */ ++int dprc_destroy_container(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int child_container_id); ++ ++/** ++ * dprc_reset_container - Reset child container. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @child_container_id: ID of the container to reset ++ * ++ * In case a software context crashes or becomes non-responsive, the parent ++ * may wish to reset its resources container before the software context is ++ * restarted. ++ * ++ * This routine informs all objects assigned to the child container that the ++ * container is being reset, so they may perform any cleanup operations that are ++ * needed. All objects handles that were owned by the child container shall be ++ * closed. ++ * ++ * Note that such request may be submitted even if the child software context ++ * has not crashed, but the resulting object cleanup operations will not be ++ * aware of that. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_reset_container(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int child_container_id); ++ ++/** ++ * DPRC IRQ Index and Events ++ */ ++ ++/** ++ * IRQ index ++ */ ++#define DPRC_IRQ_INDEX 0 ++ ++/** ++ * Number of dprc's IRQs ++ */ ++#define DPRC_NUM_OF_IRQS 1 ++ ++/* DPRC IRQ events */ ++/** ++ * IRQ event - Indicates that a new object added to the container ++ */ ++#define DPRC_IRQ_EVENT_OBJ_ADDED 0x00000001 ++/** ++ * IRQ event - Indicates that an object was removed from the container ++ */ ++#define DPRC_IRQ_EVENT_OBJ_REMOVED 0x00000002 ++/** ++ * IRQ event - Indicates that resources added to the container ++ */ ++#define DPRC_IRQ_EVENT_RES_ADDED 0x00000004 ++/** ++ * IRQ event - Indicates that resources removed from the container ++ */ ++#define DPRC_IRQ_EVENT_RES_REMOVED 0x00000008 ++/** ++ * IRQ event - Indicates that one of the descendant containers that opened by ++ * this container is destroyed ++ */ ++#define DPRC_IRQ_EVENT_CONTAINER_DESTROYED 0x00000010 ++/** ++ * IRQ event - Indicates that on one of the container's opened object is ++ * destroyed ++ */ ++#define DPRC_IRQ_EVENT_OBJ_DESTROYED 0x00000020 ++/** ++ * Irq event - Indicates that object is created at the container ++ */ ++#define DPRC_IRQ_EVENT_OBJ_CREATED 0x00000040 ++ ++/** ++ * struct dprc_irq_cfg - IRQ configuration ++ * @addr: Address that must be written to signal a message-based interrupt ++ * @val: Value to write into irq_addr address ++ * @irq_num: A user defined number associated with this IRQ ++ */ ++struct dprc_irq_cfg { ++ uint64_t addr; ++ uint32_t val; ++ int irq_num; ++}; ++ ++/** ++ * dprc_set_irq() - Set IRQ information for the DPRC to trigger an interrupt. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @irq_index: Identifies the interrupt index to configure ++ * @irq_cfg: IRQ configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dprc_irq_cfg *irq_cfg); ++ ++/** ++ * dprc_get_irq() - Get IRQ information from the DPRC. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @irq_index: The interrupt index to configure ++ * @type: Interrupt type: 0 represents message interrupt ++ * type (both irq_addr and irq_val are valid) ++ * @irq_cfg: IRQ attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dprc_irq_cfg *irq_cfg); ++ ++/** ++ * dprc_set_irq_enable() - Set overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @irq_index: The interrupt index to configure ++ * @en: Interrupt state - enable = 1, disable = 0 ++ * ++ * Allows GPP software to control when interrupts are generated. ++ * Each interrupt can have up to 32 causes. The enable/disable control's the ++ * overall interrupt state. if the interrupt is disabled no causes will cause ++ * an interrupt. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en); ++ ++/** ++ * dprc_get_irq_enable() - Get overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @irq_index: The interrupt index to configure ++ * @en: Returned interrupt state - enable = 1, disable = 0 ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en); ++ ++/** ++ * dprc_set_irq_mask() - Set interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @irq_index: The interrupt index to configure ++ * @mask: event mask to trigger interrupt; ++ * each bit: ++ * 0 = ignore event ++ * 1 = consider event for asserting IRQ ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask); ++ ++/** ++ * dprc_get_irq_mask() - Get interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @irq_index: The interrupt index to configure ++ * @mask: Returned event mask to trigger interrupt ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask); ++ ++/** ++ * dprc_get_irq_status() - Get the current status of any pending interrupts. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @irq_index: The interrupt index to configure ++ * @status: Returned interrupts status - one bit per cause: ++ * 0 = no interrupt pending ++ * 1 = interrupt pending ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status); ++ ++/** ++ * dprc_clear_irq_status() - Clear a pending interrupt's status ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @irq_index: The interrupt index to configure ++ * @status: bits to clear (W1C) - one bit per cause: ++ * 0 = don't change ++ * 1 = clear status bit ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status); ++ ++/** ++ * struct dprc_attributes - Container attributes ++ * @container_id: Container's ID ++ * @icid: Container's ICID ++ * @portal_id: Container's portal ID ++ * @options: Container's options as set at container's creation ++ * @version: DPRC version ++ */ ++struct dprc_attributes { ++ int container_id; ++ uint16_t icid; ++ int portal_id; ++ uint64_t options; ++ /** ++ * struct version - DPRC version ++ * @major: DPRC major version ++ * @minor: DPRC minor version ++ */ ++ struct { ++ uint16_t major; ++ uint16_t minor; ++ } version; ++}; ++ ++/** ++ * dprc_get_attributes() - Obtains container attributes ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @attributes: Returned container attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dprc_attributes *attributes); ++ ++/** ++ * dprc_set_res_quota() - Set allocation policy for a specific resource/object ++ * type in a child container ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @child_container_id: ID of the child container ++ * @type: Resource/object type ++ * @quota: Sets the maximum number of resources of the selected type ++ * that the child container is allowed to allocate from its parent; ++ * when quota is set to -1, the policy is the same as container's ++ * general policy. ++ * ++ * Allocation policy determines whether or not a container may allocate ++ * resources from its parent. Each container has a 'global' allocation policy ++ * that is set when the container is created. ++ * ++ * This function sets allocation policy for a specific resource type. ++ * The default policy for all resource types matches the container's 'global' ++ * allocation policy. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ * ++ * @warning Only the parent container is allowed to change a child policy. ++ */ ++int dprc_set_res_quota(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int child_container_id, ++ char *type, ++ uint16_t quota); ++ ++/** ++ * dprc_get_res_quota() - Gets the allocation policy of a specific ++ * resource/object type in a child container ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @child_container_id: ID of the child container ++ * @type: resource/object type ++ * @quota: Returnes the maximum number of resources of the selected type ++ * that the child container is allowed to allocate from the parent; ++ * when quota is set to -1, the policy is the same as container's ++ * general policy. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_get_res_quota(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int child_container_id, ++ char *type, ++ uint16_t *quota); ++ ++/* Resource request options */ ++ ++/** ++ * Explicit resource ID request - The requested objects/resources ++ * are explicit and sequential (in case of resources). ++ * The base ID is given at res_req at base_align field ++ */ ++#define DPRC_RES_REQ_OPT_EXPLICIT 0x00000001 ++ ++/** ++ * Aligned resources request - Relevant only for resources ++ * request (and not objects). Indicates that resources base ID should be ++ * sequential and aligned to the value given at dprc_res_req base_align field ++ */ ++#define DPRC_RES_REQ_OPT_ALIGNED 0x00000002 ++ ++/** ++ * Plugged Flag - Relevant only for object assignment request. ++ * Indicates that after all objects assigned. An interrupt will be invoked at ++ * the relevant GPP. The assigned object will be marked as plugged. ++ * plugged objects can't be assigned from their container ++ */ ++#define DPRC_RES_REQ_OPT_PLUGGED 0x00000004 ++ ++/** ++ * struct dprc_res_req - Resource request descriptor, to be used in assignment ++ * or un-assignment of resources and objects. ++ * @type: Resource/object type: Represent as a NULL terminated string. ++ * This string may received by using dprc_get_pool() to get resource ++ * type and dprc_get_obj() to get object type; ++ * Note: it is not possible to assign/un-assign DPRC objects ++ * @num: Number of resources ++ * @options: Request options: combination of DPRC_RES_REQ_OPT_ options ++ * @id_base_align: In case of explicit assignment (DPRC_RES_REQ_OPT_EXPLICIT ++ * is set at option), this field represents the required base ID ++ * for resource allocation; In case of aligned assignment ++ * (DPRC_RES_REQ_OPT_ALIGNED is set at option), this field ++ * indicates the required alignment for the resource ID(s) - ++ * use 0 if there is no alignment or explicit ID requirements ++ */ ++struct dprc_res_req { ++ char type[16]; ++ uint32_t num; ++ uint32_t options; ++ int id_base_align; ++}; ++ ++/** ++ * dprc_assign() - Assigns objects or resource to a child container. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @container_id: ID of the child container ++ * @res_req: Describes the type and amount of resources to ++ * assign to the given container ++ * ++ * Assignment is usually done by a parent (this DPRC) to one of its child ++ * containers. ++ * ++ * According to the DPRC allocation policy, the assigned resources may be taken ++ * (allocated) from the container's ancestors, if not enough resources are ++ * available in the container itself. ++ * ++ * The type of assignment depends on the dprc_res_req options, as follows: ++ * - DPRC_RES_REQ_OPT_EXPLICIT: indicates that assigned resources should have ++ * the explicit base ID specified at the id_base_align field of res_req. ++ * - DPRC_RES_REQ_OPT_ALIGNED: indicates that the assigned resources should be ++ * aligned to the value given at id_base_align field of res_req. ++ * - DPRC_RES_REQ_OPT_PLUGGED: Relevant only for object assignment, ++ * and indicates that the object must be set to the plugged state. ++ * ++ * A container may use this function with its own ID in order to change a ++ * object state to plugged or unplugged. ++ * ++ * If IRQ information has been set in the child DPRC, it will signal an ++ * interrupt following every change in its object assignment. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_assign(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int container_id, ++ struct dprc_res_req *res_req); ++ ++/** ++ * dprc_unassign() - Un-assigns objects or resources from a child container ++ * and moves them into this (parent) DPRC. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @child_container_id: ID of the child container ++ * @res_req: Describes the type and amount of resources to un-assign from ++ * the child container ++ * ++ * Un-assignment of objects can succeed only if the object is not in the ++ * plugged or opened state. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_unassign(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int child_container_id, ++ struct dprc_res_req *res_req); ++ ++/** ++ * dprc_get_pool_count() - Get the number of dprc's pools ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @pool_count: Returned number of resource pools in the dprc ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_get_pool_count(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *pool_count); ++ ++/** ++ * dprc_get_pool() - Get the type (string) of a certain dprc's pool ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @pool_index: Index of the pool to be queried (< pool_count) ++ * @type: The type of the pool ++ * ++ * The pool types retrieved one by one by incrementing ++ * pool_index up to (not including) the value of pool_count returned ++ * from dprc_get_pool_count(). dprc_get_pool_count() must ++ * be called prior to dprc_get_pool(). ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_get_pool(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int pool_index, ++ char *type); ++ ++/** ++ * dprc_get_obj_count() - Obtains the number of objects in the DPRC ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @obj_count: Number of objects assigned to the DPRC ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_get_obj_count(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *obj_count); ++ ++/** ++ * Objects Attributes Flags ++ */ ++ ++/** ++ * Opened state - Indicates that an object is open by at least one owner ++ */ ++#define DPRC_OBJ_STATE_OPEN 0x00000001 ++/** ++ * Plugged state - Indicates that the object is plugged ++ */ ++#define DPRC_OBJ_STATE_PLUGGED 0x00000002 ++ ++/** ++ * Shareability flag - Object flag indicating no memory shareability. ++ * the object generates memory accesses that are non coherent with other ++ * masters; ++ * user is responsible for proper memory handling through IOMMU configuration. ++ */ ++#define DPRC_OBJ_FLAG_NO_MEM_SHAREABILITY 0x0001 ++ ++/** ++ * struct dprc_obj_desc - Object descriptor, returned from dprc_get_obj() ++ * @type: Type of object: NULL terminated string ++ * @id: ID of logical object resource ++ * @vendor: Object vendor identifier ++ * @ver_major: Major version number ++ * @ver_minor: Minor version number ++ * @irq_count: Number of interrupts supported by the object ++ * @region_count: Number of mappable regions supported by the object ++ * @state: Object state: combination of DPRC_OBJ_STATE_ states ++ * @label: Object label ++ * @flags: Object's flags ++ */ ++struct dprc_obj_desc { ++ char type[16]; ++ int id; ++ uint16_t vendor; ++ uint16_t ver_major; ++ uint16_t ver_minor; ++ uint8_t irq_count; ++ uint8_t region_count; ++ uint32_t state; ++ char label[16]; ++ uint16_t flags; ++}; ++ ++/** ++ * dprc_get_obj() - Get general information on an object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @obj_index: Index of the object to be queried (< obj_count) ++ * @obj_desc: Returns the requested object descriptor ++ * ++ * The object descriptors are retrieved one by one by incrementing ++ * obj_index up to (not including) the value of obj_count returned ++ * from dprc_get_obj_count(). dprc_get_obj_count() must ++ * be called prior to dprc_get_obj(). ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_get_obj(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int obj_index, ++ struct dprc_obj_desc *obj_desc); ++ ++/** ++ * dprc_get_obj_desc() - Get object descriptor. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @obj_type: The type of the object to get its descriptor. ++ * @obj_id: The id of the object to get its descriptor ++ * @obj_desc: The returned descriptor to fill and return to the user ++ * ++ * Return: '0' on Success; Error code otherwise. ++ * ++ */ ++int dprc_get_obj_desc(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ char *obj_type, ++ int obj_id, ++ struct dprc_obj_desc *obj_desc); ++ ++/** ++ * dprc_set_obj_irq() - Set IRQ information for object to trigger an interrupt. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @obj_type: Type of the object to set its IRQ ++ * @obj_id: ID of the object to set its IRQ ++ * @irq_index: The interrupt index to configure ++ * @irq_cfg: IRQ configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_set_obj_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ char *obj_type, ++ int obj_id, ++ uint8_t irq_index, ++ struct dprc_irq_cfg *irq_cfg); ++ ++/** ++ * dprc_get_obj_irq() - Get IRQ information from object. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @obj_type: Type od the object to get its IRQ ++ * @obj_id: ID of the object to get its IRQ ++ * @irq_index: The interrupt index to configure ++ * @type: Interrupt type: 0 represents message interrupt ++ * type (both irq_addr and irq_val are valid) ++ * @irq_cfg: The returned IRQ attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_get_obj_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ char *obj_type, ++ int obj_id, ++ uint8_t irq_index, ++ int *type, ++ struct dprc_irq_cfg *irq_cfg); ++ ++/** ++ * dprc_get_res_count() - Obtains the number of free resources that are ++ * assigned to this container, by pool type ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @type: pool type ++ * @res_count: Returned number of free resources of the given ++ * resource type that are assigned to this DPRC ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_get_res_count(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ char *type, ++ int *res_count); ++ ++/** ++ * enum dprc_iter_status - Iteration status ++ * @DPRC_ITER_STATUS_FIRST: Perform first iteration ++ * @DPRC_ITER_STATUS_MORE: Indicates more/next iteration is needed ++ * @DPRC_ITER_STATUS_LAST: Indicates last iteration ++ */ ++enum dprc_iter_status { ++ DPRC_ITER_STATUS_FIRST = 0, ++ DPRC_ITER_STATUS_MORE = 1, ++ DPRC_ITER_STATUS_LAST = 2 ++}; ++ ++/** ++ * struct dprc_res_ids_range_desc - Resource ID range descriptor ++ * @base_id: Base resource ID of this range ++ * @last_id: Last resource ID of this range ++ * @iter_status: Iteration status - should be set to DPRC_ITER_STATUS_FIRST at ++ * first iteration; while the returned marker is DPRC_ITER_STATUS_MORE, ++ * additional iterations are needed, until the returned marker is ++ * DPRC_ITER_STATUS_LAST ++ */ ++struct dprc_res_ids_range_desc { ++ int base_id; ++ int last_id; ++ enum dprc_iter_status iter_status; ++}; ++ ++/** ++ * dprc_get_res_ids() - Obtains IDs of free resources in the container ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @type: pool type ++ * @range_desc: range descriptor ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_get_res_ids(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ char *type, ++ struct dprc_res_ids_range_desc *range_desc); ++ ++/** ++ * Region flags ++ */ ++/** ++ * Cacheable - Indicates that region should be mapped as cacheable ++ */ ++#define DPRC_REGION_CACHEABLE 0x00000001 ++ ++/** ++ * enum dprc_region_type - Region type ++ * @DPRC_REGION_TYPE_MC_PORTAL: MC portal region ++ * @DPRC_REGION_TYPE_QBMAN_PORTAL: Qbman portal region ++ */ ++enum dprc_region_type { ++ DPRC_REGION_TYPE_MC_PORTAL, ++ DPRC_REGION_TYPE_QBMAN_PORTAL ++}; ++ ++/** ++ * struct dprc_region_desc - Mappable region descriptor ++ * @base_offset: Region offset from region's base address. ++ * For DPMCP and DPRC objects, region base is offset from SoC MC portals ++ * base address; For DPIO, region base is offset from SoC QMan portals ++ * base address ++ * @size: Region size (in bytes) ++ * @flags: Region attributes ++ * @type: Portal region type ++ */ ++struct dprc_region_desc { ++ uint32_t base_offset; ++ uint32_t size; ++ uint32_t flags; ++ enum dprc_region_type type; ++}; ++ ++/** ++ * dprc_get_obj_region() - Get region information for a specified object. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @obj_type: Object type as returned in dprc_get_obj() ++ * @obj_id: Unique object instance as returned in dprc_get_obj() ++ * @region_index: The specific region to query ++ * @region_desc: Returns the requested region descriptor ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_get_obj_region(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ char *obj_type, ++ int obj_id, ++ uint8_t region_index, ++ struct dprc_region_desc *region_desc); ++ ++/** ++ * dprc_set_obj_label() - Set object label. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @obj_type: Object's type ++ * @obj_id: Object's ID ++ * @label: The required label. The maximum length is 16 chars. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_set_obj_label(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ char *obj_type, ++ int obj_id, ++ char *label); ++ ++/** ++ * struct dprc_endpoint - Endpoint description for link connect/disconnect ++ * operations ++ * @type: Endpoint object type: NULL terminated string ++ * @id: Endpoint object ID ++ * @if_id: Interface ID; should be set for endpoints with multiple ++ * interfaces ("dpsw", "dpdmux"); for others, always set to 0 ++ */ ++struct dprc_endpoint { ++ char type[16]; ++ int id; ++ uint16_t if_id; ++}; ++ ++/** ++ * struct dprc_connection_cfg - Connection configuration. ++ * Used for virtual connections only ++ * @committed_rate: Committed rate (Mbits/s) ++ * @max_rate: Maximum rate (Mbits/s) ++ */ ++struct dprc_connection_cfg { ++ uint32_t committed_rate; ++ uint32_t max_rate; ++}; ++ ++/** ++ * dprc_connect() - Connect two endpoints to create a network link between them ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @endpoint1: Endpoint 1 configuration parameters ++ * @endpoint2: Endpoint 2 configuration parameters ++ * @cfg: Connection configuration. The connection configuration is ignored for ++ * connections made to DPMAC objects, where rate is retrieved from the ++ * MAC configuration. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_connect(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dprc_endpoint *endpoint1, ++ const struct dprc_endpoint *endpoint2, ++ const struct dprc_connection_cfg *cfg); ++ ++/** ++ * dprc_disconnect() - Disconnect one endpoint to remove its network connection ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @endpoint: Endpoint configuration parameters ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_disconnect(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dprc_endpoint *endpoint); ++ ++/** ++* dprc_get_connection() - Get connected endpoint and link status if connection ++* exists. ++* @mc_io: Pointer to MC portal's I/O object ++* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++* @token: Token of DPRC object ++* @endpoint1: Endpoint 1 configuration parameters ++* @endpoint2: Returned endpoint 2 configuration parameters ++* @state: Returned link state: ++* 1 - link is up; ++* 0 - link is down; ++* -1 - no connection (endpoint2 information is irrelevant) ++* ++* Return: '0' on Success; -ENAVAIL if connection does not exist. ++*/ ++int dprc_get_connection(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dprc_endpoint *endpoint1, ++ struct dprc_endpoint *endpoint2, ++ int *state); ++ ++#endif /* _FSL_DPRC_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dprc_cmd.h b/drivers/net/dpaa2/mc/fsl_dprc_cmd.h +new file mode 100644 +index 0000000..469e286 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dprc_cmd.h +@@ -0,0 +1,755 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_DPRC_CMD_H ++#define _FSL_DPRC_CMD_H ++ ++/* DPRC Version */ ++#define DPRC_VER_MAJOR 5 ++#define DPRC_VER_MINOR 1 ++ ++/* Command IDs */ ++#define DPRC_CMDID_CLOSE 0x800 ++#define DPRC_CMDID_OPEN 0x805 ++#define DPRC_CMDID_CREATE 0x905 ++ ++#define DPRC_CMDID_GET_ATTR 0x004 ++#define DPRC_CMDID_RESET_CONT 0x005 ++ ++#define DPRC_CMDID_SET_IRQ 0x010 ++#define DPRC_CMDID_GET_IRQ 0x011 ++#define DPRC_CMDID_SET_IRQ_ENABLE 0x012 ++#define DPRC_CMDID_GET_IRQ_ENABLE 0x013 ++#define DPRC_CMDID_SET_IRQ_MASK 0x014 ++#define DPRC_CMDID_GET_IRQ_MASK 0x015 ++#define DPRC_CMDID_GET_IRQ_STATUS 0x016 ++#define DPRC_CMDID_CLEAR_IRQ_STATUS 0x017 ++ ++#define DPRC_CMDID_CREATE_CONT 0x151 ++#define DPRC_CMDID_DESTROY_CONT 0x152 ++#define DPRC_CMDID_GET_CONT_ID 0x830 ++#define DPRC_CMDID_SET_RES_QUOTA 0x155 ++#define DPRC_CMDID_GET_RES_QUOTA 0x156 ++#define DPRC_CMDID_ASSIGN 0x157 ++#define DPRC_CMDID_UNASSIGN 0x158 ++#define DPRC_CMDID_GET_OBJ_COUNT 0x159 ++#define DPRC_CMDID_GET_OBJ 0x15A ++#define DPRC_CMDID_GET_RES_COUNT 0x15B ++#define DPRC_CMDID_GET_RES_IDS 0x15C ++#define DPRC_CMDID_GET_OBJ_REG 0x15E ++#define DPRC_CMDID_SET_OBJ_IRQ 0x15F ++#define DPRC_CMDID_GET_OBJ_IRQ 0x160 ++#define DPRC_CMDID_SET_OBJ_LABEL 0x161 ++#define DPRC_CMDID_GET_OBJ_DESC 0x162 ++ ++#define DPRC_CMDID_CONNECT 0x167 ++#define DPRC_CMDID_DISCONNECT 0x168 ++#define DPRC_CMDID_GET_POOL 0x169 ++#define DPRC_CMDID_GET_POOL_COUNT 0x16A ++ ++#define DPRC_CMDID_GET_CONNECTION 0x16C ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_RSP_GET_CONTAINER_ID(cmd, container_id) \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, container_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_OPEN(cmd, container_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, container_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_CREATE_CONTAINER(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 32, 16, uint16_t, cfg->icid); \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, cfg->options); \ ++ MC_CMD_OP(cmd, 1, 32, 32, int, cfg->portal_id); \ ++ MC_CMD_OP(cmd, 2, 0, 8, char, cfg->label[0]);\ ++ MC_CMD_OP(cmd, 2, 8, 8, char, cfg->label[1]);\ ++ MC_CMD_OP(cmd, 2, 16, 8, char, cfg->label[2]);\ ++ MC_CMD_OP(cmd, 2, 24, 8, char, cfg->label[3]);\ ++ MC_CMD_OP(cmd, 2, 32, 8, char, cfg->label[4]);\ ++ MC_CMD_OP(cmd, 2, 40, 8, char, cfg->label[5]);\ ++ MC_CMD_OP(cmd, 2, 48, 8, char, cfg->label[6]);\ ++ MC_CMD_OP(cmd, 2, 56, 8, char, cfg->label[7]);\ ++ MC_CMD_OP(cmd, 3, 0, 8, char, cfg->label[8]);\ ++ MC_CMD_OP(cmd, 3, 8, 8, char, cfg->label[9]);\ ++ MC_CMD_OP(cmd, 3, 16, 8, char, cfg->label[10]);\ ++ MC_CMD_OP(cmd, 3, 24, 8, char, cfg->label[11]);\ ++ MC_CMD_OP(cmd, 3, 32, 8, char, cfg->label[12]);\ ++ MC_CMD_OP(cmd, 3, 40, 8, char, cfg->label[13]);\ ++ MC_CMD_OP(cmd, 3, 48, 8, char, cfg->label[14]);\ ++ MC_CMD_OP(cmd, 3, 56, 8, char, cfg->label[15]);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_RSP_CREATE_CONTAINER(cmd, child_container_id, child_portal_offset)\ ++do { \ ++ MC_RSP_OP(cmd, 1, 0, 32, int, child_container_id); \ ++ MC_RSP_OP(cmd, 2, 0, 64, uint64_t, child_portal_offset);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_DESTROY_CONTAINER(cmd, child_container_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, child_container_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_RESET_CONTAINER(cmd, child_container_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, child_container_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index); \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\ ++ MC_CMD_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_GET_IRQ(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_RSP_GET_IRQ(cmd, type, irq_cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\ ++ MC_RSP_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, type); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_SET_IRQ_ENABLE(cmd, irq_index, en) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, en); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_GET_IRQ_ENABLE(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_RSP_GET_IRQ_ENABLE(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 8, uint8_t, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, mask); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_GET_IRQ_MASK(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_RSP_GET_IRQ_MASK(cmd, mask) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mask) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_RSP_GET_IRQ_STATUS(cmd, status) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, status) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_RSP_GET_ATTRIBUTES(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, attr->container_id); \ ++ MC_RSP_OP(cmd, 0, 32, 16, uint16_t, attr->icid); \ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, attr->options);\ ++ MC_RSP_OP(cmd, 1, 32, 32, int, attr->portal_id); \ ++ MC_RSP_OP(cmd, 2, 0, 16, uint16_t, attr->version.major);\ ++ MC_RSP_OP(cmd, 2, 16, 16, uint16_t, attr->version.minor);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_SET_RES_QUOTA(cmd, child_container_id, type, quota) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, child_container_id); \ ++ MC_CMD_OP(cmd, 0, 32, 16, uint16_t, quota);\ ++ MC_CMD_OP(cmd, 1, 0, 8, char, type[0]);\ ++ MC_CMD_OP(cmd, 1, 8, 8, char, type[1]);\ ++ MC_CMD_OP(cmd, 1, 16, 8, char, type[2]);\ ++ MC_CMD_OP(cmd, 1, 24, 8, char, type[3]);\ ++ MC_CMD_OP(cmd, 1, 32, 8, char, type[4]);\ ++ MC_CMD_OP(cmd, 1, 40, 8, char, type[5]);\ ++ MC_CMD_OP(cmd, 1, 48, 8, char, type[6]);\ ++ MC_CMD_OP(cmd, 1, 56, 8, char, type[7]);\ ++ MC_CMD_OP(cmd, 2, 0, 8, char, type[8]);\ ++ MC_CMD_OP(cmd, 2, 8, 8, char, type[9]);\ ++ MC_CMD_OP(cmd, 2, 16, 8, char, type[10]);\ ++ MC_CMD_OP(cmd, 2, 24, 8, char, type[11]);\ ++ MC_CMD_OP(cmd, 2, 32, 8, char, type[12]);\ ++ MC_CMD_OP(cmd, 2, 40, 8, char, type[13]);\ ++ MC_CMD_OP(cmd, 2, 48, 8, char, type[14]);\ ++ MC_CMD_OP(cmd, 2, 56, 8, char, type[15]);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_GET_RES_QUOTA(cmd, child_container_id, type) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, child_container_id); \ ++ MC_CMD_OP(cmd, 1, 0, 8, char, type[0]);\ ++ MC_CMD_OP(cmd, 1, 8, 8, char, type[1]);\ ++ MC_CMD_OP(cmd, 1, 16, 8, char, type[2]);\ ++ MC_CMD_OP(cmd, 1, 24, 8, char, type[3]);\ ++ MC_CMD_OP(cmd, 1, 32, 8, char, type[4]);\ ++ MC_CMD_OP(cmd, 1, 40, 8, char, type[5]);\ ++ MC_CMD_OP(cmd, 1, 48, 8, char, type[6]);\ ++ MC_CMD_OP(cmd, 1, 56, 8, char, type[7]);\ ++ MC_CMD_OP(cmd, 2, 0, 8, char, type[8]);\ ++ MC_CMD_OP(cmd, 2, 8, 8, char, type[9]);\ ++ MC_CMD_OP(cmd, 2, 16, 8, char, type[10]);\ ++ MC_CMD_OP(cmd, 2, 24, 8, char, type[11]);\ ++ MC_CMD_OP(cmd, 2, 32, 8, char, type[12]);\ ++ MC_CMD_OP(cmd, 2, 40, 8, char, type[13]);\ ++ MC_CMD_OP(cmd, 2, 48, 8, char, type[14]);\ ++ MC_CMD_OP(cmd, 2, 56, 8, char, type[15]);\ ++} while (0) ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_RSP_GET_RES_QUOTA(cmd, quota) \ ++ MC_RSP_OP(cmd, 0, 32, 16, uint16_t, quota) ++ ++/* param, offset, width, type, arg_name */ ++#define DPRC_CMD_ASSIGN(cmd, container_id, res_req) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, container_id); \ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, res_req->options);\ ++ MC_CMD_OP(cmd, 1, 0, 32, uint32_t, res_req->num); \ ++ MC_CMD_OP(cmd, 1, 32, 32, int, res_req->id_base_align); \ ++ MC_CMD_OP(cmd, 2, 0, 8, char, res_req->type[0]);\ ++ MC_CMD_OP(cmd, 2, 8, 8, char, res_req->type[1]);\ ++ MC_CMD_OP(cmd, 2, 16, 8, char, res_req->type[2]);\ ++ MC_CMD_OP(cmd, 2, 24, 8, char, res_req->type[3]);\ ++ MC_CMD_OP(cmd, 2, 32, 8, char, res_req->type[4]);\ ++ MC_CMD_OP(cmd, 2, 40, 8, char, res_req->type[5]);\ ++ MC_CMD_OP(cmd, 2, 48, 8, char, res_req->type[6]);\ ++ MC_CMD_OP(cmd, 2, 56, 8, char, res_req->type[7]);\ ++ MC_CMD_OP(cmd, 3, 0, 8, char, res_req->type[8]);\ ++ MC_CMD_OP(cmd, 3, 8, 8, char, res_req->type[9]);\ ++ MC_CMD_OP(cmd, 3, 16, 8, char, res_req->type[10]);\ ++ MC_CMD_OP(cmd, 3, 24, 8, char, res_req->type[11]);\ ++ MC_CMD_OP(cmd, 3, 32, 8, char, res_req->type[12]);\ ++ MC_CMD_OP(cmd, 3, 40, 8, char, res_req->type[13]);\ ++ MC_CMD_OP(cmd, 3, 48, 8, char, res_req->type[14]);\ ++ MC_CMD_OP(cmd, 3, 56, 8, char, res_req->type[15]);\ ++} while (0) ++ ++/* param, offset, width, type, arg_name */ ++#define DPRC_CMD_UNASSIGN(cmd, child_container_id, res_req) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, child_container_id); \ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, res_req->options);\ ++ MC_CMD_OP(cmd, 1, 0, 32, uint32_t, res_req->num); \ ++ MC_CMD_OP(cmd, 1, 32, 32, int, res_req->id_base_align); \ ++ MC_CMD_OP(cmd, 2, 0, 8, char, res_req->type[0]);\ ++ MC_CMD_OP(cmd, 2, 8, 8, char, res_req->type[1]);\ ++ MC_CMD_OP(cmd, 2, 16, 8, char, res_req->type[2]);\ ++ MC_CMD_OP(cmd, 2, 24, 8, char, res_req->type[3]);\ ++ MC_CMD_OP(cmd, 2, 32, 8, char, res_req->type[4]);\ ++ MC_CMD_OP(cmd, 2, 40, 8, char, res_req->type[5]);\ ++ MC_CMD_OP(cmd, 2, 48, 8, char, res_req->type[6]);\ ++ MC_CMD_OP(cmd, 2, 56, 8, char, res_req->type[7]);\ ++ MC_CMD_OP(cmd, 3, 0, 8, char, res_req->type[8]);\ ++ MC_CMD_OP(cmd, 3, 8, 8, char, res_req->type[9]);\ ++ MC_CMD_OP(cmd, 3, 16, 8, char, res_req->type[10]);\ ++ MC_CMD_OP(cmd, 3, 24, 8, char, res_req->type[11]);\ ++ MC_CMD_OP(cmd, 3, 32, 8, char, res_req->type[12]);\ ++ MC_CMD_OP(cmd, 3, 40, 8, char, res_req->type[13]);\ ++ MC_CMD_OP(cmd, 3, 48, 8, char, res_req->type[14]);\ ++ MC_CMD_OP(cmd, 3, 56, 8, char, res_req->type[15]);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_RSP_GET_POOL_COUNT(cmd, pool_count) \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, pool_count) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_GET_POOL(cmd, pool_index) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, pool_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_RSP_GET_POOL(cmd, type) \ ++do { \ ++ MC_RSP_OP(cmd, 1, 0, 8, char, type[0]);\ ++ MC_RSP_OP(cmd, 1, 8, 8, char, type[1]);\ ++ MC_RSP_OP(cmd, 1, 16, 8, char, type[2]);\ ++ MC_RSP_OP(cmd, 1, 24, 8, char, type[3]);\ ++ MC_RSP_OP(cmd, 1, 32, 8, char, type[4]);\ ++ MC_RSP_OP(cmd, 1, 40, 8, char, type[5]);\ ++ MC_RSP_OP(cmd, 1, 48, 8, char, type[6]);\ ++ MC_RSP_OP(cmd, 1, 56, 8, char, type[7]);\ ++ MC_RSP_OP(cmd, 2, 0, 8, char, type[8]);\ ++ MC_RSP_OP(cmd, 2, 8, 8, char, type[9]);\ ++ MC_RSP_OP(cmd, 2, 16, 8, char, type[10]);\ ++ MC_RSP_OP(cmd, 2, 24, 8, char, type[11]);\ ++ MC_RSP_OP(cmd, 2, 32, 8, char, type[12]);\ ++ MC_RSP_OP(cmd, 2, 40, 8, char, type[13]);\ ++ MC_RSP_OP(cmd, 2, 48, 8, char, type[14]);\ ++ MC_RSP_OP(cmd, 2, 56, 8, char, type[15]);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_RSP_GET_OBJ_COUNT(cmd, obj_count) \ ++ MC_RSP_OP(cmd, 0, 32, 32, int, obj_count) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_GET_OBJ(cmd, obj_index) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, obj_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_RSP_GET_OBJ(cmd, obj_desc) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 32, 32, int, obj_desc->id); \ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, obj_desc->vendor); \ ++ MC_RSP_OP(cmd, 1, 16, 8, uint8_t, obj_desc->irq_count); \ ++ MC_RSP_OP(cmd, 1, 24, 8, uint8_t, obj_desc->region_count); \ ++ MC_RSP_OP(cmd, 1, 32, 32, uint32_t, obj_desc->state);\ ++ MC_RSP_OP(cmd, 2, 0, 16, uint16_t, obj_desc->ver_major);\ ++ MC_RSP_OP(cmd, 2, 16, 16, uint16_t, obj_desc->ver_minor);\ ++ MC_RSP_OP(cmd, 2, 32, 16, uint16_t, obj_desc->flags); \ ++ MC_RSP_OP(cmd, 3, 0, 8, char, obj_desc->type[0]);\ ++ MC_RSP_OP(cmd, 3, 8, 8, char, obj_desc->type[1]);\ ++ MC_RSP_OP(cmd, 3, 16, 8, char, obj_desc->type[2]);\ ++ MC_RSP_OP(cmd, 3, 24, 8, char, obj_desc->type[3]);\ ++ MC_RSP_OP(cmd, 3, 32, 8, char, obj_desc->type[4]);\ ++ MC_RSP_OP(cmd, 3, 40, 8, char, obj_desc->type[5]);\ ++ MC_RSP_OP(cmd, 3, 48, 8, char, obj_desc->type[6]);\ ++ MC_RSP_OP(cmd, 3, 56, 8, char, obj_desc->type[7]);\ ++ MC_RSP_OP(cmd, 4, 0, 8, char, obj_desc->type[8]);\ ++ MC_RSP_OP(cmd, 4, 8, 8, char, obj_desc->type[9]);\ ++ MC_RSP_OP(cmd, 4, 16, 8, char, obj_desc->type[10]);\ ++ MC_RSP_OP(cmd, 4, 24, 8, char, obj_desc->type[11]);\ ++ MC_RSP_OP(cmd, 4, 32, 8, char, obj_desc->type[12]);\ ++ MC_RSP_OP(cmd, 4, 40, 8, char, obj_desc->type[13]);\ ++ MC_RSP_OP(cmd, 4, 48, 8, char, obj_desc->type[14]);\ ++ MC_RSP_OP(cmd, 4, 56, 8, char, obj_desc->type[15]);\ ++ MC_RSP_OP(cmd, 5, 0, 8, char, obj_desc->label[0]);\ ++ MC_RSP_OP(cmd, 5, 8, 8, char, obj_desc->label[1]);\ ++ MC_RSP_OP(cmd, 5, 16, 8, char, obj_desc->label[2]);\ ++ MC_RSP_OP(cmd, 5, 24, 8, char, obj_desc->label[3]);\ ++ MC_RSP_OP(cmd, 5, 32, 8, char, obj_desc->label[4]);\ ++ MC_RSP_OP(cmd, 5, 40, 8, char, obj_desc->label[5]);\ ++ MC_RSP_OP(cmd, 5, 48, 8, char, obj_desc->label[6]);\ ++ MC_RSP_OP(cmd, 5, 56, 8, char, obj_desc->label[7]);\ ++ MC_RSP_OP(cmd, 6, 0, 8, char, obj_desc->label[8]);\ ++ MC_RSP_OP(cmd, 6, 8, 8, char, obj_desc->label[9]);\ ++ MC_RSP_OP(cmd, 6, 16, 8, char, obj_desc->label[10]);\ ++ MC_RSP_OP(cmd, 6, 24, 8, char, obj_desc->label[11]);\ ++ MC_RSP_OP(cmd, 6, 32, 8, char, obj_desc->label[12]);\ ++ MC_RSP_OP(cmd, 6, 40, 8, char, obj_desc->label[13]);\ ++ MC_RSP_OP(cmd, 6, 48, 8, char, obj_desc->label[14]);\ ++ MC_RSP_OP(cmd, 6, 56, 8, char, obj_desc->label[15]);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_GET_OBJ_DESC(cmd, obj_type, obj_id) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, obj_id);\ ++ MC_CMD_OP(cmd, 1, 0, 8, char, obj_type[0]);\ ++ MC_CMD_OP(cmd, 1, 8, 8, char, obj_type[1]);\ ++ MC_CMD_OP(cmd, 1, 16, 8, char, obj_type[2]);\ ++ MC_CMD_OP(cmd, 1, 24, 8, char, obj_type[3]);\ ++ MC_CMD_OP(cmd, 1, 32, 8, char, obj_type[4]);\ ++ MC_CMD_OP(cmd, 1, 40, 8, char, obj_type[5]);\ ++ MC_CMD_OP(cmd, 1, 48, 8, char, obj_type[6]);\ ++ MC_CMD_OP(cmd, 1, 56, 8, char, obj_type[7]);\ ++ MC_CMD_OP(cmd, 2, 0, 8, char, obj_type[8]);\ ++ MC_CMD_OP(cmd, 2, 8, 8, char, obj_type[9]);\ ++ MC_CMD_OP(cmd, 2, 16, 8, char, obj_type[10]);\ ++ MC_CMD_OP(cmd, 2, 24, 8, char, obj_type[11]);\ ++ MC_CMD_OP(cmd, 2, 32, 8, char, obj_type[12]);\ ++ MC_CMD_OP(cmd, 2, 40, 8, char, obj_type[13]);\ ++ MC_CMD_OP(cmd, 2, 48, 8, char, obj_type[14]);\ ++ MC_CMD_OP(cmd, 2, 56, 8, char, obj_type[15]);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_RSP_GET_OBJ_DESC(cmd, obj_desc) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 32, 32, int, obj_desc->id); \ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, obj_desc->vendor); \ ++ MC_RSP_OP(cmd, 1, 16, 8, uint8_t, obj_desc->irq_count); \ ++ MC_RSP_OP(cmd, 1, 24, 8, uint8_t, obj_desc->region_count); \ ++ MC_RSP_OP(cmd, 1, 32, 32, uint32_t, obj_desc->state);\ ++ MC_RSP_OP(cmd, 2, 0, 16, uint16_t, obj_desc->ver_major);\ ++ MC_RSP_OP(cmd, 2, 16, 16, uint16_t, obj_desc->ver_minor);\ ++ MC_RSP_OP(cmd, 2, 32, 16, uint16_t, obj_desc->flags); \ ++ MC_RSP_OP(cmd, 3, 0, 8, char, obj_desc->type[0]);\ ++ MC_RSP_OP(cmd, 3, 8, 8, char, obj_desc->type[1]);\ ++ MC_RSP_OP(cmd, 3, 16, 8, char, obj_desc->type[2]);\ ++ MC_RSP_OP(cmd, 3, 24, 8, char, obj_desc->type[3]);\ ++ MC_RSP_OP(cmd, 3, 32, 8, char, obj_desc->type[4]);\ ++ MC_RSP_OP(cmd, 3, 40, 8, char, obj_desc->type[5]);\ ++ MC_RSP_OP(cmd, 3, 48, 8, char, obj_desc->type[6]);\ ++ MC_RSP_OP(cmd, 3, 56, 8, char, obj_desc->type[7]);\ ++ MC_RSP_OP(cmd, 4, 0, 8, char, obj_desc->type[8]);\ ++ MC_RSP_OP(cmd, 4, 8, 8, char, obj_desc->type[9]);\ ++ MC_RSP_OP(cmd, 4, 16, 8, char, obj_desc->type[10]);\ ++ MC_RSP_OP(cmd, 4, 24, 8, char, obj_desc->type[11]);\ ++ MC_RSP_OP(cmd, 4, 32, 8, char, obj_desc->type[12]);\ ++ MC_RSP_OP(cmd, 4, 40, 8, char, obj_desc->type[13]);\ ++ MC_RSP_OP(cmd, 4, 48, 8, char, obj_desc->type[14]);\ ++ MC_RSP_OP(cmd, 4, 56, 8, char, obj_desc->type[15]);\ ++ MC_RSP_OP(cmd, 5, 0, 8, char, obj_desc->label[0]);\ ++ MC_RSP_OP(cmd, 5, 8, 8, char, obj_desc->label[1]);\ ++ MC_RSP_OP(cmd, 5, 16, 8, char, obj_desc->label[2]);\ ++ MC_RSP_OP(cmd, 5, 24, 8, char, obj_desc->label[3]);\ ++ MC_RSP_OP(cmd, 5, 32, 8, char, obj_desc->label[4]);\ ++ MC_RSP_OP(cmd, 5, 40, 8, char, obj_desc->label[5]);\ ++ MC_RSP_OP(cmd, 5, 48, 8, char, obj_desc->label[6]);\ ++ MC_RSP_OP(cmd, 5, 56, 8, char, obj_desc->label[7]);\ ++ MC_RSP_OP(cmd, 6, 0, 8, char, obj_desc->label[8]);\ ++ MC_RSP_OP(cmd, 6, 8, 8, char, obj_desc->label[9]);\ ++ MC_RSP_OP(cmd, 6, 16, 8, char, obj_desc->label[10]);\ ++ MC_RSP_OP(cmd, 6, 24, 8, char, obj_desc->label[11]);\ ++ MC_RSP_OP(cmd, 6, 32, 8, char, obj_desc->label[12]);\ ++ MC_RSP_OP(cmd, 6, 40, 8, char, obj_desc->label[13]);\ ++ MC_RSP_OP(cmd, 6, 48, 8, char, obj_desc->label[14]);\ ++ MC_RSP_OP(cmd, 6, 56, 8, char, obj_desc->label[15]);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_GET_RES_COUNT(cmd, type) \ ++do { \ ++ MC_CMD_OP(cmd, 1, 0, 8, char, type[0]);\ ++ MC_CMD_OP(cmd, 1, 8, 8, char, type[1]);\ ++ MC_CMD_OP(cmd, 1, 16, 8, char, type[2]);\ ++ MC_CMD_OP(cmd, 1, 24, 8, char, type[3]);\ ++ MC_CMD_OP(cmd, 1, 32, 8, char, type[4]);\ ++ MC_CMD_OP(cmd, 1, 40, 8, char, type[5]);\ ++ MC_CMD_OP(cmd, 1, 48, 8, char, type[6]);\ ++ MC_CMD_OP(cmd, 1, 56, 8, char, type[7]);\ ++ MC_CMD_OP(cmd, 2, 0, 8, char, type[8]);\ ++ MC_CMD_OP(cmd, 2, 8, 8, char, type[9]);\ ++ MC_CMD_OP(cmd, 2, 16, 8, char, type[10]);\ ++ MC_CMD_OP(cmd, 2, 24, 8, char, type[11]);\ ++ MC_CMD_OP(cmd, 2, 32, 8, char, type[12]);\ ++ MC_CMD_OP(cmd, 2, 40, 8, char, type[13]);\ ++ MC_CMD_OP(cmd, 2, 48, 8, char, type[14]);\ ++ MC_CMD_OP(cmd, 2, 56, 8, char, type[15]);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_RSP_GET_RES_COUNT(cmd, res_count) \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, res_count) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_GET_RES_IDS(cmd, range_desc, type) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 42, 7, enum dprc_iter_status, \ ++ range_desc->iter_status); \ ++ MC_CMD_OP(cmd, 1, 0, 32, int, range_desc->base_id); \ ++ MC_CMD_OP(cmd, 1, 32, 32, int, range_desc->last_id);\ ++ MC_CMD_OP(cmd, 2, 0, 8, char, type[0]);\ ++ MC_CMD_OP(cmd, 2, 8, 8, char, type[1]);\ ++ MC_CMD_OP(cmd, 2, 16, 8, char, type[2]);\ ++ MC_CMD_OP(cmd, 2, 24, 8, char, type[3]);\ ++ MC_CMD_OP(cmd, 2, 32, 8, char, type[4]);\ ++ MC_CMD_OP(cmd, 2, 40, 8, char, type[5]);\ ++ MC_CMD_OP(cmd, 2, 48, 8, char, type[6]);\ ++ MC_CMD_OP(cmd, 2, 56, 8, char, type[7]);\ ++ MC_CMD_OP(cmd, 3, 0, 8, char, type[8]);\ ++ MC_CMD_OP(cmd, 3, 8, 8, char, type[9]);\ ++ MC_CMD_OP(cmd, 3, 16, 8, char, type[10]);\ ++ MC_CMD_OP(cmd, 3, 24, 8, char, type[11]);\ ++ MC_CMD_OP(cmd, 3, 32, 8, char, type[12]);\ ++ MC_CMD_OP(cmd, 3, 40, 8, char, type[13]);\ ++ MC_CMD_OP(cmd, 3, 48, 8, char, type[14]);\ ++ MC_CMD_OP(cmd, 3, 56, 8, char, type[15]);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_RSP_GET_RES_IDS(cmd, range_desc) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 42, 7, enum dprc_iter_status, \ ++ range_desc->iter_status);\ ++ MC_RSP_OP(cmd, 1, 0, 32, int, range_desc->base_id); \ ++ MC_RSP_OP(cmd, 1, 32, 32, int, range_desc->last_id);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_GET_OBJ_REGION(cmd, obj_type, obj_id, region_index) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, obj_id); \ ++ MC_CMD_OP(cmd, 0, 48, 8, uint8_t, region_index);\ ++ MC_CMD_OP(cmd, 3, 0, 8, char, obj_type[0]);\ ++ MC_CMD_OP(cmd, 3, 8, 8, char, obj_type[1]);\ ++ MC_CMD_OP(cmd, 3, 16, 8, char, obj_type[2]);\ ++ MC_CMD_OP(cmd, 3, 24, 8, char, obj_type[3]);\ ++ MC_CMD_OP(cmd, 3, 32, 8, char, obj_type[4]);\ ++ MC_CMD_OP(cmd, 3, 40, 8, char, obj_type[5]);\ ++ MC_CMD_OP(cmd, 3, 48, 8, char, obj_type[6]);\ ++ MC_CMD_OP(cmd, 3, 56, 8, char, obj_type[7]);\ ++ MC_CMD_OP(cmd, 4, 0, 8, char, obj_type[8]);\ ++ MC_CMD_OP(cmd, 4, 8, 8, char, obj_type[9]);\ ++ MC_CMD_OP(cmd, 4, 16, 8, char, obj_type[10]);\ ++ MC_CMD_OP(cmd, 4, 24, 8, char, obj_type[11]);\ ++ MC_CMD_OP(cmd, 4, 32, 8, char, obj_type[12]);\ ++ MC_CMD_OP(cmd, 4, 40, 8, char, obj_type[13]);\ ++ MC_CMD_OP(cmd, 4, 48, 8, char, obj_type[14]);\ ++ MC_CMD_OP(cmd, 4, 56, 8, char, obj_type[15]);\ ++} while (0) ++ ++/* param, offset, width, type, arg_name */ ++#define DPRC_RSP_GET_OBJ_REGION(cmd, region_desc) \ ++do { \ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, region_desc->base_offset);\ ++ MC_RSP_OP(cmd, 2, 0, 32, uint32_t, region_desc->size); \ ++ MC_RSP_OP(cmd, 2, 32, 4, enum dprc_region_type, region_desc->type);\ ++ MC_RSP_OP(cmd, 3, 0, 32, uint32_t, region_desc->flags);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_SET_OBJ_LABEL(cmd, obj_type, obj_id, label) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, obj_id); \ ++ MC_CMD_OP(cmd, 1, 0, 8, char, label[0]);\ ++ MC_CMD_OP(cmd, 1, 8, 8, char, label[1]);\ ++ MC_CMD_OP(cmd, 1, 16, 8, char, label[2]);\ ++ MC_CMD_OP(cmd, 1, 24, 8, char, label[3]);\ ++ MC_CMD_OP(cmd, 1, 32, 8, char, label[4]);\ ++ MC_CMD_OP(cmd, 1, 40, 8, char, label[5]);\ ++ MC_CMD_OP(cmd, 1, 48, 8, char, label[6]);\ ++ MC_CMD_OP(cmd, 1, 56, 8, char, label[7]);\ ++ MC_CMD_OP(cmd, 2, 0, 8, char, label[8]);\ ++ MC_CMD_OP(cmd, 2, 8, 8, char, label[9]);\ ++ MC_CMD_OP(cmd, 2, 16, 8, char, label[10]);\ ++ MC_CMD_OP(cmd, 2, 24, 8, char, label[11]);\ ++ MC_CMD_OP(cmd, 2, 32, 8, char, label[12]);\ ++ MC_CMD_OP(cmd, 2, 40, 8, char, label[13]);\ ++ MC_CMD_OP(cmd, 2, 48, 8, char, label[14]);\ ++ MC_CMD_OP(cmd, 2, 56, 8, char, label[15]);\ ++ MC_CMD_OP(cmd, 3, 0, 8, char, obj_type[0]);\ ++ MC_CMD_OP(cmd, 3, 8, 8, char, obj_type[1]);\ ++ MC_CMD_OP(cmd, 3, 16, 8, char, obj_type[2]);\ ++ MC_CMD_OP(cmd, 3, 24, 8, char, obj_type[3]);\ ++ MC_CMD_OP(cmd, 3, 32, 8, char, obj_type[4]);\ ++ MC_CMD_OP(cmd, 3, 40, 8, char, obj_type[5]);\ ++ MC_CMD_OP(cmd, 3, 48, 8, char, obj_type[6]);\ ++ MC_CMD_OP(cmd, 3, 56, 8, char, obj_type[7]);\ ++ MC_CMD_OP(cmd, 4, 0, 8, char, obj_type[8]);\ ++ MC_CMD_OP(cmd, 4, 8, 8, char, obj_type[9]);\ ++ MC_CMD_OP(cmd, 4, 16, 8, char, obj_type[10]);\ ++ MC_CMD_OP(cmd, 4, 24, 8, char, obj_type[11]);\ ++ MC_CMD_OP(cmd, 4, 32, 8, char, obj_type[12]);\ ++ MC_CMD_OP(cmd, 4, 40, 8, char, obj_type[13]);\ ++ MC_CMD_OP(cmd, 4, 48, 8, char, obj_type[14]);\ ++ MC_CMD_OP(cmd, 4, 56, 8, char, obj_type[15]);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_SET_OBJ_IRQ(cmd, obj_type, obj_id, irq_index, irq_cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index); \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\ ++ MC_CMD_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++ MC_CMD_OP(cmd, 2, 32, 32, int, obj_id); \ ++ MC_CMD_OP(cmd, 3, 0, 8, char, obj_type[0]);\ ++ MC_CMD_OP(cmd, 3, 8, 8, char, obj_type[1]);\ ++ MC_CMD_OP(cmd, 3, 16, 8, char, obj_type[2]);\ ++ MC_CMD_OP(cmd, 3, 24, 8, char, obj_type[3]);\ ++ MC_CMD_OP(cmd, 3, 32, 8, char, obj_type[4]);\ ++ MC_CMD_OP(cmd, 3, 40, 8, char, obj_type[5]);\ ++ MC_CMD_OP(cmd, 3, 48, 8, char, obj_type[6]);\ ++ MC_CMD_OP(cmd, 3, 56, 8, char, obj_type[7]);\ ++ MC_CMD_OP(cmd, 4, 0, 8, char, obj_type[8]);\ ++ MC_CMD_OP(cmd, 4, 8, 8, char, obj_type[9]);\ ++ MC_CMD_OP(cmd, 4, 16, 8, char, obj_type[10]);\ ++ MC_CMD_OP(cmd, 4, 24, 8, char, obj_type[11]);\ ++ MC_CMD_OP(cmd, 4, 32, 8, char, obj_type[12]);\ ++ MC_CMD_OP(cmd, 4, 40, 8, char, obj_type[13]);\ ++ MC_CMD_OP(cmd, 4, 48, 8, char, obj_type[14]);\ ++ MC_CMD_OP(cmd, 4, 56, 8, char, obj_type[15]);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_GET_OBJ_IRQ(cmd, obj_type, obj_id, irq_index) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, obj_id); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index); \ ++ MC_CMD_OP(cmd, 1, 0, 8, char, obj_type[0]);\ ++ MC_CMD_OP(cmd, 1, 8, 8, char, obj_type[1]);\ ++ MC_CMD_OP(cmd, 1, 16, 8, char, obj_type[2]);\ ++ MC_CMD_OP(cmd, 1, 24, 8, char, obj_type[3]);\ ++ MC_CMD_OP(cmd, 1, 32, 8, char, obj_type[4]);\ ++ MC_CMD_OP(cmd, 1, 40, 8, char, obj_type[5]);\ ++ MC_CMD_OP(cmd, 1, 48, 8, char, obj_type[6]);\ ++ MC_CMD_OP(cmd, 1, 56, 8, char, obj_type[7]);\ ++ MC_CMD_OP(cmd, 2, 0, 8, char, obj_type[8]);\ ++ MC_CMD_OP(cmd, 2, 8, 8, char, obj_type[9]);\ ++ MC_CMD_OP(cmd, 2, 16, 8, char, obj_type[10]);\ ++ MC_CMD_OP(cmd, 2, 24, 8, char, obj_type[11]);\ ++ MC_CMD_OP(cmd, 2, 32, 8, char, obj_type[12]);\ ++ MC_CMD_OP(cmd, 2, 40, 8, char, obj_type[13]);\ ++ MC_CMD_OP(cmd, 2, 48, 8, char, obj_type[14]);\ ++ MC_CMD_OP(cmd, 2, 56, 8, char, obj_type[15]);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_RSP_GET_OBJ_IRQ(cmd, type, irq_cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\ ++ MC_RSP_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, type); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_CONNECT(cmd, endpoint1, endpoint2, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, endpoint1->id); \ ++ MC_CMD_OP(cmd, 0, 32, 16, uint16_t, endpoint1->if_id); \ ++ MC_CMD_OP(cmd, 1, 0, 32, int, endpoint2->id); \ ++ MC_CMD_OP(cmd, 1, 32, 16, uint16_t, endpoint2->if_id); \ ++ MC_CMD_OP(cmd, 2, 0, 8, char, endpoint1->type[0]); \ ++ MC_CMD_OP(cmd, 2, 8, 8, char, endpoint1->type[1]); \ ++ MC_CMD_OP(cmd, 2, 16, 8, char, endpoint1->type[2]); \ ++ MC_CMD_OP(cmd, 2, 24, 8, char, endpoint1->type[3]); \ ++ MC_CMD_OP(cmd, 2, 32, 8, char, endpoint1->type[4]); \ ++ MC_CMD_OP(cmd, 2, 40, 8, char, endpoint1->type[5]); \ ++ MC_CMD_OP(cmd, 2, 48, 8, char, endpoint1->type[6]); \ ++ MC_CMD_OP(cmd, 2, 56, 8, char, endpoint1->type[7]); \ ++ MC_CMD_OP(cmd, 3, 0, 8, char, endpoint1->type[8]); \ ++ MC_CMD_OP(cmd, 3, 8, 8, char, endpoint1->type[9]); \ ++ MC_CMD_OP(cmd, 3, 16, 8, char, endpoint1->type[10]); \ ++ MC_CMD_OP(cmd, 3, 24, 8, char, endpoint1->type[11]); \ ++ MC_CMD_OP(cmd, 3, 32, 8, char, endpoint1->type[12]); \ ++ MC_CMD_OP(cmd, 3, 40, 8, char, endpoint1->type[13]); \ ++ MC_CMD_OP(cmd, 3, 48, 8, char, endpoint1->type[14]); \ ++ MC_CMD_OP(cmd, 3, 56, 8, char, endpoint1->type[15]); \ ++ MC_CMD_OP(cmd, 4, 0, 32, uint32_t, cfg->max_rate); \ ++ MC_CMD_OP(cmd, 4, 32, 32, uint32_t, cfg->committed_rate); \ ++ MC_CMD_OP(cmd, 5, 0, 8, char, endpoint2->type[0]); \ ++ MC_CMD_OP(cmd, 5, 8, 8, char, endpoint2->type[1]); \ ++ MC_CMD_OP(cmd, 5, 16, 8, char, endpoint2->type[2]); \ ++ MC_CMD_OP(cmd, 5, 24, 8, char, endpoint2->type[3]); \ ++ MC_CMD_OP(cmd, 5, 32, 8, char, endpoint2->type[4]); \ ++ MC_CMD_OP(cmd, 5, 40, 8, char, endpoint2->type[5]); \ ++ MC_CMD_OP(cmd, 5, 48, 8, char, endpoint2->type[6]); \ ++ MC_CMD_OP(cmd, 5, 56, 8, char, endpoint2->type[7]); \ ++ MC_CMD_OP(cmd, 6, 0, 8, char, endpoint2->type[8]); \ ++ MC_CMD_OP(cmd, 6, 8, 8, char, endpoint2->type[9]); \ ++ MC_CMD_OP(cmd, 6, 16, 8, char, endpoint2->type[10]); \ ++ MC_CMD_OP(cmd, 6, 24, 8, char, endpoint2->type[11]); \ ++ MC_CMD_OP(cmd, 6, 32, 8, char, endpoint2->type[12]); \ ++ MC_CMD_OP(cmd, 6, 40, 8, char, endpoint2->type[13]); \ ++ MC_CMD_OP(cmd, 6, 48, 8, char, endpoint2->type[14]); \ ++ MC_CMD_OP(cmd, 6, 56, 8, char, endpoint2->type[15]); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_DISCONNECT(cmd, endpoint) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, endpoint->id); \ ++ MC_CMD_OP(cmd, 0, 32, 16, uint16_t, endpoint->if_id); \ ++ MC_CMD_OP(cmd, 1, 0, 8, char, endpoint->type[0]); \ ++ MC_CMD_OP(cmd, 1, 8, 8, char, endpoint->type[1]); \ ++ MC_CMD_OP(cmd, 1, 16, 8, char, endpoint->type[2]); \ ++ MC_CMD_OP(cmd, 1, 24, 8, char, endpoint->type[3]); \ ++ MC_CMD_OP(cmd, 1, 32, 8, char, endpoint->type[4]); \ ++ MC_CMD_OP(cmd, 1, 40, 8, char, endpoint->type[5]); \ ++ MC_CMD_OP(cmd, 1, 48, 8, char, endpoint->type[6]); \ ++ MC_CMD_OP(cmd, 1, 56, 8, char, endpoint->type[7]); \ ++ MC_CMD_OP(cmd, 2, 0, 8, char, endpoint->type[8]); \ ++ MC_CMD_OP(cmd, 2, 8, 8, char, endpoint->type[9]); \ ++ MC_CMD_OP(cmd, 2, 16, 8, char, endpoint->type[10]); \ ++ MC_CMD_OP(cmd, 2, 24, 8, char, endpoint->type[11]); \ ++ MC_CMD_OP(cmd, 2, 32, 8, char, endpoint->type[12]); \ ++ MC_CMD_OP(cmd, 2, 40, 8, char, endpoint->type[13]); \ ++ MC_CMD_OP(cmd, 2, 48, 8, char, endpoint->type[14]); \ ++ MC_CMD_OP(cmd, 2, 56, 8, char, endpoint->type[15]); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_GET_CONNECTION(cmd, endpoint1) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, endpoint1->id); \ ++ MC_CMD_OP(cmd, 0, 32, 16, uint16_t, endpoint1->if_id); \ ++ MC_CMD_OP(cmd, 1, 0, 8, char, endpoint1->type[0]); \ ++ MC_CMD_OP(cmd, 1, 8, 8, char, endpoint1->type[1]); \ ++ MC_CMD_OP(cmd, 1, 16, 8, char, endpoint1->type[2]); \ ++ MC_CMD_OP(cmd, 1, 24, 8, char, endpoint1->type[3]); \ ++ MC_CMD_OP(cmd, 1, 32, 8, char, endpoint1->type[4]); \ ++ MC_CMD_OP(cmd, 1, 40, 8, char, endpoint1->type[5]); \ ++ MC_CMD_OP(cmd, 1, 48, 8, char, endpoint1->type[6]); \ ++ MC_CMD_OP(cmd, 1, 56, 8, char, endpoint1->type[7]); \ ++ MC_CMD_OP(cmd, 2, 0, 8, char, endpoint1->type[8]); \ ++ MC_CMD_OP(cmd, 2, 8, 8, char, endpoint1->type[9]); \ ++ MC_CMD_OP(cmd, 2, 16, 8, char, endpoint1->type[10]); \ ++ MC_CMD_OP(cmd, 2, 24, 8, char, endpoint1->type[11]); \ ++ MC_CMD_OP(cmd, 2, 32, 8, char, endpoint1->type[12]); \ ++ MC_CMD_OP(cmd, 2, 40, 8, char, endpoint1->type[13]); \ ++ MC_CMD_OP(cmd, 2, 48, 8, char, endpoint1->type[14]); \ ++ MC_CMD_OP(cmd, 2, 56, 8, char, endpoint1->type[15]); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_RSP_GET_CONNECTION(cmd, endpoint2, state) \ ++do { \ ++ MC_RSP_OP(cmd, 3, 0, 32, int, endpoint2->id); \ ++ MC_RSP_OP(cmd, 3, 32, 16, uint16_t, endpoint2->if_id); \ ++ MC_RSP_OP(cmd, 4, 0, 8, char, endpoint2->type[0]); \ ++ MC_RSP_OP(cmd, 4, 8, 8, char, endpoint2->type[1]); \ ++ MC_RSP_OP(cmd, 4, 16, 8, char, endpoint2->type[2]); \ ++ MC_RSP_OP(cmd, 4, 24, 8, char, endpoint2->type[3]); \ ++ MC_RSP_OP(cmd, 4, 32, 8, char, endpoint2->type[4]); \ ++ MC_RSP_OP(cmd, 4, 40, 8, char, endpoint2->type[5]); \ ++ MC_RSP_OP(cmd, 4, 48, 8, char, endpoint2->type[6]); \ ++ MC_RSP_OP(cmd, 4, 56, 8, char, endpoint2->type[7]); \ ++ MC_RSP_OP(cmd, 5, 0, 8, char, endpoint2->type[8]); \ ++ MC_RSP_OP(cmd, 5, 8, 8, char, endpoint2->type[9]); \ ++ MC_RSP_OP(cmd, 5, 16, 8, char, endpoint2->type[10]); \ ++ MC_RSP_OP(cmd, 5, 24, 8, char, endpoint2->type[11]); \ ++ MC_RSP_OP(cmd, 5, 32, 8, char, endpoint2->type[12]); \ ++ MC_RSP_OP(cmd, 5, 40, 8, char, endpoint2->type[13]); \ ++ MC_RSP_OP(cmd, 5, 48, 8, char, endpoint2->type[14]); \ ++ MC_RSP_OP(cmd, 5, 56, 8, char, endpoint2->type[15]); \ ++ MC_RSP_OP(cmd, 6, 0, 32, int, state); \ ++} while (0) ++ ++#endif /* _FSL_DPRC_CMD_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dprtc.h b/drivers/net/dpaa2/mc/fsl_dprtc.h +new file mode 100644 +index 0000000..2eb6edc +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dprtc.h +@@ -0,0 +1,434 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPRTC_H ++#define __FSL_DPRTC_H ++ ++/* Data Path Real Time Counter API ++ * Contains initialization APIs and runtime control APIs for RTC ++ */ ++ ++struct fsl_mc_io; ++ ++/** ++ * Number of irq's ++ */ ++#define DPRTC_MAX_IRQ_NUM 1 ++#define DPRTC_IRQ_INDEX 0 ++ ++/** ++ * Interrupt event masks: ++ */ ++ ++/** ++ * Interrupt event mask indicating alarm event had occured ++ */ ++#define DPRTC_EVENT_ALARM 0x40000000 ++/** ++ * Interrupt event mask indicating periodic pulse event had occured ++ */ ++#define DPRTC_EVENT_PPS 0x08000000 ++ ++/** ++ * dprtc_open() - Open a control session for the specified object. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @dprtc_id: DPRTC unique ID ++ * @token: Returned token; use in subsequent API calls ++ * ++ * This function can be used to open a control session for an ++ * already created object; an object may have been declared in ++ * the DPL or by calling the dprtc_create function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent commands for ++ * this specific object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprtc_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dprtc_id, ++ uint16_t *token); ++ ++/** ++ * dprtc_close() - Close the control session of the object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRTC object ++ * ++ * After this function is called, no further operations are ++ * allowed on the object without opening a new control session. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprtc_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * struct dprtc_cfg - Structure representing DPRTC configuration ++ * @options: place holder ++ */ ++struct dprtc_cfg { ++ uint32_t options; ++}; ++ ++/** ++ * dprtc_create() - Create the DPRTC object. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @cfg: Configuration structure ++ * @token: Returned token; use in subsequent API calls ++ * ++ * Create the DPRTC object, allocate required resources and ++ * perform required initialization. ++ * ++ * The object can be created either by declaring it in the ++ * DPL file, or by calling this function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent calls to ++ * this specific object. For objects that are created using the ++ * DPL file, call dprtc_open function to get an authentication ++ * token first. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprtc_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dprtc_cfg *cfg, ++ uint16_t *token); ++ ++/** ++ * dprtc_destroy() - Destroy the DPRTC object and release all its resources. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRTC object ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dprtc_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dprtc_set_clock_offset() - Sets the clock's offset ++ * (usually relative to another clock). ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRTC object ++ * @offset: New clock offset (in nanoseconds). ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprtc_set_clock_offset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int64_t offset); ++ ++/** ++ * dprtc_set_freq_compensation() - Sets a new frequency compensation value. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRTC object ++ * @freq_compensation: ++ * The new frequency compensation value to set. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprtc_set_freq_compensation(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint32_t freq_compensation); ++ ++/** ++ * dprtc_get_freq_compensation() - Retrieves the frequency compensation value ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRTC object ++ * @freq_compensation: ++ * Frequency compensation value ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprtc_get_freq_compensation(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint32_t *freq_compensation); ++ ++/** ++ * dprtc_get_time() - Returns the current RTC time. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRTC object ++ * @time: Current RTC time. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprtc_get_time(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint64_t *time); ++ ++/** ++ * dprtc_set_time() - Updates current RTC time. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRTC object ++ * @time: New RTC time. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprtc_set_time(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint64_t time); ++ ++/** ++ * dprtc_set_alarm() - Defines and sets alarm. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRTC object ++ * @time: In nanoseconds, the time when the alarm ++ * should go off - must be a multiple of ++ * 1 microsecond ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprtc_set_alarm(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint64_t time); ++ ++/** ++ * struct dprtc_irq_cfg - IRQ configuration ++ * @addr: Address that must be written to signal a message-based interrupt ++ * @val: Value to write into irq_addr address ++ * @irq_num: A user defined number associated with this IRQ ++ */ ++struct dprtc_irq_cfg { ++ uint64_t addr; ++ uint32_t val; ++ int irq_num; ++}; ++ ++/** ++ * dprtc_set_irq() - Set IRQ information for the DPRTC to trigger an interrupt. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRTC object ++ * @irq_index: Identifies the interrupt index to configure ++ * @irq_cfg: IRQ configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprtc_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dprtc_irq_cfg *irq_cfg); ++ ++/** ++ * dprtc_get_irq() - Get IRQ information from the DPRTC. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRTC object ++ * @irq_index: The interrupt index to configure ++ * @type: Interrupt type: 0 represents message interrupt ++ * type (both irq_addr and irq_val are valid) ++ * @irq_cfg: IRQ attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprtc_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dprtc_irq_cfg *irq_cfg); ++ ++/** ++ * dprtc_set_irq_enable() - Set overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRTC object ++ * @irq_index: The interrupt index to configure ++ * @en: Interrupt state - enable = 1, disable = 0 ++ * ++ * Allows GPP software to control when interrupts are generated. ++ * Each interrupt can have up to 32 causes. The enable/disable control's the ++ * overall interrupt state. if the interrupt is disabled no causes will cause ++ * an interrupt. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprtc_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en); ++ ++/** ++ * dprtc_get_irq_enable() - Get overall interrupt state ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRTC object ++ * @irq_index: The interrupt index to configure ++ * @en: Returned interrupt state - enable = 1, disable = 0 ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprtc_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en); ++ ++/** ++ * dprtc_set_irq_mask() - Set interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRTC object ++ * @irq_index: The interrupt index to configure ++ * @mask: Event mask to trigger interrupt; ++ * each bit: ++ * 0 = ignore event ++ * 1 = consider event for asserting IRQ ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprtc_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask); ++ ++/** ++ * dprtc_get_irq_mask() - Get interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRTC object ++ * @irq_index: The interrupt index to configure ++ * @mask: Returned event mask to trigger interrupt ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprtc_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask); ++ ++/** ++ * dprtc_get_irq_status() - Get the current status of any pending interrupts. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRTC object ++ * @irq_index: The interrupt index to configure ++ * @status: Returned interrupts status - one bit per cause: ++ * 0 = no interrupt pending ++ * 1 = interrupt pending ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprtc_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status); ++ ++/** ++ * dprtc_clear_irq_status() - Clear a pending interrupt's status ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRTC object ++ * @irq_index: The interrupt index to configure ++ * @status: Bits to clear (W1C) - one bit per cause: ++ * 0 = don't change ++ * 1 = clear status bit ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprtc_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status); ++ ++/** ++ * struct dprtc_attr - Structure representing DPRTC attributes ++ * @id: DPRTC object ID ++ * @version: DPRTC version ++ */ ++struct dprtc_attr { ++ int id; ++ /** ++ * struct version - Structure representing DPRTC version ++ * @major: DPRTC major version ++ * @minor: DPRTC minor version ++ */ ++ struct { ++ uint16_t major; ++ uint16_t minor; ++ } version; ++}; ++ ++/** ++ * dprtc_get_attributes - Retrieve DPRTC attributes. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRTC object ++ * @attr: Returned object's attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprtc_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dprtc_attr *attr); ++ ++#endif /* __FSL_DPRTC_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dprtc_cmd.h b/drivers/net/dpaa2/mc/fsl_dprtc_cmd.h +new file mode 100644 +index 0000000..aeccece +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dprtc_cmd.h +@@ -0,0 +1,181 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_DPRTC_CMD_H ++#define _FSL_DPRTC_CMD_H ++ ++/* DPRTC Version */ ++#define DPRTC_VER_MAJOR 1 ++#define DPRTC_VER_MINOR 0 ++ ++/* Command IDs */ ++#define DPRTC_CMDID_CLOSE 0x800 ++#define DPRTC_CMDID_OPEN 0x810 ++#define DPRTC_CMDID_CREATE 0x910 ++#define DPRTC_CMDID_DESTROY 0x900 ++ ++#define DPRTC_CMDID_ENABLE 0x002 ++#define DPRTC_CMDID_DISABLE 0x003 ++#define DPRTC_CMDID_GET_ATTR 0x004 ++#define DPRTC_CMDID_RESET 0x005 ++#define DPRTC_CMDID_IS_ENABLED 0x006 ++ ++#define DPRTC_CMDID_SET_IRQ 0x010 ++#define DPRTC_CMDID_GET_IRQ 0x011 ++#define DPRTC_CMDID_SET_IRQ_ENABLE 0x012 ++#define DPRTC_CMDID_GET_IRQ_ENABLE 0x013 ++#define DPRTC_CMDID_SET_IRQ_MASK 0x014 ++#define DPRTC_CMDID_GET_IRQ_MASK 0x015 ++#define DPRTC_CMDID_GET_IRQ_STATUS 0x016 ++#define DPRTC_CMDID_CLEAR_IRQ_STATUS 0x017 ++ ++#define DPRTC_CMDID_SET_CLOCK_OFFSET 0x1d0 ++#define DPRTC_CMDID_SET_FREQ_COMPENSATION 0x1d1 ++#define DPRTC_CMDID_GET_FREQ_COMPENSATION 0x1d2 ++#define DPRTC_CMDID_GET_TIME 0x1d3 ++#define DPRTC_CMDID_SET_TIME 0x1d4 ++#define DPRTC_CMDID_SET_ALARM 0x1d5 ++#define DPRTC_CMDID_SET_PERIODIC_PULSE 0x1d6 ++#define DPRTC_CMDID_CLEAR_PERIODIC_PULSE 0x1d7 ++#define DPRTC_CMDID_SET_EXT_TRIGGER 0x1d8 ++#define DPRTC_CMDID_CLEAR_EXT_TRIGGER 0x1d9 ++#define DPRTC_CMDID_GET_EXT_TRIGGER_TIMESTAMP 0x1dA ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_CMD_OPEN(cmd, dpbp_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpbp_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_RSP_IS_ENABLED(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, irq_index);\ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, irq_cfg->val);\ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr); \ ++ MC_CMD_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_CMD_GET_IRQ(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_RSP_GET_IRQ(cmd, type, irq_cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr); \ ++ MC_RSP_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, type); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_CMD_SET_IRQ_ENABLE(cmd, irq_index, en) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, en); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_CMD_GET_IRQ_ENABLE(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_RSP_GET_IRQ_ENABLE(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 8, uint8_t, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, mask);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_CMD_GET_IRQ_MASK(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_RSP_GET_IRQ_MASK(cmd, mask) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mask) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_RSP_GET_IRQ_STATUS(cmd, status) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, status) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_RSP_GET_ATTRIBUTES(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 32, 32, int, attr->id);\ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->version.major);\ ++ MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->version.minor);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_CMD_SET_CLOCK_OFFSET(cmd, offset) \ ++ MC_CMD_OP(cmd, 0, 0, 64, int64_t, offset) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_CMD_SET_FREQ_COMPENSATION(cmd, freq_compensation) \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, freq_compensation) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_RSP_GET_FREQ_COMPENSATION(cmd, freq_compensation) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, freq_compensation) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_RSP_GET_TIME(cmd, time) \ ++ MC_RSP_OP(cmd, 0, 0, 64, uint64_t, time) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_CMD_SET_TIME(cmd, time) \ ++ MC_CMD_OP(cmd, 0, 0, 64, uint64_t, time) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_CMD_SET_ALARM(cmd, time) \ ++ MC_CMD_OP(cmd, 0, 0, 64, uint64_t, time) ++ ++#endif /* _FSL_DPRTC_CMD_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpseci.h b/drivers/net/dpaa2/mc/fsl_dpseci.h +new file mode 100644 +index 0000000..1dd7215 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpseci.h +@@ -0,0 +1,647 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPSECI_H ++#define __FSL_DPSECI_H ++ ++/* Data Path SEC Interface API ++ * Contains initialization APIs and runtime control APIs for DPSECI ++ */ ++ ++struct fsl_mc_io; ++ ++/** ++ * General DPSECI macros ++ */ ++ ++/** ++ * Maximum number of Tx/Rx priorities per DPSECI object ++ */ ++#define DPSECI_PRIO_NUM 8 ++ ++/** ++ * All queues considered; see dpseci_set_rx_queue() ++ */ ++#define DPSECI_ALL_QUEUES (uint8_t)(-1) ++ ++/** ++ * dpseci_open() - Open a control session for the specified object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @dpseci_id: DPSECI unique ID ++ * @token: Returned token; use in subsequent API calls ++ * ++ * This function can be used to open a control session for an ++ * already created object; an object may have been declared in ++ * the DPL or by calling the dpseci_create() function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent commands for ++ * this specific object. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpseci_id, ++ uint16_t *token); ++ ++/** ++ * dpseci_close() - Close the control session of the object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * ++ * After this function is called, no further operations are ++ * allowed on the object without opening a new control session. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * struct dpseci_cfg - Structure representing DPSECI configuration ++ * @num_tx_queues: num of queues towards the SEC ++ * @num_rx_queues: num of queues back from the SEC ++ * @priorities: Priorities for the SEC hardware processing; ++ * each place in the array is the priority of the tx queue ++ * towards the SEC, ++ * valid priorities are configured with values 1-8; ++ */ ++struct dpseci_cfg { ++ uint8_t num_tx_queues; ++ uint8_t num_rx_queues; ++ uint8_t priorities[DPSECI_PRIO_NUM]; ++}; ++ ++/** ++ * dpseci_create() - Create the DPSECI object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @cfg: Configuration structure ++ * @token: Returned token; use in subsequent API calls ++ * ++ * Create the DPSECI object, allocate required resources and ++ * perform required initialization. ++ * ++ * The object can be created either by declaring it in the ++ * DPL file, or by calling this function. ++ * ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent calls to ++ * this specific object. For objects that are created using the ++ * DPL file, call dpseci_open() function to get an authentication ++ * token first. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpseci_cfg *cfg, ++ uint16_t *token); ++ ++/** ++ * dpseci_destroy() - Destroy the DPSECI object and release all its resources. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpseci_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpseci_enable() - Enable the DPSECI, allow sending and receiving frames. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpseci_disable() - Disable the DPSECI, stop sending and receiving frames. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpseci_is_enabled() - Check if the DPSECI is enabled. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * @en: Returns '1' if object is enabled; '0' otherwise ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en); ++ ++/** ++ * dpseci_reset() - Reset the DPSECI, returns the object to initial state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * struct dpseci_irq_cfg - IRQ configuration ++ * @addr: Address that must be written to signal a message-based interrupt ++ * @val: Value to write into irq_addr address ++ * @irq_num: A user defined number associated with this IRQ ++ */ ++struct dpseci_irq_cfg { ++ uint64_t addr; ++ uint32_t val; ++ int irq_num; ++}; ++ ++/** ++ * dpseci_set_irq() - Set IRQ information for the DPSECI to trigger an interrupt ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * @irq_index: Identifies the interrupt index to configure ++ * @irq_cfg: IRQ configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpseci_irq_cfg *irq_cfg); ++ ++/** ++ * dpseci_get_irq() - Get IRQ information from the DPSECI ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * @irq_index: The interrupt index to configure ++ * @type: Interrupt type: 0 represents message interrupt ++ * type (both irq_addr and irq_val are valid) ++ * @irq_cfg: IRQ attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpseci_irq_cfg *irq_cfg); ++ ++/** ++ * dpseci_set_irq_enable() - Set overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * @irq_index: The interrupt index to configure ++ * @en: Interrupt state - enable = 1, disable = 0 ++ * ++ * Allows GPP software to control when interrupts are generated. ++ * Each interrupt can have up to 32 causes. The enable/disable control's the ++ * overall interrupt state. if the interrupt is disabled no causes will cause ++ * an interrupt ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en); ++ ++/** ++ * dpseci_get_irq_enable() - Get overall interrupt state ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * @irq_index: The interrupt index to configure ++ * @en: Returned Interrupt state - enable = 1, disable = 0 ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en); ++ ++/** ++ * dpseci_set_irq_mask() - Set interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * @irq_index: The interrupt index to configure ++ * @mask: event mask to trigger interrupt; ++ * each bit: ++ * 0 = ignore event ++ * 1 = consider event for asserting IRQ ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask); ++ ++/** ++ * dpseci_get_irq_mask() - Get interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * @irq_index: The interrupt index to configure ++ * @mask: Returned event mask to trigger interrupt ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask); ++ ++/** ++ * dpseci_get_irq_status() - Get the current status of any pending interrupts ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * @irq_index: The interrupt index to configure ++ * @status: Returned interrupts status - one bit per cause: ++ * 0 = no interrupt pending ++ * 1 = interrupt pending ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status); ++ ++/** ++ * dpseci_clear_irq_status() - Clear a pending interrupt's status ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * @irq_index: The interrupt index to configure ++ * @status: bits to clear (W1C) - one bit per cause: ++ * 0 = don't change ++ * 1 = clear status bit ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status); ++ ++/** ++ * struct dpseci_attr - Structure representing DPSECI attributes ++ * @id: DPSECI object ID ++ * @version: DPSECI version ++ * @num_tx_queues: number of queues towards the SEC ++ * @num_rx_queues: number of queues back from the SEC ++ */ ++struct dpseci_attr { ++ int id; ++ /** ++ * struct version - DPSECI version ++ * @major: DPSECI major version ++ * @minor: DPSECI minor version ++ */ ++ struct { ++ uint16_t major; ++ uint16_t minor; ++ } version; ++ uint8_t num_tx_queues; ++ uint8_t num_rx_queues; ++}; ++ ++/** ++ * dpseci_get_attributes() - Retrieve DPSECI attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * @attr: Returned object's attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpseci_attr *attr); ++ ++/** ++ * enum dpseci_dest - DPSECI destination types ++ * @DPSECI_DEST_NONE: Unassigned destination; The queue is set in parked mode ++ * and does not generate FQDAN notifications; user is expected to ++ * dequeue from the queue based on polling or other user-defined ++ * method ++ * @DPSECI_DEST_DPIO: The queue is set in schedule mode and generates FQDAN ++ * notifications to the specified DPIO; user is expected to dequeue ++ * from the queue only after notification is received ++ * @DPSECI_DEST_DPCON: The queue is set in schedule mode and does not generate ++ * FQDAN notifications, but is connected to the specified DPCON ++ * object; user is expected to dequeue from the DPCON channel ++ */ ++enum dpseci_dest { ++ DPSECI_DEST_NONE = 0, ++ DPSECI_DEST_DPIO = 1, ++ DPSECI_DEST_DPCON = 2 ++}; ++ ++/** ++ * struct dpseci_dest_cfg - Structure representing DPSECI destination parameters ++ * @dest_type: Destination type ++ * @dest_id: Either DPIO ID or DPCON ID, depending on the destination type ++ * @priority: Priority selection within the DPIO or DPCON channel; valid values ++ * are 0-1 or 0-7, depending on the number of priorities in that ++ * channel; not relevant for 'DPSECI_DEST_NONE' option ++ */ ++struct dpseci_dest_cfg { ++ enum dpseci_dest dest_type; ++ int dest_id; ++ uint8_t priority; ++}; ++ ++/** ++ * DPSECI queue modification options ++ */ ++ ++/** ++ * Select to modify the user's context associated with the queue ++ */ ++#define DPSECI_QUEUE_OPT_USER_CTX 0x00000001 ++ ++/** ++ * Select to modify the queue's destination ++ */ ++#define DPSECI_QUEUE_OPT_DEST 0x00000002 ++ ++/** ++ * Select to modify the queue's order preservation ++ */ ++#define DPSECI_QUEUE_OPT_ORDER_PRESERVATION 0x00000004 ++ ++/** ++ * struct dpseci_rx_queue_cfg - DPSECI RX queue configuration ++ * @options: Flags representing the suggested modifications to the queue; ++ * Use any combination of 'DPSECI_QUEUE_OPT_' flags ++ * @order_preservation_en: order preservation configuration for the rx queue ++ * valid only if 'DPSECI_QUEUE_OPT_ORDER_PRESERVATION' is contained in 'options' ++ * @user_ctx: User context value provided in the frame descriptor of each ++ * dequeued frame; ++ * valid only if 'DPSECI_QUEUE_OPT_USER_CTX' is contained in 'options' ++ * @dest_cfg: Queue destination parameters; ++ * valid only if 'DPSECI_QUEUE_OPT_DEST' is contained in 'options' ++ */ ++struct dpseci_rx_queue_cfg { ++ uint32_t options; ++ int order_preservation_en; ++ uint64_t user_ctx; ++ struct dpseci_dest_cfg dest_cfg; ++}; ++ ++/** ++ * dpseci_set_rx_queue() - Set Rx queue configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * @queue: Select the queue relative to number of ++ * priorities configured at DPSECI creation; use ++ * DPSECI_ALL_QUEUES to configure all Rx queues identically. ++ * @cfg: Rx queue configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_set_rx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t queue, ++ const struct dpseci_rx_queue_cfg *cfg); ++ ++/** ++ * struct dpseci_rx_queue_attr - Structure representing attributes of Rx queues ++ * @user_ctx: User context value provided in the frame descriptor of each ++ * dequeued frame ++ * @order_preservation_en: Status of the order preservation configuration ++ * on the queue ++ * @dest_cfg: Queue destination configuration ++ * @fqid: Virtual FQID value to be used for dequeue operations ++ */ ++struct dpseci_rx_queue_attr { ++ uint64_t user_ctx; ++ int order_preservation_en; ++ struct dpseci_dest_cfg dest_cfg; ++ uint32_t fqid; ++}; ++ ++/** ++ * dpseci_get_rx_queue() - Retrieve Rx queue attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * @queue: Select the queue relative to number of ++ * priorities configured at DPSECI creation ++ * @attr: Returned Rx queue attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_get_rx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t queue, ++ struct dpseci_rx_queue_attr *attr); ++ ++/** ++ * struct dpseci_tx_queue_attr - Structure representing attributes of Tx queues ++ * @fqid: Virtual FQID to be used for sending frames to SEC hardware ++ * @priority: SEC hardware processing priority for the queue ++ */ ++struct dpseci_tx_queue_attr { ++ uint32_t fqid; ++ uint8_t priority; ++}; ++ ++/** ++ * dpseci_get_tx_queue() - Retrieve Tx queue attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * @queue: Select the queue relative to number of ++ * priorities configured at DPSECI creation ++ * @attr: Returned Tx queue attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_get_tx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t queue, ++ struct dpseci_tx_queue_attr *attr); ++ ++/** ++ * struct dpseci_sec_attr - Structure representing attributes of the SEC ++ * hardware accelerator ++ * @ip_id: ID for SEC. ++ * @major_rev: Major revision number for SEC. ++ * @minor_rev: Minor revision number for SEC. ++ * @era: SEC Era. ++ * @deco_num: The number of copies of the DECO that are implemented in ++ * this version of SEC. ++ * @zuc_auth_acc_num: The number of copies of ZUCA that are implemented ++ * in this version of SEC. ++ * @zuc_enc_acc_num: The number of copies of ZUCE that are implemented ++ * in this version of SEC. ++ * @snow_f8_acc_num: The number of copies of the SNOW-f8 module that are ++ * implemented in this version of SEC. ++ * @snow_f9_acc_num: The number of copies of the SNOW-f9 module that are ++ * implemented in this version of SEC. ++ * @crc_acc_num: The number of copies of the CRC module that are implemented ++ * in this version of SEC. ++ * @pk_acc_num: The number of copies of the Public Key module that are ++ * implemented in this version of SEC. ++ * @kasumi_acc_num: The number of copies of the Kasumi module that are ++ * implemented in this version of SEC. ++ * @rng_acc_num: The number of copies of the Random Number Generator that are ++ * implemented in this version of SEC. ++ * @md_acc_num: The number of copies of the MDHA (Hashing module) that are ++ * implemented in this version of SEC. ++ * @arc4_acc_num: The number of copies of the ARC4 module that are implemented ++ * in this version of SEC. ++ * @des_acc_num: The number of copies of the DES module that are implemented ++ * in this version of SEC. ++ * @aes_acc_num: The number of copies of the AES module that are implemented ++ * in this version of SEC. ++ **/ ++ ++struct dpseci_sec_attr { ++ uint16_t ip_id; ++ uint8_t major_rev; ++ uint8_t minor_rev; ++ uint8_t era; ++ uint8_t deco_num; ++ uint8_t zuc_auth_acc_num; ++ uint8_t zuc_enc_acc_num; ++ uint8_t snow_f8_acc_num; ++ uint8_t snow_f9_acc_num; ++ uint8_t crc_acc_num; ++ uint8_t pk_acc_num; ++ uint8_t kasumi_acc_num; ++ uint8_t rng_acc_num; ++ uint8_t md_acc_num; ++ uint8_t arc4_acc_num; ++ uint8_t des_acc_num; ++ uint8_t aes_acc_num; ++}; ++ ++/** ++ * dpseci_get_sec_attr() - Retrieve SEC accelerator attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * @attr: Returned SEC attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_get_sec_attr(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpseci_sec_attr *attr); ++ ++/** ++ * struct dpseci_sec_counters - Structure representing global SEC counters and ++ * not per dpseci counters ++ * @dequeued_requests: Number of Requests Dequeued ++ * @ob_enc_requests: Number of Outbound Encrypt Requests ++ * @ib_dec_requests: Number of Inbound Decrypt Requests ++ * @ob_enc_bytes: Number of Outbound Bytes Encrypted ++ * @ob_prot_bytes: Number of Outbound Bytes Protected ++ * @ib_dec_bytes: Number of Inbound Bytes Decrypted ++ * @ib_valid_bytes: Number of Inbound Bytes Validated ++ */ ++struct dpseci_sec_counters { ++ uint64_t dequeued_requests; ++ uint64_t ob_enc_requests; ++ uint64_t ib_dec_requests; ++ uint64_t ob_enc_bytes; ++ uint64_t ob_prot_bytes; ++ uint64_t ib_dec_bytes; ++ uint64_t ib_valid_bytes; ++}; ++ ++/** ++ * dpseci_get_sec_counters() - Retrieve SEC accelerator counters. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * @counters: Returned SEC counters ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_get_sec_counters(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpseci_sec_counters *counters); ++ ++#endif /* __FSL_DPSECI_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpseci_cmd.h b/drivers/net/dpaa2/mc/fsl_dpseci_cmd.h +new file mode 100644 +index 0000000..6c0b96e +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpseci_cmd.h +@@ -0,0 +1,241 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_DPSECI_CMD_H ++#define _FSL_DPSECI_CMD_H ++ ++/* DPSECI Version */ ++#define DPSECI_VER_MAJOR 3 ++#define DPSECI_VER_MINOR 1 ++ ++/* Command IDs */ ++#define DPSECI_CMDID_CLOSE 0x800 ++#define DPSECI_CMDID_OPEN 0x809 ++#define DPSECI_CMDID_CREATE 0x909 ++#define DPSECI_CMDID_DESTROY 0x900 ++ ++#define DPSECI_CMDID_ENABLE 0x002 ++#define DPSECI_CMDID_DISABLE 0x003 ++#define DPSECI_CMDID_GET_ATTR 0x004 ++#define DPSECI_CMDID_RESET 0x005 ++#define DPSECI_CMDID_IS_ENABLED 0x006 ++ ++#define DPSECI_CMDID_SET_IRQ 0x010 ++#define DPSECI_CMDID_GET_IRQ 0x011 ++#define DPSECI_CMDID_SET_IRQ_ENABLE 0x012 ++#define DPSECI_CMDID_GET_IRQ_ENABLE 0x013 ++#define DPSECI_CMDID_SET_IRQ_MASK 0x014 ++#define DPSECI_CMDID_GET_IRQ_MASK 0x015 ++#define DPSECI_CMDID_GET_IRQ_STATUS 0x016 ++#define DPSECI_CMDID_CLEAR_IRQ_STATUS 0x017 ++ ++#define DPSECI_CMDID_SET_RX_QUEUE 0x194 ++#define DPSECI_CMDID_GET_RX_QUEUE 0x196 ++#define DPSECI_CMDID_GET_TX_QUEUE 0x197 ++#define DPSECI_CMDID_GET_SEC_ATTR 0x198 ++#define DPSECI_CMDID_GET_SEC_COUNTERS 0x199 ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_CMD_OPEN(cmd, dpseci_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpseci_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_CMD_CREATE(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, cfg->priorities[0]);\ ++ MC_CMD_OP(cmd, 0, 8, 8, uint8_t, cfg->priorities[1]);\ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, cfg->priorities[2]);\ ++ MC_CMD_OP(cmd, 0, 24, 8, uint8_t, cfg->priorities[3]);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->priorities[4]);\ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, cfg->priorities[5]);\ ++ MC_CMD_OP(cmd, 0, 48, 8, uint8_t, cfg->priorities[6]);\ ++ MC_CMD_OP(cmd, 0, 56, 8, uint8_t, cfg->priorities[7]);\ ++ MC_CMD_OP(cmd, 1, 0, 8, uint8_t, cfg->num_tx_queues);\ ++ MC_CMD_OP(cmd, 1, 8, 8, uint8_t, cfg->num_rx_queues);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_RSP_IS_ENABLED(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, irq_index);\ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, irq_cfg->val);\ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\ ++ MC_CMD_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_CMD_GET_IRQ(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_RSP_GET_IRQ(cmd, type, irq_cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\ ++ MC_RSP_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, type); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_CMD_SET_IRQ_ENABLE(cmd, irq_index, enable_state) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, enable_state); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_CMD_GET_IRQ_ENABLE(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_RSP_GET_IRQ_ENABLE(cmd, enable_state) \ ++ MC_RSP_OP(cmd, 0, 0, 8, uint8_t, enable_state) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, mask); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_CMD_GET_IRQ_MASK(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_RSP_GET_IRQ_MASK(cmd, mask) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mask) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_RSP_GET_IRQ_STATUS(cmd, status) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, status) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_RSP_GET_ATTR(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, attr->id); \ ++ MC_RSP_OP(cmd, 1, 0, 8, uint8_t, attr->num_tx_queues); \ ++ MC_RSP_OP(cmd, 1, 8, 8, uint8_t, attr->num_rx_queues); \ ++ MC_RSP_OP(cmd, 5, 0, 16, uint16_t, attr->version.major);\ ++ MC_RSP_OP(cmd, 5, 16, 16, uint16_t, attr->version.minor);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_CMD_SET_RX_QUEUE(cmd, queue, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, cfg->dest_cfg.dest_id); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->dest_cfg.priority); \ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, queue); \ ++ MC_CMD_OP(cmd, 0, 48, 4, enum dpseci_dest, cfg->dest_cfg.dest_type); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->user_ctx); \ ++ MC_CMD_OP(cmd, 2, 0, 32, uint32_t, cfg->options);\ ++ MC_CMD_OP(cmd, 2, 32, 1, int, cfg->order_preservation_en);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_CMD_GET_RX_QUEUE(cmd, queue) \ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, queue) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_RSP_GET_RX_QUEUE(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, attr->dest_cfg.dest_id);\ ++ MC_RSP_OP(cmd, 0, 32, 8, uint8_t, attr->dest_cfg.priority);\ ++ MC_RSP_OP(cmd, 0, 48, 4, enum dpseci_dest, attr->dest_cfg.dest_type);\ ++ MC_RSP_OP(cmd, 1, 0, 8, uint64_t, attr->user_ctx);\ ++ MC_RSP_OP(cmd, 2, 0, 32, uint32_t, attr->fqid);\ ++ MC_RSP_OP(cmd, 2, 32, 1, int, attr->order_preservation_en);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_CMD_GET_TX_QUEUE(cmd, queue) \ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, queue) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_RSP_GET_TX_QUEUE(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 32, 32, uint32_t, attr->fqid);\ ++ MC_RSP_OP(cmd, 1, 0, 8, uint8_t, attr->priority);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_RSP_GET_SEC_ATTR(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 16, uint16_t, attr->ip_id);\ ++ MC_RSP_OP(cmd, 0, 16, 8, uint8_t, attr->major_rev);\ ++ MC_RSP_OP(cmd, 0, 24, 8, uint8_t, attr->minor_rev);\ ++ MC_RSP_OP(cmd, 0, 32, 8, uint8_t, attr->era);\ ++ MC_RSP_OP(cmd, 1, 0, 8, uint8_t, attr->deco_num);\ ++ MC_RSP_OP(cmd, 1, 8, 8, uint8_t, attr->zuc_auth_acc_num);\ ++ MC_RSP_OP(cmd, 1, 16, 8, uint8_t, attr->zuc_enc_acc_num);\ ++ MC_RSP_OP(cmd, 1, 32, 8, uint8_t, attr->snow_f8_acc_num);\ ++ MC_RSP_OP(cmd, 1, 40, 8, uint8_t, attr->snow_f9_acc_num);\ ++ MC_RSP_OP(cmd, 1, 48, 8, uint8_t, attr->crc_acc_num);\ ++ MC_RSP_OP(cmd, 2, 0, 8, uint8_t, attr->pk_acc_num);\ ++ MC_RSP_OP(cmd, 2, 8, 8, uint8_t, attr->kasumi_acc_num);\ ++ MC_RSP_OP(cmd, 2, 16, 8, uint8_t, attr->rng_acc_num);\ ++ MC_RSP_OP(cmd, 2, 32, 8, uint8_t, attr->md_acc_num);\ ++ MC_RSP_OP(cmd, 2, 40, 8, uint8_t, attr->arc4_acc_num);\ ++ MC_RSP_OP(cmd, 2, 48, 8, uint8_t, attr->des_acc_num);\ ++ MC_RSP_OP(cmd, 2, 56, 8, uint8_t, attr->aes_acc_num);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_RSP_GET_SEC_COUNTERS(cmd, counters) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 64, uint64_t, counters->dequeued_requests);\ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, counters->ob_enc_requests);\ ++ MC_RSP_OP(cmd, 2, 0, 64, uint64_t, counters->ib_dec_requests);\ ++ MC_RSP_OP(cmd, 3, 0, 64, uint64_t, counters->ob_enc_bytes);\ ++ MC_RSP_OP(cmd, 4, 0, 64, uint64_t, counters->ob_prot_bytes);\ ++ MC_RSP_OP(cmd, 5, 0, 64, uint64_t, counters->ib_dec_bytes);\ ++ MC_RSP_OP(cmd, 6, 0, 64, uint64_t, counters->ib_valid_bytes);\ ++} while (0) ++ ++#endif /* _FSL_DPSECI_CMD_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpsw.h b/drivers/net/dpaa2/mc/fsl_dpsw.h +new file mode 100644 +index 0000000..9c1bd9d +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpsw.h +@@ -0,0 +1,2164 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPSW_H ++#define __FSL_DPSW_H ++ ++#include ++ ++/* Data Path L2-Switch API ++ * Contains API for handling DPSW topology and functionality ++ */ ++ ++struct fsl_mc_io; ++ ++/** ++ * DPSW general definitions ++ */ ++ ++/** ++ * Maximum number of traffic class priorities ++ */ ++#define DPSW_MAX_PRIORITIES 8 ++/** ++ * Maximum number of interfaces ++ */ ++#define DPSW_MAX_IF 64 ++ ++/** ++ * dpsw_open() - Open a control session for the specified object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @dpsw_id: DPSW unique ID ++ * @token: Returned token; use in subsequent API calls ++ * ++ * This function can be used to open a control session for an ++ * already created object; an object may have been declared in ++ * the DPL or by calling the dpsw_create() function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent commands for ++ * this specific object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpsw_id, ++ uint16_t *token); ++ ++/** ++ * dpsw_close() - Close the control session of the object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * ++ * After this function is called, no further operations are ++ * allowed on the object without opening a new control session. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * DPSW options ++ */ ++ ++/** ++ * Disable flooding ++ */ ++#define DPSW_OPT_FLOODING_DIS 0x0000000000000001ULL ++/** ++ * Disable Multicast ++ */ ++#define DPSW_OPT_MULTICAST_DIS 0x0000000000000004ULL ++/** ++ * Support control interface ++ */ ++#define DPSW_OPT_CTRL_IF_DIS 0x0000000000000010ULL ++/** ++ * Disable flooding metering ++ */ ++#define DPSW_OPT_FLOODING_METERING_DIS 0x0000000000000020ULL ++/** ++ * Enable metering ++ */ ++#define DPSW_OPT_METERING_EN 0x0000000000000040ULL ++ ++/** ++ * enum dpsw_component_type - component type of a bridge ++ * @DPSW_COMPONENT_TYPE_C_VLAN: A C-VLAN component of an ++ * enterprise VLAN bridge or of a Provider Bridge used ++ * to process C-tagged frames ++ * @DPSW_COMPONENT_TYPE_S_VLAN: An S-VLAN component of a ++ * Provider Bridge ++ * ++ */ ++enum dpsw_component_type { ++ DPSW_COMPONENT_TYPE_C_VLAN = 0, ++ DPSW_COMPONENT_TYPE_S_VLAN ++}; ++ ++/** ++ * struct dpsw_cfg - DPSW configuration ++ * @num_ifs: Number of external and internal interfaces ++ * @adv: Advanced parameters; default is all zeros; ++ * use this structure to change default settings ++ */ ++struct dpsw_cfg { ++ uint16_t num_ifs; ++ /** ++ * struct adv - Advanced parameters ++ * @options: Enable/Disable DPSW features (bitmap) ++ * @max_vlans: Maximum Number of VLAN's; 0 - indicates default 16 ++ * @max_meters_per_if: Number of meters per interface ++ * @max_fdbs: Maximum Number of FDB's; 0 - indicates default 16 ++ * @max_fdb_entries: Number of FDB entries for default FDB table; ++ * 0 - indicates default 1024 entries. ++ * @fdb_aging_time: Default FDB aging time for default FDB table; ++ * 0 - indicates default 300 seconds ++ * @max_fdb_mc_groups: Number of multicast groups in each FDB table; ++ * 0 - indicates default 32 ++ * @component_type: Indicates the component type of this bridge ++ */ ++ struct { ++ uint64_t options; ++ uint16_t max_vlans; ++ uint8_t max_meters_per_if; ++ uint8_t max_fdbs; ++ uint16_t max_fdb_entries; ++ uint16_t fdb_aging_time; ++ uint16_t max_fdb_mc_groups; ++ enum dpsw_component_type component_type; ++ } adv; ++}; ++ ++/** ++ * dpsw_create() - Create the DPSW object. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @cfg: Configuration structure ++ * @token: Returned token; use in subsequent API calls ++ * ++ * Create the DPSW object, allocate required resources and ++ * perform required initialization. ++ * ++ * The object can be created either by declaring it in the ++ * DPL file, or by calling this function. ++ * ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent calls to ++ * this specific object. For objects that are created using the ++ * DPL file, call dpsw_open() function to get an authentication ++ * token first ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpsw_cfg *cfg, ++ uint16_t *token); ++ ++/** ++ * dpsw_destroy() - Destroy the DPSW object and release all its resources. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpsw_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpsw_enable() - Enable DPSW functionality ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpsw_disable() - Disable DPSW functionality ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpsw_is_enabled() - Check if the DPSW is enabled ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @en: Returns '1' if object is enabled; '0' otherwise ++ * ++ * Return: '0' on Success; Error code otherwise ++ */ ++int dpsw_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en); ++ ++/** ++ * dpsw_reset() - Reset the DPSW, returns the object to initial state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * DPSW IRQ Index and Events ++ */ ++ ++#define DPSW_IRQ_INDEX_IF 0x0000 ++#define DPSW_IRQ_INDEX_L2SW 0x0001 ++ ++/** ++ * IRQ event - Indicates that the link state changed ++ */ ++#define DPSW_IRQ_EVENT_LINK_CHANGED 0x0001 ++ ++/** ++ * struct dpsw_irq_cfg - IRQ configuration ++ * @addr: Address that must be written to signal a message-based interrupt ++ * @val: Value to write into irq_addr address ++ * @irq_num: A user defined number associated with this IRQ ++ */ ++struct dpsw_irq_cfg { ++ uint64_t addr; ++ uint32_t val; ++ int irq_num; ++}; ++ ++/** ++ * dpsw_set_irq() - Set IRQ information for the DPSW to trigger an interrupt. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @irq_index: Identifies the interrupt index to configure ++ * @irq_cfg: IRQ configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpsw_irq_cfg *irq_cfg); ++ ++/** ++ * dpsw_get_irq() - Get IRQ information from the DPSW ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @irq_index: The interrupt index to configure ++ * @type: Interrupt type: 0 represents message interrupt ++ * type (both irq_addr and irq_val are valid) ++ * @irq_cfg: IRQ attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpsw_irq_cfg *irq_cfg); ++ ++/** ++ * dpsw_set_irq_enable() - Set overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @irq_index: The interrupt index to configure ++ * @en: Interrupt state - enable = 1, disable = 0 ++ * ++ * Allows GPP software to control when interrupts are generated. ++ * Each interrupt can have up to 32 causes. The enable/disable control's the ++ * overall interrupt state. if the interrupt is disabled no causes will cause ++ * an interrupt ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en); ++ ++/** ++ * dpsw_get_irq_enable() - Get overall interrupt state ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @irq_index: The interrupt index to configure ++ * @en: Returned Interrupt state - enable = 1, disable = 0 ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en); ++ ++/** ++ * dpsw_set_irq_mask() - Set interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @irq_index: The interrupt index to configure ++ * @mask: event mask to trigger interrupt; ++ * each bit: ++ * 0 = ignore event ++ * 1 = consider event for asserting IRQ ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask); ++ ++/** ++ * dpsw_get_irq_mask() - Get interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @irq_index: The interrupt index to configure ++ * @mask: Returned event mask to trigger interrupt ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask); ++ ++/** ++ * dpsw_get_irq_status() - Get the current status of any pending interrupts ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @irq_index: The interrupt index to configure ++ * @status: Returned interrupts status - one bit per cause: ++ * 0 = no interrupt pending ++ * 1 = interrupt pending ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status); ++ ++/** ++ * dpsw_clear_irq_status() - Clear a pending interrupt's status ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @irq_index: The interrupt index to configure ++ * @status: bits to clear (W1C) - one bit per cause: ++ * 0 = don't change ++ * 1 = clear status bit ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status); ++/** ++ * struct dpsw_attr - Structure representing DPSW attributes ++ * @id: DPSW object ID ++ * @version: DPSW version ++ * @options: Enable/Disable DPSW features ++ * @max_vlans: Maximum Number of VLANs ++ * @max_meters_per_if: Number of meters per interface ++ * @max_fdbs: Maximum Number of FDBs ++ * @max_fdb_entries: Number of FDB entries for default FDB table; ++ * 0 - indicates default 1024 entries. ++ * @fdb_aging_time: Default FDB aging time for default FDB table; ++ * 0 - indicates default 300 seconds ++ * @max_fdb_mc_groups: Number of multicast groups in each FDB table; ++ * 0 - indicates default 32 ++ * @mem_size: DPSW frame storage memory size ++ * @num_ifs: Number of interfaces ++ * @num_vlans: Current number of VLANs ++ * @num_fdbs: Current number of FDBs ++ * @component_type: Component type of this bridge ++ */ ++struct dpsw_attr { ++ int id; ++ /** ++ * struct version - DPSW version ++ * @major: DPSW major version ++ * @minor: DPSW minor version ++ */ ++ struct { ++ uint16_t major; ++ uint16_t minor; ++ } version; ++ uint64_t options; ++ uint16_t max_vlans; ++ uint8_t max_meters_per_if; ++ uint8_t max_fdbs; ++ uint16_t max_fdb_entries; ++ uint16_t fdb_aging_time; ++ uint16_t max_fdb_mc_groups; ++ uint16_t num_ifs; ++ uint16_t mem_size; ++ uint16_t num_vlans; ++ uint8_t num_fdbs; ++ enum dpsw_component_type component_type; ++}; ++ ++/** ++ * dpsw_get_attributes() - Retrieve DPSW attributes ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @attr: Returned DPSW attributes ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpsw_attr *attr); ++ ++/** ++ * dpsw_set_reflection_if() - Set target interface for reflected interfaces. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Id ++ * ++ * Only one reflection receive interface is allowed per switch ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_set_reflection_if(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id); ++ ++/** ++ * enum dpsw_action - Action selection for special/control frames ++ * @DPSW_ACTION_DROP: Drop frame ++ * @DPSW_ACTION_REDIRECT: Redirect frame to control port ++ */ ++enum dpsw_action { ++ DPSW_ACTION_DROP = 0, ++ DPSW_ACTION_REDIRECT = 1 ++}; ++ ++/** ++ * Enable auto-negotiation ++ */ ++#define DPSW_LINK_OPT_AUTONEG 0x0000000000000001ULL ++/** ++ * Enable half-duplex mode ++ */ ++#define DPSW_LINK_OPT_HALF_DUPLEX 0x0000000000000002ULL ++/** ++ * Enable pause frames ++ */ ++#define DPSW_LINK_OPT_PAUSE 0x0000000000000004ULL ++/** ++ * Enable a-symmetric pause frames ++ */ ++#define DPSW_LINK_OPT_ASYM_PAUSE 0x0000000000000008ULL ++ ++/** ++ * struct dpsw_link_cfg - Structure representing DPSW link configuration ++ * @rate: Rate ++ * @options: Mask of available options; use 'DPSW_LINK_OPT_' values ++ */ ++struct dpsw_link_cfg { ++ uint32_t rate; ++ uint64_t options; ++}; ++ ++/** ++ * dpsw_if_set_link_cfg() - set the link configuration. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: interface id ++ * @cfg: Link configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_set_link_cfg(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ struct dpsw_link_cfg *cfg); ++/** ++ * struct dpsw_link_state - Structure representing DPSW link state ++ * @rate: Rate ++ * @options: Mask of available options; use 'DPSW_LINK_OPT_' values ++ * @up: 0 - covers two cases: down and disconnected, 1 - up ++ */ ++struct dpsw_link_state { ++ uint32_t rate; ++ uint64_t options; ++ int up; ++}; ++ ++/** ++ * dpsw_if_get_link_state - Return the link state ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: interface id ++ * @state: link state 1 - linkup, 0 - link down or disconnected ++ * ++ * @returns '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_get_link_state(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ struct dpsw_link_state *state); ++ ++/** ++ * dpsw_if_set_flooding() - Enable Disable flooding for particular interface ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @en: 1 - enable, 0 - disable ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_set_flooding(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ int en); ++ ++/** ++ * dpsw_if_set_broadcast() - Enable/disable broadcast for particular interface ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @en: 1 - enable, 0 - disable ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_set_broadcast(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ int en); ++ ++/** ++ * dpsw_if_set_multicast() - Enable/disable multicast for particular interface ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @en: 1 - enable, 0 - disable ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_set_multicast(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ int en); ++ ++/** ++ * struct dpsw_tci_cfg - Tag Contorl Information (TCI) configuration ++ * @pcp: Priority Code Point (PCP): a 3-bit field which refers ++ * to the IEEE 802.1p priority ++ * @dei: Drop Eligible Indicator (DEI): a 1-bit field. May be used ++ * separately or in conjunction with PCP to indicate frames ++ * eligible to be dropped in the presence of congestion ++ * @vlan_id: VLAN Identifier (VID): a 12-bit field specifying the VLAN ++ * to which the frame belongs. The hexadecimal values ++ * of 0x000 and 0xFFF are reserved; ++ * all other values may be used as VLAN identifiers, ++ * allowing up to 4,094 VLANs ++ */ ++struct dpsw_tci_cfg { ++ uint8_t pcp; ++ uint8_t dei; ++ uint16_t vlan_id; ++}; ++ ++/** ++ * dpsw_if_set_tci() - Set default VLAN Tag Control Information (TCI) ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @cfg: Tag Control Information Configuration ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_set_tci(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpsw_tci_cfg *cfg); ++ ++/** ++ * dpsw_if_get_tci() - Get default VLAN Tag Control Information (TCI) ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @cfg: Tag Control Information Configuration ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_get_tci(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ struct dpsw_tci_cfg *cfg); ++ ++/** ++ * enum dpsw_stp_state - Spanning Tree Protocol (STP) states ++ * @DPSW_STP_STATE_BLOCKING: Blocking state ++ * @DPSW_STP_STATE_LISTENING: Listening state ++ * @DPSW_STP_STATE_LEARNING: Learning state ++ * @DPSW_STP_STATE_FORWARDING: Forwarding state ++ * ++ */ ++enum dpsw_stp_state { ++ DPSW_STP_STATE_BLOCKING = 0, ++ DPSW_STP_STATE_LISTENING = 1, ++ DPSW_STP_STATE_LEARNING = 2, ++ DPSW_STP_STATE_FORWARDING = 3 ++}; ++ ++/** ++ * struct dpsw_stp_cfg - Spanning Tree Protocol (STP) Configuration ++ * @vlan_id: VLAN ID STP state ++ * @state: STP state ++ */ ++struct dpsw_stp_cfg { ++ uint16_t vlan_id; ++ enum dpsw_stp_state state; ++}; ++ ++/** ++ * dpsw_if_set_stp() - Function sets Spanning Tree Protocol (STP) state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @cfg: STP State configuration parameters ++ * ++ * The following STP states are supported - ++ * blocking, listening, learning, forwarding and disabled. ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_set_stp(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpsw_stp_cfg *cfg); ++ ++/** ++ * enum dpsw_accepted_frames - Types of frames to accept ++ * @DPSW_ADMIT_ALL: The device accepts VLAN tagged, untagged and ++ * priority tagged frames ++ * @DPSW_ADMIT_ONLY_VLAN_TAGGED: The device discards untagged frames or ++ * Priority-Tagged frames received on this interface. ++ * ++ */ ++enum dpsw_accepted_frames { ++ DPSW_ADMIT_ALL = 1, ++ DPSW_ADMIT_ONLY_VLAN_TAGGED = 3 ++}; ++ ++/** ++ * struct dpsw_accepted_frames_cfg - Types of frames to accept configuration ++ * @type: Defines ingress accepted frames ++ * @unaccept_act: When a frame is not accepted, it may be discarded or ++ * redirected to control interface depending on this mode ++ */ ++struct dpsw_accepted_frames_cfg { ++ enum dpsw_accepted_frames type; ++ enum dpsw_action unaccept_act; ++}; ++ ++/** ++ * dpsw_if_set_accepted_frames() ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @cfg: Frame types configuration ++ * ++ * When is admit_only_vlan_tagged- the device will discard untagged ++ * frames or Priority-Tagged frames received on this interface. ++ * When admit_only_untagged- untagged frames or Priority-Tagged ++ * frames received on this interface will be accepted and assigned ++ * to a VID based on the PVID and VID Set for this interface. ++ * When admit_all - the device will accept VLAN tagged, untagged ++ * and priority tagged frames. ++ * The default is admit_all ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_set_accepted_frames(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpsw_accepted_frames_cfg *cfg); ++ ++/** ++ * dpsw_if_set_accept_all_vlan() ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @accept_all: Accept or drop frames having different VLAN ++ * ++ * When this is accept (FALSE), the device will discard incoming ++ * frames for VLANs that do not include this interface in its ++ * Member set. When accept (TRUE), the interface will accept all incoming frames ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_set_accept_all_vlan(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ int accept_all); ++ ++/** ++ * enum dpsw_counter - Counters types ++ * @DPSW_CNT_ING_FRAME: Counts ingress frames ++ * @DPSW_CNT_ING_BYTE: Counts ingress bytes ++ * @DPSW_CNT_ING_FLTR_FRAME: Counts filtered ingress frames ++ * @DPSW_CNT_ING_FRAME_DISCARD: Counts discarded ingress frame ++ * @DPSW_CNT_ING_MCAST_FRAME: Counts ingress multicast frames ++ * @DPSW_CNT_ING_MCAST_BYTE: Counts ingress multicast bytes ++ * @DPSW_CNT_ING_BCAST_FRAME: Counts ingress broadcast frames ++ * @DPSW_CNT_ING_BCAST_BYTES: Counts ingress broadcast bytes ++ * @DPSW_CNT_EGR_FRAME: Counts egress frames ++ * @DPSW_CNT_EGR_BYTE: Counts eEgress bytes ++ * @DPSW_CNT_EGR_FRAME_DISCARD: Counts discarded egress frames ++ * @DPSW_CNT_EGR_STP_FRAME_DISCARD: Counts egress STP discarded frames ++ */ ++enum dpsw_counter { ++ DPSW_CNT_ING_FRAME = 0x0, ++ DPSW_CNT_ING_BYTE = 0x1, ++ DPSW_CNT_ING_FLTR_FRAME = 0x2, ++ DPSW_CNT_ING_FRAME_DISCARD = 0x3, ++ DPSW_CNT_ING_MCAST_FRAME = 0x4, ++ DPSW_CNT_ING_MCAST_BYTE = 0x5, ++ DPSW_CNT_ING_BCAST_FRAME = 0x6, ++ DPSW_CNT_ING_BCAST_BYTES = 0x7, ++ DPSW_CNT_EGR_FRAME = 0x8, ++ DPSW_CNT_EGR_BYTE = 0x9, ++ DPSW_CNT_EGR_FRAME_DISCARD = 0xa, ++ DPSW_CNT_EGR_STP_FRAME_DISCARD = 0xb ++}; ++ ++/** ++ * dpsw_if_get_counter() - Get specific counter of particular interface ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @type: Counter type ++ * @counter: return value ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_get_counter(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ enum dpsw_counter type, ++ uint64_t *counter); ++ ++/** ++ * dpsw_if_set_counter() - Set specific counter of particular interface ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @type: Counter type ++ * @counter: New counter value ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_set_counter(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ enum dpsw_counter type, ++ uint64_t counter); ++ ++/** ++ * Maximum number of TC ++ */ ++#define DPSW_MAX_TC 8 ++ ++/** ++ * enum dpsw_priority_selector - User priority ++ * @DPSW_UP_PCP: Priority Code Point (PCP): a 3-bit field which ++ * refers to the IEEE 802.1p priority. ++ * @DPSW_UP_DSCP: Differentiated services Code Point (DSCP): 6 bit ++ * field from IP header ++ * ++ */ ++enum dpsw_priority_selector { ++ DPSW_UP_PCP = 0, ++ DPSW_UP_DSCP = 1 ++}; ++ ++/** ++ * enum dpsw_schedule_mode - Traffic classes scheduling ++ * @DPSW_SCHED_STRICT_PRIORITY: schedule strict priority ++ * @DPSW_SCHED_WEIGHTED: schedule based on token bucket created algorithm ++ */ ++enum dpsw_schedule_mode { ++ DPSW_SCHED_STRICT_PRIORITY, ++ DPSW_SCHED_WEIGHTED ++}; ++ ++/** ++ * struct dpsw_tx_schedule_cfg - traffic class configuration ++ * @mode: Strict or weight-based scheduling ++ * @delta_bandwidth: weighted Bandwidth in range from 100 to 10000 ++ */ ++struct dpsw_tx_schedule_cfg { ++ enum dpsw_schedule_mode mode; ++ uint16_t delta_bandwidth; ++}; ++ ++/** ++ * struct dpsw_tx_selection_cfg - Mapping user priority into traffic ++ * class configuration ++ * @priority_selector: Source for user priority regeneration ++ * @tc_id: The Regenerated User priority that the incoming ++ * User Priority is mapped to for this interface ++ * @tc_sched: Traffic classes configuration ++ */ ++struct dpsw_tx_selection_cfg { ++ enum dpsw_priority_selector priority_selector; ++ uint8_t tc_id[DPSW_MAX_PRIORITIES]; ++ struct dpsw_tx_schedule_cfg tc_sched[DPSW_MAX_TC]; ++}; ++ ++/** ++ * dpsw_if_set_tx_selection() - Function is used for mapping variety ++ * of frame fields ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @cfg: Traffic class mapping configuration ++ * ++ * Function is used for mapping variety of frame fields (DSCP, PCP) ++ * to Traffic Class. Traffic class is a number ++ * in the range from 0 to 7 ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_set_tx_selection(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpsw_tx_selection_cfg *cfg); ++ ++/** ++ * enum dpsw_reflection_filter - Filter type for frames to reflect ++ * @DPSW_REFLECTION_FILTER_INGRESS_ALL: Reflect all frames ++ * @DPSW_REFLECTION_FILTER_INGRESS_VLAN: Reflect only frames belong to ++ * particular VLAN defined by vid parameter ++ * ++ */ ++enum dpsw_reflection_filter { ++ DPSW_REFLECTION_FILTER_INGRESS_ALL = 0, ++ DPSW_REFLECTION_FILTER_INGRESS_VLAN = 1 ++}; ++ ++/** ++ * struct dpsw_reflection_cfg - Structure representing reflection information ++ * @filter: Filter type for frames to reflect ++ * @vlan_id: Vlan Id to reflect; valid only when filter type is ++ * DPSW_INGRESS_VLAN ++ */ ++struct dpsw_reflection_cfg { ++ enum dpsw_reflection_filter filter; ++ uint16_t vlan_id; ++}; ++ ++/** ++ * dpsw_if_add_reflection() - Identify interface to be reflected or mirrored ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @cfg: Reflection configuration ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_add_reflection(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpsw_reflection_cfg *cfg); ++ ++/** ++ * dpsw_if_remove_reflection() - Remove interface to be reflected or mirrored ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @cfg: Reflection configuration ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_remove_reflection(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpsw_reflection_cfg *cfg); ++ ++/** ++ * enum dpsw_metering_mode - Metering modes ++ * @DPSW_METERING_MODE_NONE: metering disabled ++ * @DPSW_METERING_MODE_RFC2698: RFC 2698 ++ * @DPSW_METERING_MODE_RFC4115: RFC 4115 ++ */ ++enum dpsw_metering_mode { ++ DPSW_METERING_MODE_NONE = 0, ++ DPSW_METERING_MODE_RFC2698, ++ DPSW_METERING_MODE_RFC4115 ++}; ++ ++/** ++ * enum dpsw_metering_unit - Metering count ++ * @DPSW_METERING_UNIT_BYTES: count bytes ++ * @DPSW_METERING_UNIT_FRAMES: count frames ++ */ ++enum dpsw_metering_unit { ++ DPSW_METERING_UNIT_BYTES = 0, ++ DPSW_METERING_UNIT_FRAMES ++}; ++ ++/** ++ * struct dpsw_metering_cfg - Metering configuration ++ * @mode: metering modes ++ * @units: Bytes or frame units ++ * @cir: Committed information rate (CIR) in Kbits/s ++ * @eir: Peak information rate (PIR) Kbit/s rfc2698 ++ * Excess information rate (EIR) Kbit/s rfc4115 ++ * @cbs: Committed burst size (CBS) in bytes ++ * @ebs: Peak burst size (PBS) in bytes for rfc2698 ++ * Excess bust size (EBS) in bytes rfc4115 ++ * ++ */ ++struct dpsw_metering_cfg { ++ enum dpsw_metering_mode mode; ++ enum dpsw_metering_unit units; ++ uint32_t cir; ++ uint32_t eir; ++ uint32_t cbs; ++ uint32_t ebs; ++}; ++ ++/** ++ * dpsw_if_set_flooding_metering() - Set flooding metering ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @cfg: Metering parameters ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_set_flooding_metering(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpsw_metering_cfg *cfg); ++ ++/** ++ * dpsw_if_set_metering() - Set interface metering for flooding ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @tc_id: Traffic class ID ++ * @cfg: Metering parameters ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_set_metering(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ uint8_t tc_id, ++ const struct dpsw_metering_cfg *cfg); ++ ++/** ++ * enum dpsw_early_drop_unit - DPSW early drop unit ++ * @DPSW_EARLY_DROP_UNIT_BYTE: count bytes ++ * @DPSW_EARLY_DROP_UNIT_FRAMES: count frames ++ */ ++enum dpsw_early_drop_unit { ++ DPSW_EARLY_DROP_UNIT_BYTE = 0, ++ DPSW_EARLY_DROP_UNIT_FRAMES ++}; ++ ++/** ++ * enum dpsw_early_drop_mode - DPSW early drop mode ++ * @DPSW_EARLY_DROP_MODE_NONE: early drop is disabled ++ * @DPSW_EARLY_DROP_MODE_TAIL: early drop in taildrop mode ++ * @DPSW_EARLY_DROP_MODE_WRED: early drop in WRED mode ++ */ ++enum dpsw_early_drop_mode { ++ DPSW_EARLY_DROP_MODE_NONE = 0, ++ DPSW_EARLY_DROP_MODE_TAIL, ++ DPSW_EARLY_DROP_MODE_WRED ++}; ++ ++/** ++ * struct dpsw_wred_cfg - WRED configuration ++ * @max_threshold: maximum threshold that packets may be discarded. Above this ++ * threshold all packets are discarded; must be less than 2^39; ++ * approximated to be expressed as (x+256)*2^(y-1) due to HW ++ * implementation. ++ * @min_threshold: minimum threshold that packets may be discarded at ++ * @drop_probability: probability that a packet will be discarded (1-100, ++ * associated with the maximum threshold) ++ */ ++struct dpsw_wred_cfg { ++ uint64_t min_threshold; ++ uint64_t max_threshold; ++ uint8_t drop_probability; ++}; ++ ++/** ++ * struct dpsw_early_drop_cfg - early-drop configuration ++ * @drop_mode: drop mode ++ * @units: count units ++ * @yellow: WRED - 'yellow' configuration ++ * @green: WRED - 'green' configuration ++ * @tail_drop_threshold: tail drop threshold ++ */ ++struct dpsw_early_drop_cfg { ++ enum dpsw_early_drop_mode drop_mode; ++ enum dpsw_early_drop_unit units; ++ struct dpsw_wred_cfg yellow; ++ struct dpsw_wred_cfg green; ++ uint32_t tail_drop_threshold; ++}; ++ ++/** ++ * dpsw_prepare_early_drop() - Prepare an early drop for setting in to interface ++ * @cfg: Early-drop configuration ++ * @early_drop_buf: Zeroed 256 bytes of memory before mapping it to DMA ++ * ++ * This function has to be called before dpsw_if_tc_set_early_drop ++ * ++ */ ++void dpsw_prepare_early_drop(const struct dpsw_early_drop_cfg *cfg, ++ uint8_t *early_drop_buf); ++ ++/** ++ * dpsw_if_set_early_drop() - Set interface traffic class early-drop ++ * configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @tc_id: Traffic class selection (0-7) ++ * @early_drop_iova: I/O virtual address of 64 bytes; ++ * Must be cacheline-aligned and DMA-able memory ++ * ++ * warning: Before calling this function, call dpsw_prepare_if_tc_early_drop() ++ * to prepare the early_drop_iova parameter ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpsw_if_set_early_drop(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ uint8_t tc_id, ++ uint64_t early_drop_iova); ++ ++/** ++ * struct dpsw_custom_tpid_cfg - Structure representing tag Protocol identifier ++ * @tpid: An additional tag protocol identifier ++ */ ++struct dpsw_custom_tpid_cfg { ++ uint16_t tpid; ++}; ++ ++/** ++ * dpsw_add_custom_tpid() - API Configures a distinct Ethernet type value ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @cfg: Tag Protocol identifier ++ * ++ * API Configures a distinct Ethernet type value (or TPID value) ++ * to indicate a VLAN tag in addition to the common ++ * TPID values 0x8100 and 0x88A8. ++ * Two additional TPID's are supported ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_add_custom_tpid(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpsw_custom_tpid_cfg *cfg); ++ ++/** ++ * dpsw_remove_custom_tpid - API removes a distinct Ethernet type value ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @cfg: Tag Protocol identifier ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_remove_custom_tpid(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpsw_custom_tpid_cfg *cfg); ++ ++/** ++ * dpsw_if_enable() - Enable Interface ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id); ++ ++/** ++ * dpsw_if_disable() - Disable Interface ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id); ++ ++/** ++ * struct dpsw_if_attr - Structure representing DPSW interface attributes ++ * @num_tcs: Number of traffic classes ++ * @rate: Transmit rate in bits per second ++ * @options: Interface configuration options (bitmap) ++ * @enabled: Indicates if interface is enabled ++ * @accept_all_vlan: The device discards/accepts incoming frames ++ * for VLANs that do not include this interface ++ * @admit_untagged: When set to 'DPSW_ADMIT_ONLY_VLAN_TAGGED', the device ++ * discards untagged frames or priority-tagged frames received on ++ * this interface; ++ * When set to 'DPSW_ADMIT_ALL', untagged frames or priority- ++ * tagged frames received on this interface are accepted ++ * @qdid: control frames transmit qdid ++ */ ++struct dpsw_if_attr { ++ uint8_t num_tcs; ++ uint32_t rate; ++ uint32_t options; ++ int enabled; ++ int accept_all_vlan; ++ enum dpsw_accepted_frames admit_untagged; ++ uint16_t qdid; ++}; ++ ++/** ++ * dpsw_if_get_attributes() - Function obtains attributes of interface ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @attr: Returned interface attributes ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ struct dpsw_if_attr *attr); ++ ++/** ++ * dpsw_if_set_max_frame_length() - Set Maximum Receive frame length. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @frame_length: Maximum Frame Length ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_set_max_frame_length(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ uint16_t frame_length); ++ ++/** ++ * dpsw_if_get_max_frame_length() - Get Maximum Receive frame length. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @frame_length: Returned maximum Frame Length ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_get_max_frame_length(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ uint16_t *frame_length); ++ ++/** ++ * struct dpsw_vlan_cfg - VLAN Configuration ++ * @fdb_id: Forwarding Data Base ++ */ ++struct dpsw_vlan_cfg { ++ uint16_t fdb_id; ++}; ++ ++/** ++ * dpsw_vlan_add() - Adding new VLAN to DPSW. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @vlan_id: VLAN Identifier ++ * @cfg: VLAN configuration ++ * ++ * Only VLAN ID and FDB ID are required parameters here. ++ * 12 bit VLAN ID is defined in IEEE802.1Q. ++ * Adding a duplicate VLAN ID is not allowed. ++ * FDB ID can be shared across multiple VLANs. Shared learning ++ * is obtained by calling dpsw_vlan_add for multiple VLAN IDs ++ * with same fdb_id ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_vlan_add(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ const struct dpsw_vlan_cfg *cfg); ++ ++/** ++ * struct dpsw_vlan_if_cfg - Set of VLAN Interfaces ++ * @num_ifs: The number of interfaces that are assigned to the egress ++ * list for this VLAN ++ * @if_id: The set of interfaces that are ++ * assigned to the egress list for this VLAN ++ */ ++struct dpsw_vlan_if_cfg { ++ uint16_t num_ifs; ++ uint16_t if_id[DPSW_MAX_IF]; ++}; ++ ++/** ++ * dpsw_vlan_add_if() - Adding a set of interfaces to an existing VLAN. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @vlan_id: VLAN Identifier ++ * @cfg: Set of interfaces to add ++ * ++ * It adds only interfaces not belonging to this VLAN yet, ++ * otherwise an error is generated and an entire command is ++ * ignored. This function can be called numerous times always ++ * providing required interfaces delta. ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_vlan_add_if(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ const struct dpsw_vlan_if_cfg *cfg); ++ ++/** ++ * dpsw_vlan_add_if_untagged() - Defining a set of interfaces that should be ++ * transmitted as untagged. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @vlan_id: VLAN Identifier ++ * @cfg: set of interfaces that should be transmitted as untagged ++ * ++ * These interfaces should already belong to this VLAN. ++ * By default all interfaces are transmitted as tagged. ++ * Providing un-existing interface or untagged interface that is ++ * configured untagged already generates an error and the entire ++ * command is ignored. ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_vlan_add_if_untagged(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ const struct dpsw_vlan_if_cfg *cfg); ++ ++/** ++ * dpsw_vlan_add_if_flooding() - Define a set of interfaces that should be ++ * included in flooding when frame with unknown destination ++ * unicast MAC arrived. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @vlan_id: VLAN Identifier ++ * @cfg: Set of interfaces that should be used for flooding ++ * ++ * These interfaces should belong to this VLAN. By default all ++ * interfaces are included into flooding list. Providing ++ * un-existing interface or an interface that already in the ++ * flooding list generates an error and the entire command is ++ * ignored. ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_vlan_add_if_flooding(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ const struct dpsw_vlan_if_cfg *cfg); ++ ++/** ++ * dpsw_vlan_remove_if() - Remove interfaces from an existing VLAN. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @vlan_id: VLAN Identifier ++ * @cfg: Set of interfaces that should be removed ++ * ++ * Interfaces must belong to this VLAN, otherwise an error ++ * is returned and an the command is ignored ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_vlan_remove_if(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ const struct dpsw_vlan_if_cfg *cfg); ++ ++/** ++ * dpsw_vlan_remove_if_untagged() - Define a set of interfaces that should be ++ * converted from transmitted as untagged to transmit as tagged. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @vlan_id: VLAN Identifier ++ * @cfg: set of interfaces that should be removed ++ * ++ * Interfaces provided by API have to belong to this VLAN and ++ * configured untagged, otherwise an error is returned and the ++ * command is ignored ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_vlan_remove_if_untagged(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ const struct dpsw_vlan_if_cfg *cfg); ++ ++/** ++ * dpsw_vlan_remove_if_flooding() - Define a set of interfaces that should be ++ * removed from the flooding list. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @vlan_id: VLAN Identifier ++ * @cfg: set of interfaces used for flooding ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_vlan_remove_if_flooding(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ const struct dpsw_vlan_if_cfg *cfg); ++ ++/** ++ * dpsw_vlan_remove() - Remove an entire VLAN ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @vlan_id: VLAN Identifier ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_vlan_remove(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id); ++ ++/** ++ * struct dpsw_vlan_attr - VLAN attributes ++ * @fdb_id: Associated FDB ID ++ * @num_ifs: Number of interfaces ++ * @num_untagged_ifs: Number of untagged interfaces ++ * @num_flooding_ifs: Number of flooding interfaces ++ */ ++struct dpsw_vlan_attr { ++ uint16_t fdb_id; ++ uint16_t num_ifs; ++ uint16_t num_untagged_ifs; ++ uint16_t num_flooding_ifs; ++}; ++ ++/** ++ * dpsw_vlan_get_attributes() - Get VLAN attributes ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @vlan_id: VLAN Identifier ++ * @attr: Returned DPSW attributes ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_vlan_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ struct dpsw_vlan_attr *attr); ++ ++/** ++ * dpsw_vlan_get_if() - Get interfaces belong to this VLAN ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @vlan_id: VLAN Identifier ++ * @cfg: Returned set of interfaces belong to this VLAN ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_vlan_get_if(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ struct dpsw_vlan_if_cfg *cfg); ++ ++/** ++ * dpsw_vlan_get_if_flooding() - Get interfaces used in flooding for this VLAN ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @vlan_id: VLAN Identifier ++ * @cfg: Returned set of flooding interfaces ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_vlan_get_if_flooding(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ struct dpsw_vlan_if_cfg *cfg); ++ ++/** ++ * dpsw_vlan_get_if_untagged() - Get interfaces that should be transmitted as ++ * untagged ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @vlan_id: VLAN Identifier ++ * @cfg: Returned set of untagged interfaces ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_vlan_get_if_untagged(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ struct dpsw_vlan_if_cfg *cfg); ++ ++/** ++ * struct dpsw_fdb_cfg - FDB Configuration ++ * @num_fdb_entries: Number of FDB entries ++ * @fdb_aging_time: Aging time in seconds ++ */ ++struct dpsw_fdb_cfg { ++ uint16_t num_fdb_entries; ++ uint16_t fdb_aging_time; ++}; ++ ++/** ++ * dpsw_fdb_add() - Add FDB to switch and Returns handle to FDB table for ++ * the reference ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @fdb_id: Returned Forwarding Database Identifier ++ * @cfg: FDB Configuration ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_fdb_add(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t *fdb_id, ++ const struct dpsw_fdb_cfg *cfg); ++ ++/** ++ * dpsw_fdb_remove() - Remove FDB from switch ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @fdb_id: Forwarding Database Identifier ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_fdb_remove(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t fdb_id); ++ ++/** ++ * enum dpsw_fdb_entry_type - FDB Entry type - Static/Dynamic ++ * @DPSW_FDB_ENTRY_STATIC: Static entry ++ * @DPSW_FDB_ENTRY_DINAMIC: Dynamic entry ++ */ ++enum dpsw_fdb_entry_type { ++ DPSW_FDB_ENTRY_STATIC = 0, ++ DPSW_FDB_ENTRY_DINAMIC = 1 ++}; ++ ++/** ++ * struct dpsw_fdb_unicast_cfg - Unicast entry configuration ++ * @type: Select static or dynamic entry ++ * @mac_addr: MAC address ++ * @if_egress: Egress interface ID ++ */ ++struct dpsw_fdb_unicast_cfg { ++ enum dpsw_fdb_entry_type type; ++ uint8_t mac_addr[6]; ++ uint16_t if_egress; ++}; ++ ++/** ++ * dpsw_fdb_add_unicast() - Function adds an unicast entry into MAC lookup table ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @fdb_id: Forwarding Database Identifier ++ * @cfg: Unicast entry configuration ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_fdb_add_unicast(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t fdb_id, ++ const struct dpsw_fdb_unicast_cfg *cfg); ++ ++/** ++ * dpsw_fdb_get_unicast() - Get unicast entry from MAC lookup table by ++ * unicast Ethernet address ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @fdb_id: Forwarding Database Identifier ++ * @cfg: Returned unicast entry configuration ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_fdb_get_unicast(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t fdb_id, ++ struct dpsw_fdb_unicast_cfg *cfg); ++ ++/** ++ * dpsw_fdb_remove_unicast() - removes an entry from MAC lookup table ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @fdb_id: Forwarding Database Identifier ++ * @cfg: Unicast entry configuration ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_fdb_remove_unicast(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t fdb_id, ++ const struct dpsw_fdb_unicast_cfg *cfg); ++ ++/** ++ * struct dpsw_fdb_multicast_cfg - Multi-cast entry configuration ++ * @type: Select static or dynamic entry ++ * @mac_addr: MAC address ++ * @num_ifs: Number of external and internal interfaces ++ * @if_id: Egress interface IDs ++ */ ++struct dpsw_fdb_multicast_cfg { ++ enum dpsw_fdb_entry_type type; ++ uint8_t mac_addr[6]; ++ uint16_t num_ifs; ++ uint16_t if_id[DPSW_MAX_IF]; ++}; ++ ++/** ++ * dpsw_fdb_add_multicast() - Add a set of egress interfaces to multi-cast group ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @fdb_id: Forwarding Database Identifier ++ * @cfg: Multicast entry configuration ++ * ++ * If group doesn't exist, it will be created. ++ * It adds only interfaces not belonging to this multicast group ++ * yet, otherwise error will be generated and the command is ++ * ignored. ++ * This function may be called numerous times always providing ++ * required interfaces delta. ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_fdb_add_multicast(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t fdb_id, ++ const struct dpsw_fdb_multicast_cfg *cfg); ++ ++/** ++ * dpsw_fdb_get_multicast() - Reading multi-cast group by multi-cast Ethernet ++ * address. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @fdb_id: Forwarding Database Identifier ++ * @cfg: Returned multicast entry configuration ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_fdb_get_multicast(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t fdb_id, ++ struct dpsw_fdb_multicast_cfg *cfg); ++ ++/** ++ * dpsw_fdb_remove_multicast() - Removing interfaces from an existing multicast ++ * group. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @fdb_id: Forwarding Database Identifier ++ * @cfg: Multicast entry configuration ++ * ++ * Interfaces provided by this API have to exist in the group, ++ * otherwise an error will be returned and an entire command ++ * ignored. If there is no interface left in the group, ++ * an entire group is deleted ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_fdb_remove_multicast(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t fdb_id, ++ const struct dpsw_fdb_multicast_cfg *cfg); ++ ++/** ++ * enum dpsw_fdb_learning_mode - Auto-learning modes ++ * @DPSW_FDB_LEARNING_MODE_DIS: Disable Auto-learning ++ * @DPSW_FDB_LEARNING_MODE_HW: Enable HW auto-Learning ++ * @DPSW_FDB_LEARNING_MODE_NON_SECURE: Enable None secure learning by CPU ++ * @DPSW_FDB_LEARNING_MODE_SECURE: Enable secure learning by CPU ++ * ++ * NONE - SECURE LEARNING ++ * SMAC found DMAC found CTLU Action ++ * v v Forward frame to ++ * 1. DMAC destination ++ * - v Forward frame to ++ * 1. DMAC destination ++ * 2. Control interface ++ * v - Forward frame to ++ * 1. Flooding list of interfaces ++ * - - Forward frame to ++ * 1. Flooding list of interfaces ++ * 2. Control interface ++ * SECURE LEARING ++ * SMAC found DMAC found CTLU Action ++ * v v Forward frame to ++ * 1. DMAC destination ++ * - v Forward frame to ++ * 1. Control interface ++ * v - Forward frame to ++ * 1. Flooding list of interfaces ++ * - - Forward frame to ++ * 1. Control interface ++ */ ++enum dpsw_fdb_learning_mode { ++ DPSW_FDB_LEARNING_MODE_DIS = 0, ++ DPSW_FDB_LEARNING_MODE_HW = 1, ++ DPSW_FDB_LEARNING_MODE_NON_SECURE = 2, ++ DPSW_FDB_LEARNING_MODE_SECURE = 3 ++}; ++ ++/** ++ * dpsw_fdb_set_learning_mode() - Define FDB learning mode ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @fdb_id: Forwarding Database Identifier ++ * @mode: learning mode ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_fdb_set_learning_mode(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t fdb_id, ++ enum dpsw_fdb_learning_mode mode); ++ ++/** ++ * struct dpsw_fdb_attr - FDB Attributes ++ * @max_fdb_entries: Number of FDB entries ++ * @fdb_aging_time: Aging time in seconds ++ * @learning_mode: Learning mode ++ * @num_fdb_mc_groups: Current number of multicast groups ++ * @max_fdb_mc_groups: Maximum number of multicast groups ++ */ ++struct dpsw_fdb_attr { ++ uint16_t max_fdb_entries; ++ uint16_t fdb_aging_time; ++ enum dpsw_fdb_learning_mode learning_mode; ++ uint16_t num_fdb_mc_groups; ++ uint16_t max_fdb_mc_groups; ++}; ++ ++/** ++ * dpsw_fdb_get_attributes() - Get FDB attributes ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @fdb_id: Forwarding Database Identifier ++ * @attr: Returned FDB attributes ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_fdb_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t fdb_id, ++ struct dpsw_fdb_attr *attr); ++ ++/** ++ * struct dpsw_acl_cfg - ACL Configuration ++ * @max_entries: Number of FDB entries ++ */ ++struct dpsw_acl_cfg { ++ uint16_t max_entries; ++}; ++ ++/** ++ * struct dpsw_acl_fields - ACL fields. ++ * @l2_dest_mac: Destination MAC address: BPDU, Multicast, Broadcast, Unicast, ++ * slow protocols, MVRP, STP ++ * @l2_source_mac: Source MAC address ++ * @l2_tpid: Layer 2 (Ethernet) protocol type, used to identify the following ++ * protocols: MPLS, PTP, PFC, ARP, Jumbo frames, LLDP, IEEE802.1ae, ++ * Q-in-Q, IPv4, IPv6, PPPoE ++ * @l2_pcp_dei: indicate which protocol is encapsulated in the payload ++ * @l2_vlan_id: layer 2 VLAN ID ++ * @l2_ether_type: layer 2 Ethernet type ++ * @l3_dscp: Layer 3 differentiated services code point ++ * @l3_protocol: Tells the Network layer at the destination host, to which ++ * Protocol this packet belongs to. The following protocol are ++ * supported: ICMP, IGMP, IPv4 (encapsulation), TCP, IPv6 ++ * (encapsulation), GRE, PTP ++ * @l3_source_ip: Source IPv4 IP ++ * @l3_dest_ip: Destination IPv4 IP ++ * @l4_source_port: Source TCP/UDP Port ++ * @l4_dest_port: Destination TCP/UDP Port ++ */ ++struct dpsw_acl_fields { ++ uint8_t l2_dest_mac[6]; ++ uint8_t l2_source_mac[6]; ++ uint16_t l2_tpid; ++ uint8_t l2_pcp_dei; ++ uint16_t l2_vlan_id; ++ uint16_t l2_ether_type; ++ uint8_t l3_dscp; ++ uint8_t l3_protocol; ++ uint32_t l3_source_ip; ++ uint32_t l3_dest_ip; ++ uint16_t l4_source_port; ++ uint16_t l4_dest_port; ++}; ++ ++/** ++ * struct dpsw_acl_key - ACL key ++ * @match: Match fields ++ * @mask: Mask: b'1 - valid, b'0 don't care ++ */ ++struct dpsw_acl_key { ++ struct dpsw_acl_fields match; ++ struct dpsw_acl_fields mask; ++}; ++ ++/** ++ * enum dpsw_acl_action ++ * @DPSW_ACL_ACTION_DROP: Drop frame ++ * @DPSW_ACL_ACTION_REDIRECT: Redirect to certain port ++ * @DPSW_ACL_ACTION_ACCEPT: Accept frame ++ * @DPSW_ACL_ACTION_REDIRECT_TO_CTRL_IF: Redirect to control interface ++ */ ++enum dpsw_acl_action { ++ DPSW_ACL_ACTION_DROP, ++ DPSW_ACL_ACTION_REDIRECT, ++ DPSW_ACL_ACTION_ACCEPT, ++ DPSW_ACL_ACTION_REDIRECT_TO_CTRL_IF ++}; ++ ++/** ++ * struct dpsw_acl_result - ACL action ++ * @action: Action should be taken when ACL entry hit ++ * @if_id: Interface IDs to redirect frame. Valid only if redirect selected for ++ * action ++ */ ++struct dpsw_acl_result { ++ enum dpsw_acl_action action; ++ uint16_t if_id; ++}; ++ ++/** ++ * struct dpsw_acl_entry_cfg - ACL entry ++ * @key_iova: I/O virtual address of DMA-able memory filled with key after call ++ * to dpsw_acl_prepare_entry_cfg() ++ * @result: Required action when entry hit occurs ++ * @precedence: Precedence inside ACL 0 is lowest; This priority can not change ++ * during the lifetime of a Policy. It is user responsibility to ++ * space the priorities according to consequent rule additions. ++ */ ++struct dpsw_acl_entry_cfg { ++ uint64_t key_iova; ++ struct dpsw_acl_result result; ++ int precedence; ++}; ++ ++/** ++ * dpsw_acl_add() - Adds ACL to L2 switch. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @acl_id: Returned ACL ID, for the future reference ++ * @cfg: ACL configuration ++ * ++ * Create Access Control List. Multiple ACLs can be created and ++ * co-exist in L2 switch ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_acl_add(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t *acl_id, ++ const struct dpsw_acl_cfg *cfg); ++ ++/** ++ * dpsw_acl_remove() - Removes ACL from L2 switch. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @acl_id: ACL ID ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_acl_remove(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t acl_id); ++ ++/** ++ * dpsw_acl_prepare_entry_cfg() - Set an entry to ACL. ++ * @key: key ++ * @entry_cfg_buf: Zeroed 256 bytes of memory before mapping it to DMA ++ * ++ * This function has to be called before adding or removing acl_entry ++ * ++ */ ++void dpsw_acl_prepare_entry_cfg(const struct dpsw_acl_key *key, ++ uint8_t *entry_cfg_buf); ++ ++/** ++ * dpsw_acl_add_entry() - Adds an entry to ACL. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @acl_id: ACL ID ++ * @cfg: entry configuration ++ * ++ * warning: This function has to be called after dpsw_acl_set_entry_cfg() ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_acl_add_entry(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t acl_id, ++ const struct dpsw_acl_entry_cfg *cfg); ++ ++/** ++ * dpsw_acl_remove_entry() - Removes an entry from ACL. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @acl_id: ACL ID ++ * @cfg: entry configuration ++ * ++ * warning: This function has to be called after dpsw_acl_set_entry_cfg() ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_acl_remove_entry(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t acl_id, ++ const struct dpsw_acl_entry_cfg *cfg); ++ ++/** ++ * struct dpsw_acl_if_cfg - List of interfaces to Associate with ACL ++ * @num_ifs: Number of interfaces ++ * @if_id: List of interfaces ++ */ ++struct dpsw_acl_if_cfg { ++ uint16_t num_ifs; ++ uint16_t if_id[DPSW_MAX_IF]; ++}; ++ ++/** ++ * dpsw_acl_add_if() - Associate interface/interfaces with ACL. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @acl_id: ACL ID ++ * @cfg: interfaces list ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_acl_add_if(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t acl_id, ++ const struct dpsw_acl_if_cfg *cfg); ++ ++/** ++ * dpsw_acl_remove_if() - De-associate interface/interfaces from ACL. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @acl_id: ACL ID ++ * @cfg: interfaces list ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_acl_remove_if(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t acl_id, ++ const struct dpsw_acl_if_cfg *cfg); ++ ++/** ++ * struct dpsw_acl_attr - ACL Attributes ++ * @max_entries: Max number of ACL entries ++ * @num_entries: Number of used ACL entries ++ * @num_ifs: Number of interfaces associated with ACL ++ */ ++struct dpsw_acl_attr { ++ uint16_t max_entries; ++ uint16_t num_entries; ++ uint16_t num_ifs; ++}; ++ ++/** ++* dpsw_acl_get_attributes() - Get specific counter of particular interface ++* @mc_io: Pointer to MC portal's I/O object ++* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++* @token: Token of DPSW object ++* @acl_id: ACL Identifier ++* @attr: Returned ACL attributes ++* ++* Return: '0' on Success; Error code otherwise. ++*/ ++int dpsw_acl_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t acl_id, ++ struct dpsw_acl_attr *attr); ++/** ++* struct dpsw_ctrl_if_attr - Control interface attributes ++* @rx_fqid: Receive FQID ++* @rx_err_fqid: Receive error FQID ++* @tx_err_conf_fqid: Transmit error and confirmation FQID ++*/ ++struct dpsw_ctrl_if_attr { ++ uint32_t rx_fqid; ++ uint32_t rx_err_fqid; ++ uint32_t tx_err_conf_fqid; ++}; ++ ++/** ++* dpsw_ctrl_if_get_attributes() - Obtain control interface attributes ++* @mc_io: Pointer to MC portal's I/O object ++* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++* @token: Token of DPSW object ++* @attr: Returned control interface attributes ++* ++* Return: '0' on Success; Error code otherwise. ++*/ ++int dpsw_ctrl_if_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpsw_ctrl_if_attr *attr); ++ ++/** ++ * Maximum number of DPBP ++ */ ++#define DPSW_MAX_DPBP 8 ++ ++/** ++ * struct dpsw_ctrl_if_pools_cfg - Control interface buffer pools configuration ++ * @num_dpbp: Number of DPBPs ++ * @pools: Array of buffer pools parameters; The number of valid entries ++ * must match 'num_dpbp' value ++ */ ++struct dpsw_ctrl_if_pools_cfg { ++ uint8_t num_dpbp; ++ /** ++ * struct pools - Buffer pools parameters ++ * @dpbp_id: DPBP object ID ++ * @buffer_size: Buffer size ++ * @backup_pool: Backup pool ++ */ ++ struct { ++ int dpbp_id; ++ uint16_t buffer_size; ++ int backup_pool; ++ } pools[DPSW_MAX_DPBP]; ++}; ++ ++/** ++* dpsw_ctrl_if_set_pools() - Set control interface buffer pools ++* @mc_io: Pointer to MC portal's I/O object ++* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++* @token: Token of DPSW object ++* @cfg: buffer pools configuration ++* ++* Return: '0' on Success; Error code otherwise. ++*/ ++int dpsw_ctrl_if_set_pools(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpsw_ctrl_if_pools_cfg *cfg); ++ ++/** ++* dpsw_ctrl_if_enable() - Enable control interface ++* @mc_io: Pointer to MC portal's I/O object ++* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++* @token: Token of DPSW object ++* ++* Return: '0' on Success; Error code otherwise. ++*/ ++int dpsw_ctrl_if_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++* dpsw_ctrl_if_disable() - Function disables control interface ++* @mc_io: Pointer to MC portal's I/O object ++* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++* @token: Token of DPSW object ++* ++* Return: '0' on Success; Error code otherwise. ++*/ ++int dpsw_ctrl_if_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++#endif /* __FSL_DPSW_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpsw_cmd.h b/drivers/net/dpaa2/mc/fsl_dpsw_cmd.h +new file mode 100644 +index 0000000..c65fe38 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpsw_cmd.h +@@ -0,0 +1,916 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPSW_CMD_H ++#define __FSL_DPSW_CMD_H ++ ++/* DPSW Version */ ++#define DPSW_VER_MAJOR 7 ++#define DPSW_VER_MINOR 0 ++ ++/* Command IDs */ ++#define DPSW_CMDID_CLOSE 0x800 ++#define DPSW_CMDID_OPEN 0x802 ++#define DPSW_CMDID_CREATE 0x902 ++#define DPSW_CMDID_DESTROY 0x900 ++ ++#define DPSW_CMDID_ENABLE 0x002 ++#define DPSW_CMDID_DISABLE 0x003 ++#define DPSW_CMDID_GET_ATTR 0x004 ++#define DPSW_CMDID_RESET 0x005 ++#define DPSW_CMDID_IS_ENABLED 0x006 ++ ++#define DPSW_CMDID_SET_IRQ 0x010 ++#define DPSW_CMDID_GET_IRQ 0x011 ++#define DPSW_CMDID_SET_IRQ_ENABLE 0x012 ++#define DPSW_CMDID_GET_IRQ_ENABLE 0x013 ++#define DPSW_CMDID_SET_IRQ_MASK 0x014 ++#define DPSW_CMDID_GET_IRQ_MASK 0x015 ++#define DPSW_CMDID_GET_IRQ_STATUS 0x016 ++#define DPSW_CMDID_CLEAR_IRQ_STATUS 0x017 ++ ++#define DPSW_CMDID_SET_REFLECTION_IF 0x022 ++ ++#define DPSW_CMDID_ADD_CUSTOM_TPID 0x024 ++ ++#define DPSW_CMDID_REMOVE_CUSTOM_TPID 0x026 ++ ++#define DPSW_CMDID_IF_SET_TCI 0x030 ++#define DPSW_CMDID_IF_SET_STP 0x031 ++#define DPSW_CMDID_IF_SET_ACCEPTED_FRAMES 0x032 ++#define DPSW_CMDID_SET_IF_ACCEPT_ALL_VLAN 0x033 ++#define DPSW_CMDID_IF_GET_COUNTER 0x034 ++#define DPSW_CMDID_IF_SET_COUNTER 0x035 ++#define DPSW_CMDID_IF_SET_TX_SELECTION 0x036 ++#define DPSW_CMDID_IF_ADD_REFLECTION 0x037 ++#define DPSW_CMDID_IF_REMOVE_REFLECTION 0x038 ++#define DPSW_CMDID_IF_SET_FLOODING_METERING 0x039 ++#define DPSW_CMDID_IF_SET_METERING 0x03A ++#define DPSW_CMDID_IF_SET_EARLY_DROP 0x03B ++ ++#define DPSW_CMDID_IF_ENABLE 0x03D ++#define DPSW_CMDID_IF_DISABLE 0x03E ++ ++#define DPSW_CMDID_IF_GET_ATTR 0x042 ++ ++#define DPSW_CMDID_IF_SET_MAX_FRAME_LENGTH 0x044 ++#define DPSW_CMDID_IF_GET_MAX_FRAME_LENGTH 0x045 ++#define DPSW_CMDID_IF_GET_LINK_STATE 0x046 ++#define DPSW_CMDID_IF_SET_FLOODING 0x047 ++#define DPSW_CMDID_IF_SET_BROADCAST 0x048 ++#define DPSW_CMDID_IF_SET_MULTICAST 0x049 ++#define DPSW_CMDID_IF_GET_TCI 0x04A ++ ++#define DPSW_CMDID_IF_SET_LINK_CFG 0x04C ++ ++#define DPSW_CMDID_VLAN_ADD 0x060 ++#define DPSW_CMDID_VLAN_ADD_IF 0x061 ++#define DPSW_CMDID_VLAN_ADD_IF_UNTAGGED 0x062 ++#define DPSW_CMDID_VLAN_ADD_IF_FLOODING 0x063 ++#define DPSW_CMDID_VLAN_REMOVE_IF 0x064 ++#define DPSW_CMDID_VLAN_REMOVE_IF_UNTAGGED 0x065 ++#define DPSW_CMDID_VLAN_REMOVE_IF_FLOODING 0x066 ++#define DPSW_CMDID_VLAN_REMOVE 0x067 ++#define DPSW_CMDID_VLAN_GET_IF 0x068 ++#define DPSW_CMDID_VLAN_GET_IF_FLOODING 0x069 ++#define DPSW_CMDID_VLAN_GET_IF_UNTAGGED 0x06A ++#define DPSW_CMDID_VLAN_GET_ATTRIBUTES 0x06B ++ ++#define DPSW_CMDID_FDB_GET_MULTICAST 0x080 ++#define DPSW_CMDID_FDB_GET_UNICAST 0x081 ++#define DPSW_CMDID_FDB_ADD 0x082 ++#define DPSW_CMDID_FDB_REMOVE 0x083 ++#define DPSW_CMDID_FDB_ADD_UNICAST 0x084 ++#define DPSW_CMDID_FDB_REMOVE_UNICAST 0x085 ++#define DPSW_CMDID_FDB_ADD_MULTICAST 0x086 ++#define DPSW_CMDID_FDB_REMOVE_MULTICAST 0x087 ++#define DPSW_CMDID_FDB_SET_LEARNING_MODE 0x088 ++#define DPSW_CMDID_FDB_GET_ATTR 0x089 ++ ++#define DPSW_CMDID_ACL_ADD 0x090 ++#define DPSW_CMDID_ACL_REMOVE 0x091 ++#define DPSW_CMDID_ACL_ADD_ENTRY 0x092 ++#define DPSW_CMDID_ACL_REMOVE_ENTRY 0x093 ++#define DPSW_CMDID_ACL_ADD_IF 0x094 ++#define DPSW_CMDID_ACL_REMOVE_IF 0x095 ++#define DPSW_CMDID_ACL_GET_ATTR 0x096 ++ ++#define DPSW_CMDID_CTRL_IF_GET_ATTR 0x0A0 ++#define DPSW_CMDID_CTRL_IF_SET_POOLS 0x0A1 ++#define DPSW_CMDID_CTRL_IF_ENABLE 0x0A2 ++#define DPSW_CMDID_CTRL_IF_DISABLE 0x0A3 ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_OPEN(cmd, dpsw_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpsw_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_CREATE(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, cfg->num_ifs);\ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, cfg->adv.max_fdbs);\ ++ MC_CMD_OP(cmd, 0, 24, 8, uint8_t, cfg->adv.max_meters_per_if);\ ++ MC_CMD_OP(cmd, 0, 32, 4, enum dpsw_component_type, \ ++ cfg->adv.component_type);\ ++ MC_CMD_OP(cmd, 1, 0, 16, uint16_t, cfg->adv.max_vlans);\ ++ MC_CMD_OP(cmd, 1, 16, 16, uint16_t, cfg->adv.max_fdb_entries);\ ++ MC_CMD_OP(cmd, 1, 32, 16, uint16_t, cfg->adv.fdb_aging_time);\ ++ MC_CMD_OP(cmd, 1, 48, 16, uint16_t, cfg->adv.max_fdb_mc_groups);\ ++ MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->adv.options);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_IS_ENABLED(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, irq_index);\ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, irq_cfg->val);\ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\ ++ MC_CMD_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_GET_IRQ(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_GET_IRQ(cmd, type, irq_cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\ ++ MC_RSP_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, type); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_SET_IRQ_ENABLE(cmd, irq_index, enable_state) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, enable_state); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_GET_IRQ_ENABLE(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_GET_IRQ_ENABLE(cmd, enable_state) \ ++ MC_RSP_OP(cmd, 0, 0, 8, uint8_t, enable_state) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, mask); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_GET_IRQ_MASK(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_GET_IRQ_MASK(cmd, mask) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mask) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_GET_IRQ_STATUS(cmd, status) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, status) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_GET_ATTR(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 16, uint16_t, attr->num_ifs);\ ++ MC_RSP_OP(cmd, 0, 16, 8, uint8_t, attr->max_fdbs);\ ++ MC_RSP_OP(cmd, 0, 24, 8, uint8_t, attr->num_fdbs);\ ++ MC_RSP_OP(cmd, 0, 32, 16, uint16_t, attr->max_vlans);\ ++ MC_RSP_OP(cmd, 0, 48, 16, uint16_t, attr->num_vlans);\ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->version.major);\ ++ MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->version.minor);\ ++ MC_RSP_OP(cmd, 1, 32, 16, uint16_t, attr->max_fdb_entries);\ ++ MC_RSP_OP(cmd, 1, 48, 16, uint16_t, attr->fdb_aging_time);\ ++ MC_RSP_OP(cmd, 2, 0, 32, int, attr->id);\ ++ MC_RSP_OP(cmd, 2, 32, 16, uint16_t, attr->mem_size);\ ++ MC_RSP_OP(cmd, 2, 48, 16, uint16_t, attr->max_fdb_mc_groups);\ ++ MC_RSP_OP(cmd, 3, 0, 64, uint64_t, attr->options);\ ++ MC_RSP_OP(cmd, 4, 0, 8, uint8_t, attr->max_meters_per_if);\ ++ MC_RSP_OP(cmd, 4, 8, 4, enum dpsw_component_type, \ ++ attr->component_type);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_SET_REFLECTION_IF(cmd, if_id) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_SET_FLOODING(cmd, if_id, en) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 16, 1, int, en);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_SET_BROADCAST(cmd, if_id, en) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 16, 1, int, en);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_SET_MULTICAST(cmd, if_id, en) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 16, 1, int, en);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_SET_TCI(cmd, if_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 16, 12, uint16_t, cfg->vlan_id);\ ++ MC_CMD_OP(cmd, 0, 28, 1, uint8_t, cfg->dei);\ ++ MC_CMD_OP(cmd, 0, 29, 3, uint8_t, cfg->pcp);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_GET_TCI(cmd, if_id) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_IF_GET_TCI(cmd, cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 16, 16, uint16_t, cfg->vlan_id);\ ++ MC_RSP_OP(cmd, 0, 32, 8, uint8_t, cfg->dei);\ ++ MC_RSP_OP(cmd, 0, 40, 8, uint8_t, cfg->pcp);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_SET_STP(cmd, if_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->vlan_id);\ ++ MC_CMD_OP(cmd, 0, 32, 4, enum dpsw_stp_state, cfg->state);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_SET_ACCEPTED_FRAMES(cmd, if_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 16, 4, enum dpsw_accepted_frames, cfg->type);\ ++ MC_CMD_OP(cmd, 0, 20, 4, enum dpsw_action, cfg->unaccept_act);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_SET_ACCEPT_ALL_VLAN(cmd, if_id, accept_all) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 16, 1, int, accept_all);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_GET_COUNTER(cmd, if_id, type) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 16, 5, enum dpsw_counter, type);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_IF_GET_COUNTER(cmd, counter) \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, counter) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_SET_COUNTER(cmd, if_id, type, counter) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 16, 5, enum dpsw_counter, type);\ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, counter);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_SET_TX_SELECTION(cmd, if_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 16, 3, enum dpsw_priority_selector, \ ++ cfg->priority_selector);\ ++ MC_CMD_OP(cmd, 1, 0, 8, uint8_t, cfg->tc_id[0]);\ ++ MC_CMD_OP(cmd, 1, 8, 8, uint8_t, cfg->tc_id[1]);\ ++ MC_CMD_OP(cmd, 1, 16, 8, uint8_t, cfg->tc_id[2]);\ ++ MC_CMD_OP(cmd, 1, 24, 8, uint8_t, cfg->tc_id[3]);\ ++ MC_CMD_OP(cmd, 1, 32, 8, uint8_t, cfg->tc_id[4]);\ ++ MC_CMD_OP(cmd, 1, 40, 8, uint8_t, cfg->tc_id[5]);\ ++ MC_CMD_OP(cmd, 1, 48, 8, uint8_t, cfg->tc_id[6]);\ ++ MC_CMD_OP(cmd, 1, 56, 8, uint8_t, cfg->tc_id[7]);\ ++ MC_CMD_OP(cmd, 2, 0, 16, uint16_t, cfg->tc_sched[0].delta_bandwidth);\ ++ MC_CMD_OP(cmd, 2, 16, 4, enum dpsw_schedule_mode, \ ++ cfg->tc_sched[0].mode);\ ++ MC_CMD_OP(cmd, 2, 32, 16, uint16_t, cfg->tc_sched[1].delta_bandwidth);\ ++ MC_CMD_OP(cmd, 2, 48, 4, enum dpsw_schedule_mode, \ ++ cfg->tc_sched[1].mode);\ ++ MC_CMD_OP(cmd, 3, 0, 16, uint16_t, cfg->tc_sched[2].delta_bandwidth);\ ++ MC_CMD_OP(cmd, 3, 16, 4, enum dpsw_schedule_mode, \ ++ cfg->tc_sched[2].mode);\ ++ MC_CMD_OP(cmd, 3, 32, 16, uint16_t, cfg->tc_sched[3].delta_bandwidth);\ ++ MC_CMD_OP(cmd, 3, 48, 4, enum dpsw_schedule_mode, \ ++ cfg->tc_sched[3].mode);\ ++ MC_CMD_OP(cmd, 4, 0, 16, uint16_t, cfg->tc_sched[4].delta_bandwidth);\ ++ MC_CMD_OP(cmd, 4, 16, 4, enum dpsw_schedule_mode, \ ++ cfg->tc_sched[4].mode);\ ++ MC_CMD_OP(cmd, 4, 32, 16, uint16_t, cfg->tc_sched[5].delta_bandwidth);\ ++ MC_CMD_OP(cmd, 4, 48, 4, enum dpsw_schedule_mode, \ ++ cfg->tc_sched[5].mode);\ ++ MC_CMD_OP(cmd, 5, 0, 16, uint16_t, cfg->tc_sched[6].delta_bandwidth);\ ++ MC_CMD_OP(cmd, 5, 16, 4, enum dpsw_schedule_mode, \ ++ cfg->tc_sched[6].mode);\ ++ MC_CMD_OP(cmd, 5, 32, 16, uint16_t, cfg->tc_sched[7].delta_bandwidth);\ ++ MC_CMD_OP(cmd, 5, 48, 4, enum dpsw_schedule_mode, \ ++ cfg->tc_sched[7].mode);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_ADD_REFLECTION(cmd, if_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->vlan_id);\ ++ MC_CMD_OP(cmd, 0, 32, 2, enum dpsw_reflection_filter, cfg->filter);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_REMOVE_REFLECTION(cmd, if_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->vlan_id);\ ++ MC_CMD_OP(cmd, 0, 32, 2, enum dpsw_reflection_filter, cfg->filter);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_SET_FLOODING_METERING(cmd, if_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 24, 4, enum dpsw_metering_mode, cfg->mode);\ ++ MC_CMD_OP(cmd, 0, 28, 4, enum dpsw_metering_unit, cfg->units);\ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, cfg->cir);\ ++ MC_CMD_OP(cmd, 1, 0, 32, uint32_t, cfg->eir);\ ++ MC_CMD_OP(cmd, 1, 32, 32, uint32_t, cfg->cbs);\ ++ MC_CMD_OP(cmd, 2, 0, 32, uint32_t, cfg->ebs);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_SET_METERING(cmd, if_id, tc_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, tc_id);\ ++ MC_CMD_OP(cmd, 0, 24, 4, enum dpsw_metering_mode, cfg->mode);\ ++ MC_CMD_OP(cmd, 0, 28, 4, enum dpsw_metering_unit, cfg->units);\ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, cfg->cir);\ ++ MC_CMD_OP(cmd, 1, 0, 32, uint32_t, cfg->eir);\ ++ MC_CMD_OP(cmd, 1, 32, 32, uint32_t, cfg->cbs);\ ++ MC_CMD_OP(cmd, 2, 0, 32, uint32_t, cfg->ebs);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_PREP_EARLY_DROP(ext, cfg) \ ++do { \ ++ MC_PREP_OP(ext, 0, 0, 2, enum dpsw_early_drop_mode, cfg->drop_mode); \ ++ MC_PREP_OP(ext, 0, 2, 2, \ ++ enum dpsw_early_drop_unit, cfg->units); \ ++ MC_PREP_OP(ext, 0, 32, 32, uint32_t, cfg->tail_drop_threshold); \ ++ MC_PREP_OP(ext, 1, 0, 8, uint8_t, cfg->green.drop_probability); \ ++ MC_PREP_OP(ext, 2, 0, 64, uint64_t, cfg->green.max_threshold); \ ++ MC_PREP_OP(ext, 3, 0, 64, uint64_t, cfg->green.min_threshold); \ ++ MC_PREP_OP(ext, 5, 0, 8, uint8_t, cfg->yellow.drop_probability);\ ++ MC_PREP_OP(ext, 6, 0, 64, uint64_t, cfg->yellow.max_threshold); \ ++ MC_PREP_OP(ext, 7, 0, 64, uint64_t, cfg->yellow.min_threshold); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_EXT_EARLY_DROP(ext, cfg) \ ++do { \ ++ MC_EXT_OP(ext, 0, 0, 2, enum dpsw_early_drop_mode, cfg->drop_mode); \ ++ MC_EXT_OP(ext, 0, 2, 2, \ ++ enum dpsw_early_drop_unit, cfg->units); \ ++ MC_EXT_OP(ext, 0, 32, 32, uint32_t, cfg->tail_drop_threshold); \ ++ MC_EXT_OP(ext, 1, 0, 8, uint8_t, cfg->green.drop_probability); \ ++ MC_EXT_OP(ext, 2, 0, 64, uint64_t, cfg->green.max_threshold); \ ++ MC_EXT_OP(ext, 3, 0, 64, uint64_t, cfg->green.min_threshold); \ ++ MC_EXT_OP(ext, 5, 0, 8, uint8_t, cfg->yellow.drop_probability);\ ++ MC_EXT_OP(ext, 6, 0, 64, uint64_t, cfg->yellow.max_threshold); \ ++ MC_EXT_OP(ext, 7, 0, 64, uint64_t, cfg->yellow.min_threshold); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_SET_EARLY_DROP(cmd, if_id, tc_id, early_drop_iova) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 8, 8, uint8_t, tc_id); \ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, if_id); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, early_drop_iova); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_ADD_CUSTOM_TPID(cmd, cfg) \ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->tpid) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_REMOVE_CUSTOM_TPID(cmd, cfg) \ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->tpid) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_ENABLE(cmd, if_id) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_DISABLE(cmd, if_id) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_GET_ATTR(cmd, if_id) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_IF_GET_ATTR(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 4, enum dpsw_accepted_frames, \ ++ attr->admit_untagged);\ ++ MC_RSP_OP(cmd, 0, 5, 1, int, attr->enabled);\ ++ MC_RSP_OP(cmd, 0, 6, 1, int, attr->accept_all_vlan);\ ++ MC_RSP_OP(cmd, 0, 16, 8, uint8_t, attr->num_tcs);\ ++ MC_RSP_OP(cmd, 0, 32, 16, uint16_t, attr->qdid);\ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, attr->options);\ ++ MC_RSP_OP(cmd, 2, 0, 32, uint32_t, attr->rate);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_SET_MAX_FRAME_LENGTH(cmd, if_id, frame_length) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, frame_length);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_GET_MAX_FRAME_LENGTH(cmd, if_id) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_IF_GET_MAX_FRAME_LENGTH(cmd, frame_length) \ ++ MC_RSP_OP(cmd, 0, 16, 16, uint16_t, frame_length) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_SET_LINK_CFG(cmd, if_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 1, 0, 32, uint32_t, cfg->rate);\ ++ MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->options);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_GET_LINK_STATE(cmd, if_id) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_IF_GET_LINK_STATE(cmd, state) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 32, 1, int, state->up);\ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, state->rate);\ ++ MC_RSP_OP(cmd, 2, 0, 64, uint64_t, state->options);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_VLAN_ADD(cmd, vlan_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, cfg->fdb_id);\ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, vlan_id);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_VLAN_ADD_IF(cmd, vlan_id) \ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, vlan_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_VLAN_ADD_IF_UNTAGGED(cmd, vlan_id) \ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, vlan_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_VLAN_ADD_IF_FLOODING(cmd, vlan_id) \ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, vlan_id) ++ ++#define DPSW_CMD_VLAN_REMOVE_IF(cmd, vlan_id) \ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, vlan_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_VLAN_REMOVE_IF_UNTAGGED(cmd, vlan_id) \ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, vlan_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_VLAN_REMOVE_IF_FLOODING(cmd, vlan_id) \ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, vlan_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_VLAN_REMOVE(cmd, vlan_id) \ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, vlan_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_VLAN_GET_ATTR(cmd, vlan_id) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, vlan_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_VLAN_GET_ATTR(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->fdb_id); \ ++ MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->num_ifs); \ ++ MC_RSP_OP(cmd, 1, 32, 16, uint16_t, attr->num_untagged_ifs); \ ++ MC_RSP_OP(cmd, 1, 48, 16, uint16_t, attr->num_flooding_ifs); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_VLAN_GET_IF(cmd, vlan_id) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, vlan_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_VLAN_GET_IF(cmd, cfg) \ ++ MC_RSP_OP(cmd, 0, 16, 16, uint16_t, cfg->num_ifs) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_VLAN_GET_IF_FLOODING(cmd, vlan_id) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, vlan_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_VLAN_GET_IF_FLOODING(cmd, cfg) \ ++ MC_RSP_OP(cmd, 0, 16, 16, uint16_t, cfg->num_ifs) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_VLAN_GET_IF_UNTAGGED(cmd, vlan_id) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, vlan_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_VLAN_GET_IF_UNTAGGED(cmd, cfg) \ ++ MC_RSP_OP(cmd, 0, 16, 16, uint16_t, cfg->num_ifs) ++ ++/* param, offset, width, type, arg_name */ ++#define DPSW_CMD_FDB_ADD(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 32, 16, uint16_t, cfg->fdb_aging_time);\ ++ MC_CMD_OP(cmd, 0, 48, 16, uint16_t, cfg->num_fdb_entries);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_FDB_ADD(cmd, fdb_id) \ ++ MC_RSP_OP(cmd, 0, 0, 16, uint16_t, fdb_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_FDB_REMOVE(cmd, fdb_id) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, fdb_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_FDB_ADD_UNICAST(cmd, fdb_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, fdb_id);\ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, cfg->mac_addr[5]);\ ++ MC_CMD_OP(cmd, 0, 24, 8, uint8_t, cfg->mac_addr[4]);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->mac_addr[3]);\ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, cfg->mac_addr[2]);\ ++ MC_CMD_OP(cmd, 0, 48, 8, uint8_t, cfg->mac_addr[1]);\ ++ MC_CMD_OP(cmd, 0, 56, 8, uint8_t, cfg->mac_addr[0]);\ ++ MC_CMD_OP(cmd, 1, 0, 8, uint16_t, cfg->if_egress);\ ++ MC_CMD_OP(cmd, 1, 16, 4, enum dpsw_fdb_entry_type, cfg->type);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_FDB_GET_UNICAST(cmd, fdb_id) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, fdb_id);\ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, cfg->mac_addr[5]);\ ++ MC_CMD_OP(cmd, 0, 24, 8, uint8_t, cfg->mac_addr[4]);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->mac_addr[3]);\ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, cfg->mac_addr[2]);\ ++ MC_CMD_OP(cmd, 0, 48, 8, uint8_t, cfg->mac_addr[1]);\ ++ MC_CMD_OP(cmd, 0, 56, 8, uint8_t, cfg->mac_addr[0]);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_FDB_GET_UNICAST(cmd, cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, cfg->if_egress);\ ++ MC_RSP_OP(cmd, 1, 16, 4, enum dpsw_fdb_entry_type, cfg->type);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_FDB_REMOVE_UNICAST(cmd, fdb_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, fdb_id);\ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, cfg->mac_addr[5]);\ ++ MC_CMD_OP(cmd, 0, 24, 8, uint8_t, cfg->mac_addr[4]);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->mac_addr[3]);\ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, cfg->mac_addr[2]);\ ++ MC_CMD_OP(cmd, 0, 48, 8, uint8_t, cfg->mac_addr[1]);\ ++ MC_CMD_OP(cmd, 0, 56, 8, uint8_t, cfg->mac_addr[0]);\ ++ MC_CMD_OP(cmd, 1, 0, 16, uint16_t, cfg->if_egress);\ ++ MC_CMD_OP(cmd, 1, 16, 4, enum dpsw_fdb_entry_type, cfg->type);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_FDB_ADD_MULTICAST(cmd, fdb_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, fdb_id);\ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->num_ifs);\ ++ MC_CMD_OP(cmd, 0, 32, 4, enum dpsw_fdb_entry_type, cfg->type);\ ++ MC_CMD_OP(cmd, 1, 0, 8, uint8_t, cfg->mac_addr[5]);\ ++ MC_CMD_OP(cmd, 1, 8, 8, uint8_t, cfg->mac_addr[4]);\ ++ MC_CMD_OP(cmd, 1, 16, 8, uint8_t, cfg->mac_addr[3]);\ ++ MC_CMD_OP(cmd, 1, 24, 8, uint8_t, cfg->mac_addr[2]);\ ++ MC_CMD_OP(cmd, 1, 32, 8, uint8_t, cfg->mac_addr[1]);\ ++ MC_CMD_OP(cmd, 1, 40, 8, uint8_t, cfg->mac_addr[0]);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_FDB_GET_MULTICAST(cmd, fdb_id) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, fdb_id);\ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, cfg->mac_addr[5]);\ ++ MC_CMD_OP(cmd, 0, 24, 8, uint8_t, cfg->mac_addr[4]);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->mac_addr[3]);\ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, cfg->mac_addr[2]);\ ++ MC_CMD_OP(cmd, 0, 48, 8, uint8_t, cfg->mac_addr[1]);\ ++ MC_CMD_OP(cmd, 0, 56, 8, uint8_t, cfg->mac_addr[0]);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_FDB_GET_MULTICAST(cmd, cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, cfg->num_ifs);\ ++ MC_RSP_OP(cmd, 1, 16, 4, enum dpsw_fdb_entry_type, cfg->type);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_FDB_REMOVE_MULTICAST(cmd, fdb_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, fdb_id);\ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->num_ifs);\ ++ MC_CMD_OP(cmd, 0, 32, 4, enum dpsw_fdb_entry_type, cfg->type);\ ++ MC_CMD_OP(cmd, 1, 0, 8, uint8_t, cfg->mac_addr[5]);\ ++ MC_CMD_OP(cmd, 1, 8, 8, uint8_t, cfg->mac_addr[4]);\ ++ MC_CMD_OP(cmd, 1, 16, 8, uint8_t, cfg->mac_addr[3]);\ ++ MC_CMD_OP(cmd, 1, 24, 8, uint8_t, cfg->mac_addr[2]);\ ++ MC_CMD_OP(cmd, 1, 32, 8, uint8_t, cfg->mac_addr[1]);\ ++ MC_CMD_OP(cmd, 1, 40, 8, uint8_t, cfg->mac_addr[0]);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_FDB_SET_LEARNING_MODE(cmd, fdb_id, mode) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, fdb_id);\ ++ MC_CMD_OP(cmd, 0, 16, 4, enum dpsw_fdb_learning_mode, mode);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_FDB_GET_ATTR(cmd, fdb_id) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, fdb_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_FDB_GET_ATTR(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 16, 16, uint16_t, attr->max_fdb_entries);\ ++ MC_RSP_OP(cmd, 0, 32, 16, uint16_t, attr->fdb_aging_time);\ ++ MC_RSP_OP(cmd, 0, 48, 16, uint16_t, attr->num_fdb_mc_groups);\ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->max_fdb_mc_groups);\ ++ MC_RSP_OP(cmd, 1, 16, 4, enum dpsw_fdb_learning_mode, \ ++ attr->learning_mode);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_ACL_ADD(cmd, cfg) \ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->max_entries) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_ACL_ADD(cmd, acl_id) \ ++ MC_RSP_OP(cmd, 0, 0, 16, uint16_t, acl_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_ACL_REMOVE(cmd, acl_id) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, acl_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_PREP_ACL_ENTRY(ext, key) \ ++do { \ ++ MC_PREP_OP(ext, 0, 0, 8, uint8_t, key->match.l2_dest_mac[5]);\ ++ MC_PREP_OP(ext, 0, 8, 8, uint8_t, key->match.l2_dest_mac[4]);\ ++ MC_PREP_OP(ext, 0, 16, 8, uint8_t, key->match.l2_dest_mac[3]);\ ++ MC_PREP_OP(ext, 0, 24, 8, uint8_t, key->match.l2_dest_mac[2]);\ ++ MC_PREP_OP(ext, 0, 32, 8, uint8_t, key->match.l2_dest_mac[1]);\ ++ MC_PREP_OP(ext, 0, 40, 8, uint8_t, key->match.l2_dest_mac[0]);\ ++ MC_PREP_OP(ext, 0, 48, 16, uint16_t, key->match.l2_tpid);\ ++ MC_PREP_OP(ext, 1, 0, 8, uint8_t, key->match.l2_source_mac[5]);\ ++ MC_PREP_OP(ext, 1, 8, 8, uint8_t, key->match.l2_source_mac[4]);\ ++ MC_PREP_OP(ext, 1, 16, 8, uint8_t, key->match.l2_source_mac[3]);\ ++ MC_PREP_OP(ext, 1, 24, 8, uint8_t, key->match.l2_source_mac[2]);\ ++ MC_PREP_OP(ext, 1, 32, 8, uint8_t, key->match.l2_source_mac[1]);\ ++ MC_PREP_OP(ext, 1, 40, 8, uint8_t, key->match.l2_source_mac[0]);\ ++ MC_PREP_OP(ext, 1, 48, 16, uint16_t, key->match.l2_vlan_id);\ ++ MC_PREP_OP(ext, 2, 0, 32, uint32_t, key->match.l3_dest_ip);\ ++ MC_PREP_OP(ext, 2, 32, 32, uint32_t, key->match.l3_source_ip);\ ++ MC_PREP_OP(ext, 3, 0, 16, uint16_t, key->match.l4_dest_port);\ ++ MC_PREP_OP(ext, 3, 16, 16, uint16_t, key->match.l4_source_port);\ ++ MC_PREP_OP(ext, 3, 32, 16, uint16_t, key->match.l2_ether_type);\ ++ MC_PREP_OP(ext, 3, 48, 8, uint8_t, key->match.l2_pcp_dei);\ ++ MC_PREP_OP(ext, 3, 56, 8, uint8_t, key->match.l3_dscp);\ ++ MC_PREP_OP(ext, 4, 0, 8, uint8_t, key->mask.l2_dest_mac[5]);\ ++ MC_PREP_OP(ext, 4, 8, 8, uint8_t, key->mask.l2_dest_mac[4]);\ ++ MC_PREP_OP(ext, 4, 16, 8, uint8_t, key->mask.l2_dest_mac[3]);\ ++ MC_PREP_OP(ext, 4, 24, 8, uint8_t, key->mask.l2_dest_mac[2]);\ ++ MC_PREP_OP(ext, 4, 32, 8, uint8_t, key->mask.l2_dest_mac[1]);\ ++ MC_PREP_OP(ext, 4, 40, 8, uint8_t, key->mask.l2_dest_mac[0]);\ ++ MC_PREP_OP(ext, 4, 48, 16, uint16_t, key->mask.l2_tpid);\ ++ MC_PREP_OP(ext, 5, 0, 8, uint8_t, key->mask.l2_source_mac[5]);\ ++ MC_PREP_OP(ext, 5, 8, 8, uint8_t, key->mask.l2_source_mac[4]);\ ++ MC_PREP_OP(ext, 5, 16, 8, uint8_t, key->mask.l2_source_mac[3]);\ ++ MC_PREP_OP(ext, 5, 24, 8, uint8_t, key->mask.l2_source_mac[2]);\ ++ MC_PREP_OP(ext, 5, 32, 8, uint8_t, key->mask.l2_source_mac[1]);\ ++ MC_PREP_OP(ext, 5, 40, 8, uint8_t, key->mask.l2_source_mac[0]);\ ++ MC_PREP_OP(ext, 5, 48, 16, uint16_t, key->mask.l2_vlan_id);\ ++ MC_PREP_OP(ext, 6, 0, 32, uint32_t, key->mask.l3_dest_ip);\ ++ MC_PREP_OP(ext, 6, 32, 32, uint32_t, key->mask.l3_source_ip);\ ++ MC_PREP_OP(ext, 7, 0, 16, uint16_t, key->mask.l4_dest_port);\ ++ MC_PREP_OP(ext, 7, 16, 16, uint16_t, key->mask.l4_source_port);\ ++ MC_PREP_OP(ext, 7, 32, 16, uint16_t, key->mask.l2_ether_type);\ ++ MC_PREP_OP(ext, 7, 48, 8, uint8_t, key->mask.l2_pcp_dei);\ ++ MC_PREP_OP(ext, 7, 56, 8, uint8_t, key->mask.l3_dscp);\ ++ MC_PREP_OP(ext, 8, 0, 8, uint8_t, key->match.l3_protocol);\ ++ MC_PREP_OP(ext, 8, 8, 8, uint8_t, key->mask.l3_protocol);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_EXT_ACL_ENTRY(ext, key) \ ++do { \ ++ MC_EXT_OP(ext, 0, 0, 8, uint8_t, key->match.l2_dest_mac[5]);\ ++ MC_EXT_OP(ext, 0, 8, 8, uint8_t, key->match.l2_dest_mac[4]);\ ++ MC_EXT_OP(ext, 0, 16, 8, uint8_t, key->match.l2_dest_mac[3]);\ ++ MC_EXT_OP(ext, 0, 24, 8, uint8_t, key->match.l2_dest_mac[2]);\ ++ MC_EXT_OP(ext, 0, 32, 8, uint8_t, key->match.l2_dest_mac[1]);\ ++ MC_EXT_OP(ext, 0, 40, 8, uint8_t, key->match.l2_dest_mac[0]);\ ++ MC_EXT_OP(ext, 0, 48, 16, uint16_t, key->match.l2_tpid);\ ++ MC_EXT_OP(ext, 1, 0, 8, uint8_t, key->match.l2_source_mac[5]);\ ++ MC_EXT_OP(ext, 1, 8, 8, uint8_t, key->match.l2_source_mac[4]);\ ++ MC_EXT_OP(ext, 1, 16, 8, uint8_t, key->match.l2_source_mac[3]);\ ++ MC_EXT_OP(ext, 1, 24, 8, uint8_t, key->match.l2_source_mac[2]);\ ++ MC_EXT_OP(ext, 1, 32, 8, uint8_t, key->match.l2_source_mac[1]);\ ++ MC_EXT_OP(ext, 1, 40, 8, uint8_t, key->match.l2_source_mac[0]);\ ++ MC_EXT_OP(ext, 1, 48, 16, uint16_t, key->match.l2_vlan_id);\ ++ MC_EXT_OP(ext, 2, 0, 32, uint32_t, key->match.l3_dest_ip);\ ++ MC_EXT_OP(ext, 2, 32, 32, uint32_t, key->match.l3_source_ip);\ ++ MC_EXT_OP(ext, 3, 0, 16, uint16_t, key->match.l4_dest_port);\ ++ MC_EXT_OP(ext, 3, 16, 16, uint16_t, key->match.l4_source_port);\ ++ MC_EXT_OP(ext, 3, 32, 16, uint16_t, key->match.l2_ether_type);\ ++ MC_EXT_OP(ext, 3, 48, 8, uint8_t, key->match.l2_pcp_dei);\ ++ MC_EXT_OP(ext, 3, 56, 8, uint8_t, key->match.l3_dscp);\ ++ MC_EXT_OP(ext, 4, 0, 8, uint8_t, key->mask.l2_dest_mac[5]);\ ++ MC_EXT_OP(ext, 4, 8, 8, uint8_t, key->mask.l2_dest_mac[4]);\ ++ MC_EXT_OP(ext, 4, 16, 8, uint8_t, key->mask.l2_dest_mac[3]);\ ++ MC_EXT_OP(ext, 4, 24, 8, uint8_t, key->mask.l2_dest_mac[2]);\ ++ MC_EXT_OP(ext, 4, 32, 8, uint8_t, key->mask.l2_dest_mac[1]);\ ++ MC_EXT_OP(ext, 4, 40, 8, uint8_t, key->mask.l2_dest_mac[0]);\ ++ MC_EXT_OP(ext, 4, 48, 16, uint16_t, key->mask.l2_tpid);\ ++ MC_EXT_OP(ext, 5, 0, 8, uint8_t, key->mask.l2_source_mac[5]);\ ++ MC_EXT_OP(ext, 5, 8, 8, uint8_t, key->mask.l2_source_mac[4]);\ ++ MC_EXT_OP(ext, 5, 16, 8, uint8_t, key->mask.l2_source_mac[3]);\ ++ MC_EXT_OP(ext, 5, 24, 8, uint8_t, key->mask.l2_source_mac[2]);\ ++ MC_EXT_OP(ext, 5, 32, 8, uint8_t, key->mask.l2_source_mac[1]);\ ++ MC_EXT_OP(ext, 5, 40, 8, uint8_t, key->mask.l2_source_mac[0]);\ ++ MC_EXT_OP(ext, 5, 48, 16, uint16_t, key->mask.l2_vlan_id);\ ++ MC_EXT_OP(ext, 6, 0, 32, uint32_t, key->mask.l3_dest_ip);\ ++ MC_EXT_OP(ext, 6, 32, 32, uint32_t, key->mask.l3_source_ip);\ ++ MC_EXT_OP(ext, 7, 0, 16, uint16_t, key->mask.l4_dest_port);\ ++ MC_EXT_OP(ext, 7, 16, 16, uint16_t, key->mask.l4_source_port);\ ++ MC_EXT_OP(ext, 7, 32, 16, uint16_t, key->mask.l2_ether_type);\ ++ MC_EXT_OP(ext, 7, 48, 8, uint8_t, key->mask.l2_pcp_dei);\ ++ MC_EXT_OP(ext, 7, 56, 8, uint8_t, key->mask.l3_dscp);\ ++ MC_EXT_OP(ext, 8, 0, 8, uint8_t, key->match.l3_protocol);\ ++ MC_EXT_OP(ext, 8, 8, 8, uint8_t, key->mask.l3_protocol);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_ACL_ADD_ENTRY(cmd, acl_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, acl_id);\ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->result.if_id);\ ++ MC_CMD_OP(cmd, 0, 32, 32, int, cfg->precedence);\ ++ MC_CMD_OP(cmd, 1, 0, 4, enum dpsw_acl_action, cfg->result.action);\ ++ MC_CMD_OP(cmd, 6, 0, 64, uint64_t, cfg->key_iova); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_ACL_REMOVE_ENTRY(cmd, acl_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, acl_id);\ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->result.if_id);\ ++ MC_CMD_OP(cmd, 0, 32, 32, int, cfg->precedence);\ ++ MC_CMD_OP(cmd, 1, 0, 4, enum dpsw_acl_action, cfg->result.action);\ ++ MC_CMD_OP(cmd, 6, 0, 64, uint64_t, cfg->key_iova); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_ACL_ADD_IF(cmd, acl_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, acl_id);\ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->num_ifs); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_ACL_REMOVE_IF(cmd, acl_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, acl_id);\ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->num_ifs); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_ACL_GET_ATTR(cmd, acl_id) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, acl_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_ACL_GET_ATTR(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->max_entries);\ ++ MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->num_entries);\ ++ MC_RSP_OP(cmd, 1, 32, 16, uint16_t, attr->num_ifs);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_CTRL_IF_GET_ATTR(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, attr->rx_fqid);\ ++ MC_RSP_OP(cmd, 1, 32, 32, uint32_t, attr->rx_err_fqid);\ ++ MC_RSP_OP(cmd, 2, 0, 32, uint32_t, attr->tx_err_conf_fqid);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_CTRL_IF_SET_POOLS(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, cfg->num_dpbp); \ ++ MC_CMD_OP(cmd, 0, 8, 1, int, cfg->pools[0].backup_pool); \ ++ MC_CMD_OP(cmd, 0, 9, 1, int, cfg->pools[1].backup_pool); \ ++ MC_CMD_OP(cmd, 0, 10, 1, int, cfg->pools[2].backup_pool); \ ++ MC_CMD_OP(cmd, 0, 11, 1, int, cfg->pools[3].backup_pool); \ ++ MC_CMD_OP(cmd, 0, 12, 1, int, cfg->pools[4].backup_pool); \ ++ MC_CMD_OP(cmd, 0, 13, 1, int, cfg->pools[5].backup_pool); \ ++ MC_CMD_OP(cmd, 0, 14, 1, int, cfg->pools[6].backup_pool); \ ++ MC_CMD_OP(cmd, 0, 15, 1, int, cfg->pools[7].backup_pool); \ ++ MC_CMD_OP(cmd, 0, 32, 32, int, cfg->pools[0].dpbp_id); \ ++ MC_CMD_OP(cmd, 4, 32, 16, uint16_t, cfg->pools[0].buffer_size);\ ++ MC_CMD_OP(cmd, 1, 0, 32, int, cfg->pools[1].dpbp_id); \ ++ MC_CMD_OP(cmd, 4, 48, 16, uint16_t, cfg->pools[1].buffer_size);\ ++ MC_CMD_OP(cmd, 1, 32, 32, int, cfg->pools[2].dpbp_id); \ ++ MC_CMD_OP(cmd, 5, 0, 16, uint16_t, cfg->pools[2].buffer_size);\ ++ MC_CMD_OP(cmd, 2, 0, 32, int, cfg->pools[3].dpbp_id); \ ++ MC_CMD_OP(cmd, 5, 16, 16, uint16_t, cfg->pools[3].buffer_size);\ ++ MC_CMD_OP(cmd, 2, 32, 32, int, cfg->pools[4].dpbp_id); \ ++ MC_CMD_OP(cmd, 5, 32, 16, uint16_t, cfg->pools[4].buffer_size);\ ++ MC_CMD_OP(cmd, 3, 0, 32, int, cfg->pools[5].dpbp_id); \ ++ MC_CMD_OP(cmd, 5, 48, 16, uint16_t, cfg->pools[5].buffer_size);\ ++ MC_CMD_OP(cmd, 3, 32, 32, int, cfg->pools[6].dpbp_id); \ ++ MC_CMD_OP(cmd, 6, 0, 16, uint16_t, cfg->pools[6].buffer_size);\ ++ MC_CMD_OP(cmd, 4, 0, 32, int, cfg->pools[7].dpbp_id); \ ++ MC_CMD_OP(cmd, 6, 16, 16, uint16_t, cfg->pools[7].buffer_size);\ ++} while (0) ++ ++#endif /* __FSL_DPSW_CMD_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_mc_cmd.h b/drivers/net/dpaa2/mc/fsl_mc_cmd.h +new file mode 100644 +index 0000000..ac4f2b4 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_mc_cmd.h +@@ -0,0 +1,221 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_MC_CMD_H ++#define __FSL_MC_CMD_H ++ ++#define MC_CMD_NUM_OF_PARAMS 7 ++ ++#define MAKE_UMASK64(_width) \ ++ ((uint64_t)((_width) < 64 ? ((uint64_t)1 << (_width)) - 1 :\ ++ (uint64_t)-1)) ++static inline uint64_t mc_enc(int lsoffset, int width, uint64_t val) ++{ ++ return (uint64_t)(((uint64_t)val & MAKE_UMASK64(width)) << lsoffset); ++} ++ ++static inline uint64_t mc_dec(uint64_t val, int lsoffset, int width) ++{ ++ return (uint64_t)((val >> lsoffset) & MAKE_UMASK64(width)); ++} ++ ++struct mc_command { ++ uint64_t header; ++ uint64_t params[MC_CMD_NUM_OF_PARAMS]; ++}; ++ ++/** ++ * enum mc_cmd_status - indicates MC status at command response ++ * @MC_CMD_STATUS_OK: Completed successfully ++ * @MC_CMD_STATUS_READY: Ready to be processed ++ * @MC_CMD_STATUS_AUTH_ERR: Authentication error ++ * @MC_CMD_STATUS_NO_PRIVILEGE: No privilege ++ * @MC_CMD_STATUS_DMA_ERR: DMA or I/O error ++ * @MC_CMD_STATUS_CONFIG_ERR: Configuration error ++ * @MC_CMD_STATUS_TIMEOUT: Operation timed out ++ * @MC_CMD_STATUS_NO_RESOURCE: No resources ++ * @MC_CMD_STATUS_NO_MEMORY: No memory available ++ * @MC_CMD_STATUS_BUSY: Device is busy ++ * @MC_CMD_STATUS_UNSUPPORTED_OP: Unsupported operation ++ * @MC_CMD_STATUS_INVALID_STATE: Invalid state ++ */ ++enum mc_cmd_status { ++ MC_CMD_STATUS_OK = 0x0, ++ MC_CMD_STATUS_READY = 0x1, ++ MC_CMD_STATUS_AUTH_ERR = 0x3, ++ MC_CMD_STATUS_NO_PRIVILEGE = 0x4, ++ MC_CMD_STATUS_DMA_ERR = 0x5, ++ MC_CMD_STATUS_CONFIG_ERR = 0x6, ++ MC_CMD_STATUS_TIMEOUT = 0x7, ++ MC_CMD_STATUS_NO_RESOURCE = 0x8, ++ MC_CMD_STATUS_NO_MEMORY = 0x9, ++ MC_CMD_STATUS_BUSY = 0xA, ++ MC_CMD_STATUS_UNSUPPORTED_OP = 0xB, ++ MC_CMD_STATUS_INVALID_STATE = 0xC ++}; ++ ++/* MC command flags */ ++ ++/** ++ * High priority flag ++ */ ++#define MC_CMD_FLAG_PRI 0x00008000 ++/** ++ * Command completion flag ++ */ ++#define MC_CMD_FLAG_INTR_DIS 0x01000000 ++ ++/** ++ * Command ID field offset ++ */ ++#define MC_CMD_HDR_CMDID_O 52 ++/** ++ * Command ID field size ++ */ ++#define MC_CMD_HDR_CMDID_S 12 ++/** ++ * Token field offset ++ */ ++#define MC_CMD_HDR_TOKEN_O 38 ++/** ++ * Token field size ++ */ ++#define MC_CMD_HDR_TOKEN_S 10 ++/** ++ * Status field offset ++ */ ++#define MC_CMD_HDR_STATUS_O 16 ++/** ++ * Status field size ++ */ ++#define MC_CMD_HDR_STATUS_S 8 ++/** ++ * Flags field offset ++ */ ++#define MC_CMD_HDR_FLAGS_O 0 ++/** ++ * Flags field size ++ */ ++#define MC_CMD_HDR_FLAGS_S 32 ++/** ++ * Command flags mask ++ */ ++#define MC_CMD_HDR_FLAGS_MASK 0xFF00FF00 ++ ++#define MC_CMD_HDR_READ_STATUS(_hdr) \ ++ ((enum mc_cmd_status)mc_dec((_hdr), \ ++ MC_CMD_HDR_STATUS_O, MC_CMD_HDR_STATUS_S)) ++ ++#define MC_CMD_HDR_READ_TOKEN(_hdr) \ ++ ((uint16_t)mc_dec((_hdr), MC_CMD_HDR_TOKEN_O, MC_CMD_HDR_TOKEN_S)) ++ ++#define MC_PREP_OP(_ext, _param, _offset, _width, _type, _arg) \ ++ ((_ext)[_param] |= cpu_to_le64(mc_enc((_offset), (_width), _arg))) ++ ++#define MC_EXT_OP(_ext, _param, _offset, _width, _type, _arg) \ ++ (_arg = (_type)mc_dec(cpu_to_le64(_ext[_param]), (_offset), (_width))) ++ ++#define MC_CMD_OP(_cmd, _param, _offset, _width, _type, _arg) \ ++ ((_cmd).params[_param] |= mc_enc((_offset), (_width), _arg)) ++ ++#define MC_RSP_OP(_cmd, _param, _offset, _width, _type, _arg) \ ++ (_arg = (_type)mc_dec(_cmd.params[_param], (_offset), (_width))) ++ ++static inline uint64_t mc_encode_cmd_header(uint16_t cmd_id, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ uint64_t hdr; ++ ++ hdr = mc_enc(MC_CMD_HDR_CMDID_O, MC_CMD_HDR_CMDID_S, cmd_id); ++ hdr |= mc_enc(MC_CMD_HDR_FLAGS_O, MC_CMD_HDR_FLAGS_S, ++ (cmd_flags & MC_CMD_HDR_FLAGS_MASK)); ++ hdr |= mc_enc(MC_CMD_HDR_TOKEN_O, MC_CMD_HDR_TOKEN_S, token); ++ hdr |= mc_enc(MC_CMD_HDR_STATUS_O, MC_CMD_HDR_STATUS_S, ++ MC_CMD_STATUS_READY); ++ ++ return hdr; ++} ++ ++/** ++ * mc_write_command - writes a command to a Management Complex (MC) portal ++ * ++ * @portal: pointer to an MC portal ++ * @cmd: pointer to a filled command ++ */ ++static inline void mc_write_command(struct mc_command __iomem *portal, ++ struct mc_command *cmd) ++{ ++ int i; ++ uint32_t word; ++ ++ /* copy command parameters into the portal */ ++ for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++) ++ iowrite64(cmd->params[i], &portal->params[i]); ++ ++ /* submit the command by writing the header */ ++ word = (uint32_t)mc_dec(cmd->header, 32, 32); ++ iowrite32(word, (((uint32_t *)&portal->header) + 1)); ++ ++ word = (uint32_t)mc_dec(cmd->header, 0, 32); ++ iowrite32(word, (uint32_t *)&portal->header); ++} ++ ++/** ++ * mc_read_response - reads the response for the last MC command from a ++ * Management Complex (MC) portal ++ * ++ * @portal: pointer to an MC portal ++ * @resp: pointer to command response buffer ++ * ++ * Returns MC_CMD_STATUS_OK on Success; Error code otherwise. ++ */ ++static inline enum mc_cmd_status mc_read_response( ++ struct mc_command __iomem *portal, ++ struct mc_command *resp) ++{ ++ int i; ++ enum mc_cmd_status status; ++ ++ /* Copy command response header from MC portal: */ ++ resp->header = ioread64(&portal->header); ++ status = MC_CMD_HDR_READ_STATUS(resp->header); ++ if (status != MC_CMD_STATUS_OK) ++ return status; ++ ++ /* Copy command response data from MC portal: */ ++ for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++) ++ resp->params[i] = ioread64(&portal->params[i]); ++ ++ return status; ++} ++ ++#endif /* __FSL_MC_CMD_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_mc_sys.h b/drivers/net/dpaa2/mc/fsl_mc_sys.h +new file mode 100644 +index 0000000..769c129 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_mc_sys.h +@@ -0,0 +1,95 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_MC_SYS_H ++#define _FSL_MC_SYS_H ++ ++#ifdef __linux_driver__ ++ ++#include ++#include ++#include ++ ++struct fsl_mc_io { ++ void *regs; ++}; ++ ++#ifndef ENOTSUP ++#define ENOTSUP 95 ++#endif ++ ++#define ioread64(_p) readq(_p) ++#define iowrite64(_v, _p) writeq(_v, _p) ++ ++#else /* __linux_driver__ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define cpu_to_le64(x) __cpu_to_le64(x) ++#ifndef dmb ++#define dmb() __asm__ __volatile__ ("" : : : "memory") ++#endif ++#define __iormb() dmb() ++#define __iowmb() dmb() ++#define __arch_getq(a) (*(volatile unsigned long *)(a)) ++#define __arch_putq(v, a) (*(volatile unsigned long *)(a) = (v)) ++#define __arch_putq32(v, a) (*(volatile unsigned int *)(a) = (v)) ++#define readq(c) ({ uint64_t __v = __arch_getq(c); __iormb(); __v; }) ++#define writeq(v, c) ({ uint64_t __v = v; __iowmb(); __arch_putq(__v, c); __v; }) ++#define writeq32(v, c) ({ uint32_t __v = v; __iowmb(); __arch_putq32(__v, c); __v; }) ++#define ioread64(_p) readq(_p) ++#define iowrite64(_v, _p) writeq(_v, _p) ++#define iowrite32(_v, _p) writeq32(_v, _p) ++#define __iomem ++ ++struct fsl_mc_io { ++ void *regs; ++}; ++ ++#ifndef ENOTSUP ++#define ENOTSUP 95 ++#endif ++ ++/*GPP is supposed to use MC commands with low priority*/ ++#define CMD_PRI_LOW 0 /*!< Low Priority command indication */ ++ ++struct mc_command; ++ ++int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd); ++ ++#endif /* __linux_driver__ */ ++ ++#endif /* _FSL_MC_SYS_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_net.h b/drivers/net/dpaa2/mc/fsl_net.h +new file mode 100644 +index 0000000..43825b8 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_net.h +@@ -0,0 +1,480 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_NET_H ++#define __FSL_NET_H ++ ++#define LAST_HDR_INDEX 0xFFFFFFFF ++ ++/*****************************************************************************/ ++/* Protocol fields */ ++/*****************************************************************************/ ++ ++/************************* Ethernet fields *********************************/ ++#define NH_FLD_ETH_DA (1) ++#define NH_FLD_ETH_SA (NH_FLD_ETH_DA << 1) ++#define NH_FLD_ETH_LENGTH (NH_FLD_ETH_DA << 2) ++#define NH_FLD_ETH_TYPE (NH_FLD_ETH_DA << 3) ++#define NH_FLD_ETH_FINAL_CKSUM (NH_FLD_ETH_DA << 4) ++#define NH_FLD_ETH_PADDING (NH_FLD_ETH_DA << 5) ++#define NH_FLD_ETH_ALL_FIELDS ((NH_FLD_ETH_DA << 6) - 1) ++ ++#define NH_FLD_ETH_ADDR_SIZE 6 ++ ++/*************************** VLAN fields ***********************************/ ++#define NH_FLD_VLAN_VPRI (1) ++#define NH_FLD_VLAN_CFI (NH_FLD_VLAN_VPRI << 1) ++#define NH_FLD_VLAN_VID (NH_FLD_VLAN_VPRI << 2) ++#define NH_FLD_VLAN_LENGTH (NH_FLD_VLAN_VPRI << 3) ++#define NH_FLD_VLAN_TYPE (NH_FLD_VLAN_VPRI << 4) ++#define NH_FLD_VLAN_ALL_FIELDS ((NH_FLD_VLAN_VPRI << 5) - 1) ++ ++#define NH_FLD_VLAN_TCI (NH_FLD_VLAN_VPRI | \ ++ NH_FLD_VLAN_CFI | \ ++ NH_FLD_VLAN_VID) ++ ++/************************ IP (generic) fields ******************************/ ++#define NH_FLD_IP_VER (1) ++#define NH_FLD_IP_DSCP (NH_FLD_IP_VER << 2) ++#define NH_FLD_IP_ECN (NH_FLD_IP_VER << 3) ++#define NH_FLD_IP_PROTO (NH_FLD_IP_VER << 4) ++#define NH_FLD_IP_SRC (NH_FLD_IP_VER << 5) ++#define NH_FLD_IP_DST (NH_FLD_IP_VER << 6) ++#define NH_FLD_IP_TOS_TC (NH_FLD_IP_VER << 7) ++#define NH_FLD_IP_ID (NH_FLD_IP_VER << 8) ++#define NH_FLD_IP_ALL_FIELDS ((NH_FLD_IP_VER << 9) - 1) ++ ++#define NH_FLD_IP_PROTO_SIZE 1 ++ ++/***************************** IPV4 fields *********************************/ ++#define NH_FLD_IPV4_VER (1) ++#define NH_FLD_IPV4_HDR_LEN (NH_FLD_IPV4_VER << 1) ++#define NH_FLD_IPV4_TOS (NH_FLD_IPV4_VER << 2) ++#define NH_FLD_IPV4_TOTAL_LEN (NH_FLD_IPV4_VER << 3) ++#define NH_FLD_IPV4_ID (NH_FLD_IPV4_VER << 4) ++#define NH_FLD_IPV4_FLAG_D (NH_FLD_IPV4_VER << 5) ++#define NH_FLD_IPV4_FLAG_M (NH_FLD_IPV4_VER << 6) ++#define NH_FLD_IPV4_OFFSET (NH_FLD_IPV4_VER << 7) ++#define NH_FLD_IPV4_TTL (NH_FLD_IPV4_VER << 8) ++#define NH_FLD_IPV4_PROTO (NH_FLD_IPV4_VER << 9) ++#define NH_FLD_IPV4_CKSUM (NH_FLD_IPV4_VER << 10) ++#define NH_FLD_IPV4_SRC_IP (NH_FLD_IPV4_VER << 11) ++#define NH_FLD_IPV4_DST_IP (NH_FLD_IPV4_VER << 12) ++#define NH_FLD_IPV4_OPTS (NH_FLD_IPV4_VER << 13) ++#define NH_FLD_IPV4_OPTS_COUNT (NH_FLD_IPV4_VER << 14) ++#define NH_FLD_IPV4_ALL_FIELDS ((NH_FLD_IPV4_VER << 15) - 1) ++ ++#define NH_FLD_IPV4_ADDR_SIZE 4 ++#define NH_FLD_IPV4_PROTO_SIZE 1 ++ ++/***************************** IPV6 fields *********************************/ ++#define NH_FLD_IPV6_VER (1) ++#define NH_FLD_IPV6_TC (NH_FLD_IPV6_VER << 1) ++#define NH_FLD_IPV6_SRC_IP (NH_FLD_IPV6_VER << 2) ++#define NH_FLD_IPV6_DST_IP (NH_FLD_IPV6_VER << 3) ++#define NH_FLD_IPV6_NEXT_HDR (NH_FLD_IPV6_VER << 4) ++#define NH_FLD_IPV6_FL (NH_FLD_IPV6_VER << 5) ++#define NH_FLD_IPV6_HOP_LIMIT (NH_FLD_IPV6_VER << 6) ++#define NH_FLD_IPV6_ID (NH_FLD_IPV6_VER << 7) ++#define NH_FLD_IPV6_ALL_FIELDS ((NH_FLD_IPV6_VER << 8) - 1) ++ ++#define NH_FLD_IPV6_ADDR_SIZE 16 ++#define NH_FLD_IPV6_NEXT_HDR_SIZE 1 ++ ++/***************************** ICMP fields *********************************/ ++#define NH_FLD_ICMP_TYPE (1) ++#define NH_FLD_ICMP_CODE (NH_FLD_ICMP_TYPE << 1) ++#define NH_FLD_ICMP_CKSUM (NH_FLD_ICMP_TYPE << 2) ++#define NH_FLD_ICMP_ID (NH_FLD_ICMP_TYPE << 3) ++#define NH_FLD_ICMP_SQ_NUM (NH_FLD_ICMP_TYPE << 4) ++#define NH_FLD_ICMP_ALL_FIELDS ((NH_FLD_ICMP_TYPE << 5) - 1) ++ ++#define NH_FLD_ICMP_CODE_SIZE 1 ++#define NH_FLD_ICMP_TYPE_SIZE 1 ++ ++/***************************** IGMP fields *********************************/ ++#define NH_FLD_IGMP_VERSION (1) ++#define NH_FLD_IGMP_TYPE (NH_FLD_IGMP_VERSION << 1) ++#define NH_FLD_IGMP_CKSUM (NH_FLD_IGMP_VERSION << 2) ++#define NH_FLD_IGMP_DATA (NH_FLD_IGMP_VERSION << 3) ++#define NH_FLD_IGMP_ALL_FIELDS ((NH_FLD_IGMP_VERSION << 4) - 1) ++ ++/***************************** TCP fields **********************************/ ++#define NH_FLD_TCP_PORT_SRC (1) ++#define NH_FLD_TCP_PORT_DST (NH_FLD_TCP_PORT_SRC << 1) ++#define NH_FLD_TCP_SEQ (NH_FLD_TCP_PORT_SRC << 2) ++#define NH_FLD_TCP_ACK (NH_FLD_TCP_PORT_SRC << 3) ++#define NH_FLD_TCP_OFFSET (NH_FLD_TCP_PORT_SRC << 4) ++#define NH_FLD_TCP_FLAGS (NH_FLD_TCP_PORT_SRC << 5) ++#define NH_FLD_TCP_WINDOW (NH_FLD_TCP_PORT_SRC << 6) ++#define NH_FLD_TCP_CKSUM (NH_FLD_TCP_PORT_SRC << 7) ++#define NH_FLD_TCP_URGPTR (NH_FLD_TCP_PORT_SRC << 8) ++#define NH_FLD_TCP_OPTS (NH_FLD_TCP_PORT_SRC << 9) ++#define NH_FLD_TCP_OPTS_COUNT (NH_FLD_TCP_PORT_SRC << 10) ++#define NH_FLD_TCP_ALL_FIELDS ((NH_FLD_TCP_PORT_SRC << 11) - 1) ++ ++#define NH_FLD_TCP_PORT_SIZE 2 ++ ++/***************************** UDP fields **********************************/ ++#define NH_FLD_UDP_PORT_SRC (1) ++#define NH_FLD_UDP_PORT_DST (NH_FLD_UDP_PORT_SRC << 1) ++#define NH_FLD_UDP_LEN (NH_FLD_UDP_PORT_SRC << 2) ++#define NH_FLD_UDP_CKSUM (NH_FLD_UDP_PORT_SRC << 3) ++#define NH_FLD_UDP_ALL_FIELDS ((NH_FLD_UDP_PORT_SRC << 4) - 1) ++ ++#define NH_FLD_UDP_PORT_SIZE 2 ++ ++/*************************** UDP-lite fields *******************************/ ++#define NH_FLD_UDP_LITE_PORT_SRC (1) ++#define NH_FLD_UDP_LITE_PORT_DST (NH_FLD_UDP_LITE_PORT_SRC << 1) ++#define NH_FLD_UDP_LITE_ALL_FIELDS \ ++ ((NH_FLD_UDP_LITE_PORT_SRC << 2) - 1) ++ ++#define NH_FLD_UDP_LITE_PORT_SIZE 2 ++ ++/*************************** UDP-encap-ESP fields **************************/ ++#define NH_FLD_UDP_ENC_ESP_PORT_SRC (1) ++#define NH_FLD_UDP_ENC_ESP_PORT_DST (NH_FLD_UDP_ENC_ESP_PORT_SRC << 1) ++#define NH_FLD_UDP_ENC_ESP_LEN (NH_FLD_UDP_ENC_ESP_PORT_SRC << 2) ++#define NH_FLD_UDP_ENC_ESP_CKSUM (NH_FLD_UDP_ENC_ESP_PORT_SRC << 3) ++#define NH_FLD_UDP_ENC_ESP_SPI (NH_FLD_UDP_ENC_ESP_PORT_SRC << 4) ++#define NH_FLD_UDP_ENC_ESP_SEQUENCE_NUM (NH_FLD_UDP_ENC_ESP_PORT_SRC << 5) ++#define NH_FLD_UDP_ENC_ESP_ALL_FIELDS \ ++ ((NH_FLD_UDP_ENC_ESP_PORT_SRC << 6) - 1) ++ ++#define NH_FLD_UDP_ENC_ESP_PORT_SIZE 2 ++#define NH_FLD_UDP_ENC_ESP_SPI_SIZE 4 ++ ++/***************************** SCTP fields *********************************/ ++#define NH_FLD_SCTP_PORT_SRC (1) ++#define NH_FLD_SCTP_PORT_DST (NH_FLD_SCTP_PORT_SRC << 1) ++#define NH_FLD_SCTP_VER_TAG (NH_FLD_SCTP_PORT_SRC << 2) ++#define NH_FLD_SCTP_CKSUM (NH_FLD_SCTP_PORT_SRC << 3) ++#define NH_FLD_SCTP_ALL_FIELDS ((NH_FLD_SCTP_PORT_SRC << 4) - 1) ++ ++#define NH_FLD_SCTP_PORT_SIZE 2 ++ ++/***************************** DCCP fields *********************************/ ++#define NH_FLD_DCCP_PORT_SRC (1) ++#define NH_FLD_DCCP_PORT_DST (NH_FLD_DCCP_PORT_SRC << 1) ++#define NH_FLD_DCCP_ALL_FIELDS ((NH_FLD_DCCP_PORT_SRC << 2) - 1) ++ ++#define NH_FLD_DCCP_PORT_SIZE 2 ++ ++/***************************** IPHC fields *********************************/ ++#define NH_FLD_IPHC_CID (1) ++#define NH_FLD_IPHC_CID_TYPE (NH_FLD_IPHC_CID << 1) ++#define NH_FLD_IPHC_HCINDEX (NH_FLD_IPHC_CID << 2) ++#define NH_FLD_IPHC_GEN (NH_FLD_IPHC_CID << 3) ++#define NH_FLD_IPHC_D_BIT (NH_FLD_IPHC_CID << 4) ++#define NH_FLD_IPHC_ALL_FIELDS ((NH_FLD_IPHC_CID << 5) - 1) ++ ++/***************************** SCTP fields *********************************/ ++#define NH_FLD_SCTP_CHUNK_DATA_TYPE (1) ++#define NH_FLD_SCTP_CHUNK_DATA_FLAGS (NH_FLD_SCTP_CHUNK_DATA_TYPE << 1) ++#define NH_FLD_SCTP_CHUNK_DATA_LENGTH (NH_FLD_SCTP_CHUNK_DATA_TYPE << 2) ++#define NH_FLD_SCTP_CHUNK_DATA_TSN (NH_FLD_SCTP_CHUNK_DATA_TYPE << 3) ++#define NH_FLD_SCTP_CHUNK_DATA_STREAM_ID (NH_FLD_SCTP_CHUNK_DATA_TYPE << 4) ++#define NH_FLD_SCTP_CHUNK_DATA_STREAM_SQN (NH_FLD_SCTP_CHUNK_DATA_TYPE << 5) ++#define NH_FLD_SCTP_CHUNK_DATA_PAYLOAD_PID (NH_FLD_SCTP_CHUNK_DATA_TYPE << 6) ++#define NH_FLD_SCTP_CHUNK_DATA_UNORDERED (NH_FLD_SCTP_CHUNK_DATA_TYPE << 7) ++#define NH_FLD_SCTP_CHUNK_DATA_BEGGINING (NH_FLD_SCTP_CHUNK_DATA_TYPE << 8) ++#define NH_FLD_SCTP_CHUNK_DATA_END (NH_FLD_SCTP_CHUNK_DATA_TYPE << 9) ++#define NH_FLD_SCTP_CHUNK_DATA_ALL_FIELDS \ ++ ((NH_FLD_SCTP_CHUNK_DATA_TYPE << 10) - 1) ++ ++/*************************** L2TPV2 fields *********************************/ ++#define NH_FLD_L2TPV2_TYPE_BIT (1) ++#define NH_FLD_L2TPV2_LENGTH_BIT (NH_FLD_L2TPV2_TYPE_BIT << 1) ++#define NH_FLD_L2TPV2_SEQUENCE_BIT (NH_FLD_L2TPV2_TYPE_BIT << 2) ++#define NH_FLD_L2TPV2_OFFSET_BIT (NH_FLD_L2TPV2_TYPE_BIT << 3) ++#define NH_FLD_L2TPV2_PRIORITY_BIT (NH_FLD_L2TPV2_TYPE_BIT << 4) ++#define NH_FLD_L2TPV2_VERSION (NH_FLD_L2TPV2_TYPE_BIT << 5) ++#define NH_FLD_L2TPV2_LEN (NH_FLD_L2TPV2_TYPE_BIT << 6) ++#define NH_FLD_L2TPV2_TUNNEL_ID (NH_FLD_L2TPV2_TYPE_BIT << 7) ++#define NH_FLD_L2TPV2_SESSION_ID (NH_FLD_L2TPV2_TYPE_BIT << 8) ++#define NH_FLD_L2TPV2_NS (NH_FLD_L2TPV2_TYPE_BIT << 9) ++#define NH_FLD_L2TPV2_NR (NH_FLD_L2TPV2_TYPE_BIT << 10) ++#define NH_FLD_L2TPV2_OFFSET_SIZE (NH_FLD_L2TPV2_TYPE_BIT << 11) ++#define NH_FLD_L2TPV2_FIRST_BYTE (NH_FLD_L2TPV2_TYPE_BIT << 12) ++#define NH_FLD_L2TPV2_ALL_FIELDS \ ++ ((NH_FLD_L2TPV2_TYPE_BIT << 13) - 1) ++ ++/*************************** L2TPV3 fields *********************************/ ++#define NH_FLD_L2TPV3_CTRL_TYPE_BIT (1) ++#define NH_FLD_L2TPV3_CTRL_LENGTH_BIT (NH_FLD_L2TPV3_CTRL_TYPE_BIT << 1) ++#define NH_FLD_L2TPV3_CTRL_SEQUENCE_BIT (NH_FLD_L2TPV3_CTRL_TYPE_BIT << 2) ++#define NH_FLD_L2TPV3_CTRL_VERSION (NH_FLD_L2TPV3_CTRL_TYPE_BIT << 3) ++#define NH_FLD_L2TPV3_CTRL_LENGTH (NH_FLD_L2TPV3_CTRL_TYPE_BIT << 4) ++#define NH_FLD_L2TPV3_CTRL_CONTROL (NH_FLD_L2TPV3_CTRL_TYPE_BIT << 5) ++#define NH_FLD_L2TPV3_CTRL_SENT (NH_FLD_L2TPV3_CTRL_TYPE_BIT << 6) ++#define NH_FLD_L2TPV3_CTRL_RECV (NH_FLD_L2TPV3_CTRL_TYPE_BIT << 7) ++#define NH_FLD_L2TPV3_CTRL_FIRST_BYTE (NH_FLD_L2TPV3_CTRL_TYPE_BIT << 8) ++#define NH_FLD_L2TPV3_CTRL_ALL_FIELDS \ ++ ((NH_FLD_L2TPV3_CTRL_TYPE_BIT << 9) - 1) ++ ++#define NH_FLD_L2TPV3_SESS_TYPE_BIT (1) ++#define NH_FLD_L2TPV3_SESS_VERSION (NH_FLD_L2TPV3_SESS_TYPE_BIT << 1) ++#define NH_FLD_L2TPV3_SESS_ID (NH_FLD_L2TPV3_SESS_TYPE_BIT << 2) ++#define NH_FLD_L2TPV3_SESS_COOKIE (NH_FLD_L2TPV3_SESS_TYPE_BIT << 3) ++#define NH_FLD_L2TPV3_SESS_ALL_FIELDS \ ++ ((NH_FLD_L2TPV3_SESS_TYPE_BIT << 4) - 1) ++ ++/**************************** PPP fields ***********************************/ ++#define NH_FLD_PPP_PID (1) ++#define NH_FLD_PPP_COMPRESSED (NH_FLD_PPP_PID << 1) ++#define NH_FLD_PPP_ALL_FIELDS ((NH_FLD_PPP_PID << 2) - 1) ++ ++/************************** PPPoE fields ***********************************/ ++#define NH_FLD_PPPOE_VER (1) ++#define NH_FLD_PPPOE_TYPE (NH_FLD_PPPOE_VER << 1) ++#define NH_FLD_PPPOE_CODE (NH_FLD_PPPOE_VER << 2) ++#define NH_FLD_PPPOE_SID (NH_FLD_PPPOE_VER << 3) ++#define NH_FLD_PPPOE_LEN (NH_FLD_PPPOE_VER << 4) ++#define NH_FLD_PPPOE_SESSION (NH_FLD_PPPOE_VER << 5) ++#define NH_FLD_PPPOE_PID (NH_FLD_PPPOE_VER << 6) ++#define NH_FLD_PPPOE_ALL_FIELDS ((NH_FLD_PPPOE_VER << 7) - 1) ++ ++/************************* PPP-Mux fields **********************************/ ++#define NH_FLD_PPPMUX_PID (1) ++#define NH_FLD_PPPMUX_CKSUM (NH_FLD_PPPMUX_PID << 1) ++#define NH_FLD_PPPMUX_COMPRESSED (NH_FLD_PPPMUX_PID << 2) ++#define NH_FLD_PPPMUX_ALL_FIELDS ((NH_FLD_PPPMUX_PID << 3) - 1) ++ ++/*********************** PPP-Mux sub-frame fields **************************/ ++#define NH_FLD_PPPMUX_SUBFRM_PFF (1) ++#define NH_FLD_PPPMUX_SUBFRM_LXT (NH_FLD_PPPMUX_SUBFRM_PFF << 1) ++#define NH_FLD_PPPMUX_SUBFRM_LEN (NH_FLD_PPPMUX_SUBFRM_PFF << 2) ++#define NH_FLD_PPPMUX_SUBFRM_PID (NH_FLD_PPPMUX_SUBFRM_PFF << 3) ++#define NH_FLD_PPPMUX_SUBFRM_USE_PID (NH_FLD_PPPMUX_SUBFRM_PFF << 4) ++#define NH_FLD_PPPMUX_SUBFRM_ALL_FIELDS \ ++ ((NH_FLD_PPPMUX_SUBFRM_PFF << 5) - 1) ++ ++/*************************** LLC fields ************************************/ ++#define NH_FLD_LLC_DSAP (1) ++#define NH_FLD_LLC_SSAP (NH_FLD_LLC_DSAP << 1) ++#define NH_FLD_LLC_CTRL (NH_FLD_LLC_DSAP << 2) ++#define NH_FLD_LLC_ALL_FIELDS ((NH_FLD_LLC_DSAP << 3) - 1) ++ ++/*************************** NLPID fields **********************************/ ++#define NH_FLD_NLPID_NLPID (1) ++#define NH_FLD_NLPID_ALL_FIELDS ((NH_FLD_NLPID_NLPID << 1) - 1) ++ ++/*************************** SNAP fields ***********************************/ ++#define NH_FLD_SNAP_OUI (1) ++#define NH_FLD_SNAP_PID (NH_FLD_SNAP_OUI << 1) ++#define NH_FLD_SNAP_ALL_FIELDS ((NH_FLD_SNAP_OUI << 2) - 1) ++ ++/*************************** LLC SNAP fields *******************************/ ++#define NH_FLD_LLC_SNAP_TYPE (1) ++#define NH_FLD_LLC_SNAP_ALL_FIELDS ((NH_FLD_LLC_SNAP_TYPE << 1) - 1) ++ ++#define NH_FLD_ARP_HTYPE (1) ++#define NH_FLD_ARP_PTYPE (NH_FLD_ARP_HTYPE << 1) ++#define NH_FLD_ARP_HLEN (NH_FLD_ARP_HTYPE << 2) ++#define NH_FLD_ARP_PLEN (NH_FLD_ARP_HTYPE << 3) ++#define NH_FLD_ARP_OPER (NH_FLD_ARP_HTYPE << 4) ++#define NH_FLD_ARP_SHA (NH_FLD_ARP_HTYPE << 5) ++#define NH_FLD_ARP_SPA (NH_FLD_ARP_HTYPE << 6) ++#define NH_FLD_ARP_THA (NH_FLD_ARP_HTYPE << 7) ++#define NH_FLD_ARP_TPA (NH_FLD_ARP_HTYPE << 8) ++#define NH_FLD_ARP_ALL_FIELDS ((NH_FLD_ARP_HTYPE << 9) - 1) ++ ++/*************************** RFC2684 fields ********************************/ ++#define NH_FLD_RFC2684_LLC (1) ++#define NH_FLD_RFC2684_NLPID (NH_FLD_RFC2684_LLC << 1) ++#define NH_FLD_RFC2684_OUI (NH_FLD_RFC2684_LLC << 2) ++#define NH_FLD_RFC2684_PID (NH_FLD_RFC2684_LLC << 3) ++#define NH_FLD_RFC2684_VPN_OUI (NH_FLD_RFC2684_LLC << 4) ++#define NH_FLD_RFC2684_VPN_IDX (NH_FLD_RFC2684_LLC << 5) ++#define NH_FLD_RFC2684_ALL_FIELDS ((NH_FLD_RFC2684_LLC << 6) - 1) ++ ++/*************************** User defined fields ***************************/ ++#define NH_FLD_USER_DEFINED_SRCPORT (1) ++#define NH_FLD_USER_DEFINED_PCDID (NH_FLD_USER_DEFINED_SRCPORT << 1) ++#define NH_FLD_USER_DEFINED_ALL_FIELDS \ ++ ((NH_FLD_USER_DEFINED_SRCPORT << 2) - 1) ++ ++/*************************** Payload fields ********************************/ ++#define NH_FLD_PAYLOAD_BUFFER (1) ++#define NH_FLD_PAYLOAD_SIZE (NH_FLD_PAYLOAD_BUFFER << 1) ++#define NH_FLD_MAX_FRM_SIZE (NH_FLD_PAYLOAD_BUFFER << 2) ++#define NH_FLD_MIN_FRM_SIZE (NH_FLD_PAYLOAD_BUFFER << 3) ++#define NH_FLD_PAYLOAD_TYPE (NH_FLD_PAYLOAD_BUFFER << 4) ++#define NH_FLD_FRAME_SIZE (NH_FLD_PAYLOAD_BUFFER << 5) ++#define NH_FLD_PAYLOAD_ALL_FIELDS ((NH_FLD_PAYLOAD_BUFFER << 6) - 1) ++ ++/*************************** GRE fields ************************************/ ++#define NH_FLD_GRE_TYPE (1) ++#define NH_FLD_GRE_ALL_FIELDS ((NH_FLD_GRE_TYPE << 1) - 1) ++ ++/*************************** MINENCAP fields *******************************/ ++#define NH_FLD_MINENCAP_SRC_IP (1) ++#define NH_FLD_MINENCAP_DST_IP (NH_FLD_MINENCAP_SRC_IP << 1) ++#define NH_FLD_MINENCAP_TYPE (NH_FLD_MINENCAP_SRC_IP << 2) ++#define NH_FLD_MINENCAP_ALL_FIELDS \ ++ ((NH_FLD_MINENCAP_SRC_IP << 3) - 1) ++ ++/*************************** IPSEC AH fields *******************************/ ++#define NH_FLD_IPSEC_AH_SPI (1) ++#define NH_FLD_IPSEC_AH_NH (NH_FLD_IPSEC_AH_SPI << 1) ++#define NH_FLD_IPSEC_AH_ALL_FIELDS ((NH_FLD_IPSEC_AH_SPI << 2) - 1) ++ ++/*************************** IPSEC ESP fields ******************************/ ++#define NH_FLD_IPSEC_ESP_SPI (1) ++#define NH_FLD_IPSEC_ESP_SEQUENCE_NUM (NH_FLD_IPSEC_ESP_SPI << 1) ++#define NH_FLD_IPSEC_ESP_ALL_FIELDS ((NH_FLD_IPSEC_ESP_SPI << 2) - 1) ++ ++#define NH_FLD_IPSEC_ESP_SPI_SIZE 4 ++ ++/*************************** MPLS fields ***********************************/ ++#define NH_FLD_MPLS_LABEL_STACK (1) ++#define NH_FLD_MPLS_LABEL_STACK_ALL_FIELDS \ ++ ((NH_FLD_MPLS_LABEL_STACK << 1) - 1) ++ ++/*************************** MACSEC fields *********************************/ ++#define NH_FLD_MACSEC_SECTAG (1) ++#define NH_FLD_MACSEC_ALL_FIELDS ((NH_FLD_MACSEC_SECTAG << 1) - 1) ++ ++/*************************** GTP fields ************************************/ ++#define NH_FLD_GTP_TEID (1) ++ ++/* Protocol options */ ++ ++/* Ethernet options */ ++#define NH_OPT_ETH_BROADCAST 1 ++#define NH_OPT_ETH_MULTICAST 2 ++#define NH_OPT_ETH_UNICAST 3 ++#define NH_OPT_ETH_BPDU 4 ++ ++#define NH_ETH_IS_MULTICAST_ADDR(addr) (addr[0] & 0x01) ++/* also applicable for broadcast */ ++ ++/* VLAN options */ ++#define NH_OPT_VLAN_CFI 1 ++ ++/* IPV4 options */ ++#define NH_OPT_IPV4_UNICAST 1 ++#define NH_OPT_IPV4_MULTICAST 2 ++#define NH_OPT_IPV4_BROADCAST 3 ++#define NH_OPT_IPV4_OPTION 4 ++#define NH_OPT_IPV4_FRAG 5 ++#define NH_OPT_IPV4_INITIAL_FRAG 6 ++ ++/* IPV6 options */ ++#define NH_OPT_IPV6_UNICAST 1 ++#define NH_OPT_IPV6_MULTICAST 2 ++#define NH_OPT_IPV6_OPTION 3 ++#define NH_OPT_IPV6_FRAG 4 ++#define NH_OPT_IPV6_INITIAL_FRAG 5 ++ ++/* General IP options (may be used for any version) */ ++#define NH_OPT_IP_FRAG 1 ++#define NH_OPT_IP_INITIAL_FRAG 2 ++#define NH_OPT_IP_OPTION 3 ++ ++/* Minenc. options */ ++#define NH_OPT_MINENCAP_SRC_ADDR_PRESENT 1 ++ ++/* GRE. options */ ++#define NH_OPT_GRE_ROUTING_PRESENT 1 ++ ++/* TCP options */ ++#define NH_OPT_TCP_OPTIONS 1 ++#define NH_OPT_TCP_CONTROL_HIGH_BITS 2 ++#define NH_OPT_TCP_CONTROL_LOW_BITS 3 ++ ++/* CAPWAP options */ ++#define NH_OPT_CAPWAP_DTLS 1 ++ ++enum net_prot { ++ NET_PROT_NONE = 0, ++ NET_PROT_PAYLOAD, ++ NET_PROT_ETH, ++ NET_PROT_VLAN, ++ NET_PROT_IPV4, ++ NET_PROT_IPV6, ++ NET_PROT_IP, ++ NET_PROT_TCP, ++ NET_PROT_UDP, ++ NET_PROT_UDP_LITE, ++ NET_PROT_IPHC, ++ NET_PROT_SCTP, ++ NET_PROT_SCTP_CHUNK_DATA, ++ NET_PROT_PPPOE, ++ NET_PROT_PPP, ++ NET_PROT_PPPMUX, ++ NET_PROT_PPPMUX_SUBFRM, ++ NET_PROT_L2TPV2, ++ NET_PROT_L2TPV3_CTRL, ++ NET_PROT_L2TPV3_SESS, ++ NET_PROT_LLC, ++ NET_PROT_LLC_SNAP, ++ NET_PROT_NLPID, ++ NET_PROT_SNAP, ++ NET_PROT_MPLS, ++ NET_PROT_IPSEC_AH, ++ NET_PROT_IPSEC_ESP, ++ NET_PROT_UDP_ENC_ESP, /* RFC 3948 */ ++ NET_PROT_MACSEC, ++ NET_PROT_GRE, ++ NET_PROT_MINENCAP, ++ NET_PROT_DCCP, ++ NET_PROT_ICMP, ++ NET_PROT_IGMP, ++ NET_PROT_ARP, ++ NET_PROT_CAPWAP_DATA, ++ NET_PROT_CAPWAP_CTRL, ++ NET_PROT_RFC2684, ++ NET_PROT_ICMPV6, ++ NET_PROT_FCOE, ++ NET_PROT_FIP, ++ NET_PROT_ISCSI, ++ NET_PROT_GTP, ++ NET_PROT_USER_DEFINED_L2, ++ NET_PROT_USER_DEFINED_L3, ++ NET_PROT_USER_DEFINED_L4, ++ NET_PROT_USER_DEFINED_L5, ++ NET_PROT_USER_DEFINED_SHIM1, ++ NET_PROT_USER_DEFINED_SHIM2, ++ ++ NET_PROT_DUMMY_LAST ++}; ++ ++/*! IEEE8021.Q */ ++#define NH_IEEE8021Q_ETYPE 0x8100 ++#define NH_IEEE8021Q_HDR(etype, pcp, dei, vlan_id) \ ++ ((((uint32_t)(etype & 0xFFFF)) << 16) | \ ++ (((uint32_t)(pcp & 0x07)) << 13) | \ ++ (((uint32_t)(dei & 0x01)) << 12) | \ ++ (((uint32_t)(vlan_id & 0xFFF)))) ++ ++#endif /* __FSL_NET_H */ +diff --git a/drivers/net/dpaa2/mc/mc_sys.c b/drivers/net/dpaa2/mc/mc_sys.c +new file mode 100644 +index 0000000..0a88cad +--- /dev/null ++++ b/drivers/net/dpaa2/mc/mc_sys.c +@@ -0,0 +1,129 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++ ++/* ODP framework using MC poratl in shared mode. Following ++ changes to introduce Locks must be maintained while ++ merging the FLIB. ++*/ ++ ++/** ++* The mc_spinlock_t type. ++*/ ++typedef struct { ++ volatile int locked; /**< lock status 0 = unlocked, 1 = locked */ ++} mc_spinlock_t; ++ ++/** ++* A static spinlock initializer. ++*/ ++static mc_spinlock_t mc_portal_lock = { 0 }; ++ ++static inline void mc_pause(void) {} ++ ++static inline void mc_spinlock_lock(mc_spinlock_t *sl) ++{ ++ while (__sync_lock_test_and_set(&sl->locked, 1)) ++ while (sl->locked) ++ mc_pause(); ++} ++ ++static inline void mc_spinlock_unlock(mc_spinlock_t *sl) ++{ ++ __sync_lock_release(&sl->locked); ++} ++ ++ ++static int mc_status_to_error(enum mc_cmd_status status) ++{ ++ switch (status) { ++ case MC_CMD_STATUS_OK: ++ return 0; ++ case MC_CMD_STATUS_AUTH_ERR: ++ return -EACCES; /* Token error */ ++ case MC_CMD_STATUS_NO_PRIVILEGE: ++ return -EPERM; /* Permission denied */ ++ case MC_CMD_STATUS_DMA_ERR: ++ return -EIO; /* Input/Output error */ ++ case MC_CMD_STATUS_CONFIG_ERR: ++ return -EINVAL; /* Device not configured */ ++ case MC_CMD_STATUS_TIMEOUT: ++ return -ETIMEDOUT; /* Operation timed out */ ++ case MC_CMD_STATUS_NO_RESOURCE: ++ return -ENAVAIL; /* Resource temporarily unavailable */ ++ case MC_CMD_STATUS_NO_MEMORY: ++ return -ENOMEM; /* Cannot allocate memory */ ++ case MC_CMD_STATUS_BUSY: ++ return -EBUSY; /* Device busy */ ++ case MC_CMD_STATUS_UNSUPPORTED_OP: ++ return -ENOTSUP; /* Operation not supported by device */ ++ case MC_CMD_STATUS_INVALID_STATE: ++ return -ENODEV; /* Invalid device state */ ++ default: ++ break; ++ } ++ ++ /* Not expected to reach here */ ++ return -EINVAL; ++} ++ ++int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd) ++{ ++ enum mc_cmd_status status; ++ ++ if (!mc_io || !mc_io->regs) ++ return -EACCES; ++ ++ /* --- Call lock function here in case portal is shared --- */ ++ mc_spinlock_lock(&mc_portal_lock); ++ ++ mc_write_command(mc_io->regs, cmd); ++ ++ /* Spin until status changes */ ++ do { ++ status = MC_CMD_HDR_READ_STATUS(ioread64(mc_io->regs)); ++ ++ /* --- Call wait function here to prevent blocking --- ++ * Change the loop condition accordingly to exit on timeout. ++ */ ++ } while (status == MC_CMD_STATUS_READY); ++ ++ /* Read the response back into the command buffer */ ++ mc_read_response(mc_io->regs, cmd); ++ ++ /* --- Call unlock function here in case portal is shared --- */ ++ mc_spinlock_unlock(&mc_portal_lock); ++ ++ return mc_status_to_error(status); ++} ++ +diff --git a/drivers/net/dpaa2/qbman/driver/qbman_debug.c b/drivers/net/dpaa2/qbman/driver/qbman_debug.c +new file mode 100644 +index 0000000..e205681 +--- /dev/null ++++ b/drivers/net/dpaa2/qbman/driver/qbman_debug.c +@@ -0,0 +1,926 @@ ++/* Copyright (C) 2015 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY ++ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include "qbman_portal.h" ++#include "qbman_debug.h" ++#include ++ ++/* QBMan portal management command code */ ++#define QBMAN_BP_QUERY 0x32 ++#define QBMAN_FQ_QUERY 0x44 ++#define QBMAN_FQ_QUERY_NP 0x45 ++#define QBMAN_WQ_QUERY 0x47 ++#define QBMAN_CGR_QUERY 0x51 ++#define QBMAN_WRED_QUERY 0x54 ++#define QBMAN_CGR_STAT_QUERY 0x55 ++#define QBMAN_CGR_STAT_QUERY_CLR 0x56 ++ ++enum qbman_attr_usage_e { ++ qbman_attr_usage_fq, ++ qbman_attr_usage_bpool, ++ qbman_attr_usage_cgr, ++ qbman_attr_usage_wqchan ++}; ++ ++struct int_qbman_attr { ++ uint32_t words[32]; ++ enum qbman_attr_usage_e usage; ++}; ++ ++#define attr_type_set(a, e) \ ++{ \ ++ struct qbman_attr *__attr = a; \ ++ enum qbman_attr_usage_e __usage = e; \ ++ ((struct int_qbman_attr *)__attr)->usage = __usage; \ ++} ++ ++#define ATTR32(d) (&(d)->dont_manipulate_directly[0]) ++#define ATTR32_1(d) (&(d)->dont_manipulate_directly[16]) ++ ++static struct qb_attr_code code_bp_bpid = QB_CODE(0, 16, 16); ++static struct qb_attr_code code_bp_bdi = QB_CODE(1, 16, 1); ++static struct qb_attr_code code_bp_va = QB_CODE(1, 17, 1); ++static struct qb_attr_code code_bp_wae = QB_CODE(1, 18, 1); ++static struct qb_attr_code code_bp_swdet = QB_CODE(4, 0, 16); ++static struct qb_attr_code code_bp_swdxt = QB_CODE(4, 16, 16); ++static struct qb_attr_code code_bp_hwdet = QB_CODE(5, 0, 16); ++static struct qb_attr_code code_bp_hwdxt = QB_CODE(5, 16, 16); ++static struct qb_attr_code code_bp_swset = QB_CODE(6, 0, 16); ++static struct qb_attr_code code_bp_swsxt = QB_CODE(6, 16, 16); ++static struct qb_attr_code code_bp_vbpid = QB_CODE(7, 0, 14); ++static struct qb_attr_code code_bp_icid = QB_CODE(7, 16, 15); ++static struct qb_attr_code code_bp_pl = QB_CODE(7, 31, 1); ++static struct qb_attr_code code_bp_bpscn_addr_lo = QB_CODE(8, 0, 32); ++static struct qb_attr_code code_bp_bpscn_addr_hi = QB_CODE(9, 0, 32); ++static struct qb_attr_code code_bp_bpscn_ctx_lo = QB_CODE(10, 0, 32); ++static struct qb_attr_code code_bp_bpscn_ctx_hi = QB_CODE(11, 0, 32); ++static struct qb_attr_code code_bp_hw_targ = QB_CODE(12, 0, 16); ++static struct qb_attr_code code_bp_state = QB_CODE(1, 24, 3); ++static struct qb_attr_code code_bp_fill = QB_CODE(2 , 0, 32); ++static struct qb_attr_code code_bp_hdptr = QB_CODE(3, 0, 32); ++static struct qb_attr_code code_bp_sdcnt = QB_CODE(13, 0, 8); ++static struct qb_attr_code code_bp_hdcnt = QB_CODE(13, 8, 8); ++static struct qb_attr_code code_bp_sscnt = QB_CODE(13, 16, 8); ++ ++static void qbman_bp_attr_clear(struct qbman_attr *a) ++{ ++ memset(a, 0, sizeof(*a)); ++ attr_type_set(a, qbman_attr_usage_bpool); ++} ++ ++int qbman_bp_query(struct qbman_swp *s, uint32_t bpid, ++ struct qbman_attr *a) ++{ ++ uint32_t *p; ++ uint32_t rslt; ++ uint32_t *attr = ATTR32(a); ++ ++ qbman_bp_attr_clear(a); ++ ++ /* Start the management command */ ++ p = qbman_swp_mc_start(s); ++ if (!p) ++ return -EBUSY; ++ ++ /* Encode the caller-provided attributes */ ++ qb_attr_code_encode(&code_bp_bpid, p, bpid); ++ ++ /* Complete the management command */ ++ p = qbman_swp_mc_complete(s, p, p[0] | QBMAN_BP_QUERY); ++ ++ /* Decode the outcome */ ++ rslt = qb_attr_code_decode(&code_generic_rslt, p); ++ BUG_ON(qb_attr_code_decode(&code_generic_verb, p) != QBMAN_BP_QUERY); ++ ++ /* Determine success or failure */ ++ if (unlikely(rslt != QBMAN_MC_RSLT_OK)) { ++ pr_err("Query of BPID 0x%x failed, code=0x%02x\n", bpid, rslt); ++ return -EIO; ++ } ++ ++ /* For the query, word[0] of the result contains only the ++ * verb/rslt fields, so skip word[0]. ++ */ ++ word_copy(&attr[1], &p[1], 15); ++ return 0; ++} ++ ++void qbman_bp_attr_get_bdi(struct qbman_attr *a, int *bdi, int *va, int *wae) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ *bdi = !!qb_attr_code_decode(&code_bp_bdi, p); ++ *va = !!qb_attr_code_decode(&code_bp_va, p); ++ *wae = !!qb_attr_code_decode(&code_bp_wae, p); ++} ++ ++static uint32_t qbman_bp_thresh_to_value(uint32_t val) ++{ ++ return (val & 0xff) << ((val & 0xf00) >> 8); ++} ++ ++void qbman_bp_attr_get_swdet(struct qbman_attr *a, uint32_t *swdet) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ *swdet = qbman_bp_thresh_to_value(qb_attr_code_decode(&code_bp_swdet, ++ p)); ++} ++void qbman_bp_attr_get_swdxt(struct qbman_attr *a, uint32_t *swdxt) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ *swdxt = qbman_bp_thresh_to_value(qb_attr_code_decode(&code_bp_swdxt, ++ p)); ++} ++void qbman_bp_attr_get_hwdet(struct qbman_attr *a, uint32_t *hwdet) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ *hwdet = qbman_bp_thresh_to_value(qb_attr_code_decode(&code_bp_hwdet, ++ p)); ++} ++void qbman_bp_attr_get_hwdxt(struct qbman_attr *a, uint32_t *hwdxt) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ *hwdxt = qbman_bp_thresh_to_value(qb_attr_code_decode(&code_bp_hwdxt, ++ p)); ++} ++ ++void qbman_bp_attr_get_swset(struct qbman_attr *a, uint32_t *swset) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ *swset = qbman_bp_thresh_to_value(qb_attr_code_decode(&code_bp_swset, ++ p)); ++} ++ ++void qbman_bp_attr_get_swsxt(struct qbman_attr *a, uint32_t *swsxt) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ *swsxt = qbman_bp_thresh_to_value(qb_attr_code_decode(&code_bp_swsxt, ++ p)); ++} ++ ++void qbman_bp_attr_get_vbpid(struct qbman_attr *a, uint32_t *vbpid) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ *vbpid = qb_attr_code_decode(&code_bp_vbpid, p); ++} ++ ++void qbman_bp_attr_get_icid(struct qbman_attr *a, uint32_t *icid, int *pl) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ *icid = qb_attr_code_decode(&code_bp_icid, p); ++ *pl = !!qb_attr_code_decode(&code_bp_pl, p); ++} ++ ++void qbman_bp_attr_get_bpscn_addr(struct qbman_attr *a, uint64_t *bpscn_addr) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ *bpscn_addr = ((uint64_t)qb_attr_code_decode(&code_bp_bpscn_addr_hi, ++ p) << 32) | ++ (uint64_t)qb_attr_code_decode(&code_bp_bpscn_addr_lo, ++ p); ++} ++ ++void qbman_bp_attr_get_bpscn_ctx(struct qbman_attr *a, uint64_t *bpscn_ctx) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ *bpscn_ctx = ((uint64_t)qb_attr_code_decode(&code_bp_bpscn_ctx_hi, p) ++ << 32) | ++ (uint64_t)qb_attr_code_decode(&code_bp_bpscn_ctx_lo, ++ p); ++} ++ ++void qbman_bp_attr_get_hw_targ(struct qbman_attr *a, uint32_t *hw_targ) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ *hw_targ = qb_attr_code_decode(&code_bp_hw_targ, p); ++} ++ ++int qbman_bp_info_has_free_bufs(struct qbman_attr *a) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ return !(int)(qb_attr_code_decode(&code_bp_state, p) & 0x1); ++} ++ ++int qbman_bp_info_is_depleted(struct qbman_attr *a) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ return (int)(qb_attr_code_decode(&code_bp_state, p) & 0x2); ++} ++ ++int qbman_bp_info_is_surplus(struct qbman_attr *a) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ return (int)(qb_attr_code_decode(&code_bp_state, p) & 0x4); ++} ++ ++uint32_t qbman_bp_info_num_free_bufs(struct qbman_attr *a) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ return qb_attr_code_decode(&code_bp_fill, p); ++} ++ ++uint32_t qbman_bp_info_hdptr(struct qbman_attr *a) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ return qb_attr_code_decode(&code_bp_hdptr, p); ++} ++ ++uint32_t qbman_bp_info_sdcnt(struct qbman_attr *a) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ return qb_attr_code_decode(&code_bp_sdcnt, p); ++} ++ ++uint32_t qbman_bp_info_hdcnt(struct qbman_attr *a) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ return qb_attr_code_decode(&code_bp_hdcnt, p); ++} ++ ++uint32_t qbman_bp_info_sscnt(struct qbman_attr *a) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ return qb_attr_code_decode(&code_bp_sscnt, p); ++} ++ ++static struct qb_attr_code code_fq_fqid = QB_CODE(1, 0, 24); ++static struct qb_attr_code code_fq_cgrid = QB_CODE(2, 16, 16); ++static struct qb_attr_code code_fq_destwq = QB_CODE(3, 0, 15); ++static struct qb_attr_code code_fq_fqctrl = QB_CODE(3, 24, 8); ++static struct qb_attr_code code_fq_icscred = QB_CODE(4, 0, 15); ++static struct qb_attr_code code_fq_tdthresh = QB_CODE(4, 16, 13); ++static struct qb_attr_code code_fq_oa_len = QB_CODE(5, 0, 12); ++static struct qb_attr_code code_fq_oa_ics = QB_CODE(5, 14, 1); ++static struct qb_attr_code code_fq_oa_cgr = QB_CODE(5, 15, 1); ++static struct qb_attr_code code_fq_mctl_bdi = QB_CODE(5, 24, 1); ++static struct qb_attr_code code_fq_mctl_ff = QB_CODE(5, 25, 1); ++static struct qb_attr_code code_fq_mctl_va = QB_CODE(5, 26, 1); ++static struct qb_attr_code code_fq_mctl_ps = QB_CODE(5, 27, 1); ++static struct qb_attr_code code_fq_ctx_lower32 = QB_CODE(6, 0, 32); ++static struct qb_attr_code code_fq_ctx_upper32 = QB_CODE(7, 0, 32); ++static struct qb_attr_code code_fq_icid = QB_CODE(8, 0, 15); ++static struct qb_attr_code code_fq_pl = QB_CODE(8, 15, 1); ++static struct qb_attr_code code_fq_vfqid = QB_CODE(9, 0, 24); ++static struct qb_attr_code code_fq_erfqid = QB_CODE(10, 0, 24); ++ ++static void qbman_fq_attr_clear(struct qbman_attr *a) ++{ ++ memset(a, 0, sizeof(*a)); ++ attr_type_set(a, qbman_attr_usage_fq); ++} ++ ++/* FQ query function for programmable fields */ ++int qbman_fq_query(struct qbman_swp *s, uint32_t fqid, struct qbman_attr *desc) ++{ ++ uint32_t *p; ++ uint32_t rslt; ++ uint32_t *d = ATTR32(desc); ++ ++ qbman_fq_attr_clear(desc); ++ ++ p = qbman_swp_mc_start(s); ++ if (!p) ++ return -EBUSY; ++ qb_attr_code_encode(&code_fq_fqid, p, fqid); ++ p = qbman_swp_mc_complete(s, p, QBMAN_FQ_QUERY); ++ ++ /* Decode the outcome */ ++ rslt = qb_attr_code_decode(&code_generic_rslt, p); ++ BUG_ON(qb_attr_code_decode(&code_generic_verb, p) != QBMAN_FQ_QUERY); ++ ++ /* Determine success or failure */ ++ if (unlikely(rslt != QBMAN_MC_RSLT_OK)) { ++ pr_err("Query of FQID 0x%x failed, code=0x%02x\n", ++ fqid, rslt); ++ return -EIO; ++ } ++ /* For the configure, word[0] of the command contains only the WE-mask. ++ * For the query, word[0] of the result contains only the verb/rslt ++ * fields. Skip word[0] in the latter case. */ ++ word_copy(&d[1], &p[1], 15); ++ return 0; ++} ++ ++void qbman_fq_attr_get_fqctrl(struct qbman_attr *d, uint32_t *fqctrl) ++{ ++ uint32_t *p = ATTR32(d); ++ ++ *fqctrl = qb_attr_code_decode(&code_fq_fqctrl, p); ++} ++ ++void qbman_fq_attr_get_cgrid(struct qbman_attr *d, uint32_t *cgrid) ++{ ++ uint32_t *p = ATTR32(d); ++ ++ *cgrid = qb_attr_code_decode(&code_fq_cgrid, p); ++} ++ ++void qbman_fq_attr_get_destwq(struct qbman_attr *d, uint32_t *destwq) ++{ ++ uint32_t *p = ATTR32(d); ++ ++ *destwq = qb_attr_code_decode(&code_fq_destwq, p); ++} ++ ++void qbman_fq_attr_get_icscred(struct qbman_attr *d, uint32_t *icscred) ++{ ++ uint32_t *p = ATTR32(d); ++ ++ *icscred = qb_attr_code_decode(&code_fq_icscred, p); ++} ++ ++static struct qb_attr_code code_tdthresh_exp = QB_CODE(0, 0, 5); ++static struct qb_attr_code code_tdthresh_mant = QB_CODE(0, 5, 8); ++static uint32_t qbman_thresh_to_value(uint32_t val) ++{ ++ uint32_t m, e; ++ ++ m = qb_attr_code_decode(&code_tdthresh_mant, &val); ++ e = qb_attr_code_decode(&code_tdthresh_exp, &val); ++ return m << e; ++} ++ ++void qbman_fq_attr_get_tdthresh(struct qbman_attr *d, uint32_t *tdthresh) ++{ ++ uint32_t *p = ATTR32(d); ++ ++ *tdthresh = qbman_thresh_to_value(qb_attr_code_decode(&code_fq_tdthresh, ++ p)); ++} ++ ++void qbman_fq_attr_get_oa(struct qbman_attr *d, ++ int *oa_ics, int *oa_cgr, int32_t *oa_len) ++{ ++ uint32_t *p = ATTR32(d); ++ ++ *oa_ics = !!qb_attr_code_decode(&code_fq_oa_ics, p); ++ *oa_cgr = !!qb_attr_code_decode(&code_fq_oa_cgr, p); ++ *oa_len = qb_attr_code_makesigned(&code_fq_oa_len, ++ qb_attr_code_decode(&code_fq_oa_len, p)); ++} ++ ++void qbman_fq_attr_get_mctl(struct qbman_attr *d, ++ int *bdi, int *ff, int *va, int *ps) ++{ ++ uint32_t *p = ATTR32(d); ++ ++ *bdi = !!qb_attr_code_decode(&code_fq_mctl_bdi, p); ++ *ff = !!qb_attr_code_decode(&code_fq_mctl_ff, p); ++ *va = !!qb_attr_code_decode(&code_fq_mctl_va, p); ++ *ps = !!qb_attr_code_decode(&code_fq_mctl_ps, p); ++} ++ ++void qbman_fq_attr_get_ctx(struct qbman_attr *d, uint32_t *hi, uint32_t *lo) ++{ ++ uint32_t *p = ATTR32(d); ++ ++ *hi = qb_attr_code_decode(&code_fq_ctx_upper32, p); ++ *lo = qb_attr_code_decode(&code_fq_ctx_lower32, p); ++} ++ ++void qbman_fq_attr_get_icid(struct qbman_attr *d, uint32_t *icid, int *pl) ++{ ++ uint32_t *p = ATTR32(d); ++ ++ *icid = qb_attr_code_decode(&code_fq_icid, p); ++ *pl = !!qb_attr_code_decode(&code_fq_pl, p); ++} ++ ++void qbman_fq_attr_get_vfqid(struct qbman_attr *d, uint32_t *vfqid) ++{ ++ uint32_t *p = ATTR32(d); ++ ++ *vfqid = qb_attr_code_decode(&code_fq_vfqid, p); ++} ++ ++void qbman_fq_attr_get_erfqid(struct qbman_attr *d, uint32_t *erfqid) ++{ ++ uint32_t *p = ATTR32(d); ++ ++ *erfqid = qb_attr_code_decode(&code_fq_erfqid, p); ++} ++ ++/* Query FQ Non-Programmalbe Fields */ ++static struct qb_attr_code code_fq_np_state = QB_CODE(0, 16, 3); ++static struct qb_attr_code code_fq_np_fe = QB_CODE(0, 19, 1); ++static struct qb_attr_code code_fq_np_x = QB_CODE(0, 20, 1); ++static struct qb_attr_code code_fq_np_r = QB_CODE(0, 21, 1); ++static struct qb_attr_code code_fq_np_oe = QB_CODE(0, 22, 1); ++static struct qb_attr_code code_fq_np_frm_cnt = QB_CODE(6, 0, 24); ++static struct qb_attr_code code_fq_np_byte_cnt = QB_CODE(7, 0, 32); ++ ++int qbman_fq_query_state(struct qbman_swp *s, uint32_t fqid, ++ struct qbman_attr *state) ++{ ++ uint32_t *p; ++ uint32_t rslt; ++ uint32_t *d = ATTR32(state); ++ ++ qbman_fq_attr_clear(state); ++ ++ p = qbman_swp_mc_start(s); ++ if (!p) ++ return -EBUSY; ++ qb_attr_code_encode(&code_fq_fqid, p, fqid); ++ p = qbman_swp_mc_complete(s, p, QBMAN_FQ_QUERY_NP); ++ ++ /* Decode the outcome */ ++ rslt = qb_attr_code_decode(&code_generic_rslt, p); ++ BUG_ON(qb_attr_code_decode(&code_generic_verb, p) != QBMAN_FQ_QUERY_NP); ++ ++ /* Determine success or failure */ ++ if (unlikely(rslt != QBMAN_MC_RSLT_OK)) { ++ pr_err("Query NP fields of FQID 0x%x failed, code=0x%02x\n", ++ fqid, rslt); ++ return -EIO; ++ } ++ word_copy(&d[0], &p[0], 16); ++ return 0; ++} ++ ++uint32_t qbman_fq_state_schedstate(const struct qbman_attr *state) ++{ ++ const uint32_t *p = ATTR32(state); ++ ++ return qb_attr_code_decode(&code_fq_np_state, p); ++} ++ ++int qbman_fq_state_force_eligible(const struct qbman_attr *state) ++{ ++ const uint32_t *p = ATTR32(state); ++ ++ return !!qb_attr_code_decode(&code_fq_np_fe, p); ++} ++ ++int qbman_fq_state_xoff(const struct qbman_attr *state) ++{ ++ const uint32_t *p = ATTR32(state); ++ ++ return !!qb_attr_code_decode(&code_fq_np_x, p); ++} ++ ++int qbman_fq_state_retirement_pending(const struct qbman_attr *state) ++{ ++ const uint32_t *p = ATTR32(state); ++ ++ return !!qb_attr_code_decode(&code_fq_np_r, p); ++} ++ ++int qbman_fq_state_overflow_error(const struct qbman_attr *state) ++{ ++ const uint32_t *p = ATTR32(state); ++ ++ return !!qb_attr_code_decode(&code_fq_np_oe, p); ++} ++ ++uint32_t qbman_fq_state_frame_count(const struct qbman_attr *state) ++{ ++ const uint32_t *p = ATTR32(state); ++ ++ return qb_attr_code_decode(&code_fq_np_frm_cnt, p); ++} ++ ++uint32_t qbman_fq_state_byte_count(const struct qbman_attr *state) ++{ ++ const uint32_t *p = ATTR32(state); ++ ++ return qb_attr_code_decode(&code_fq_np_byte_cnt, p); ++} ++ ++/* Query CGR */ ++static struct qb_attr_code code_cgr_cgid = QB_CODE(0, 16, 16); ++static struct qb_attr_code code_cgr_cscn_wq_en_enter = QB_CODE(2, 0, 1); ++static struct qb_attr_code code_cgr_cscn_wq_en_exit = QB_CODE(2, 1, 1); ++static struct qb_attr_code code_cgr_cscn_wq_icd = QB_CODE(2, 2, 1); ++static struct qb_attr_code code_cgr_mode = QB_CODE(3, 16, 2); ++static struct qb_attr_code code_cgr_rej_cnt_mode = QB_CODE(3, 18, 1); ++static struct qb_attr_code code_cgr_cscn_bdi = QB_CODE(3, 19, 1); ++static struct qb_attr_code code_cgr_cscn_wr_en_enter = QB_CODE(3, 24, 1); ++static struct qb_attr_code code_cgr_cscn_wr_en_exit = QB_CODE(3, 25, 1); ++static struct qb_attr_code code_cgr_cg_wr_ae = QB_CODE(3, 26, 1); ++static struct qb_attr_code code_cgr_cscn_dcp_en = QB_CODE(3, 27, 1); ++static struct qb_attr_code code_cgr_cg_wr_va = QB_CODE(3, 28, 1); ++static struct qb_attr_code code_cgr_i_cnt_wr_en = QB_CODE(4, 0, 1); ++static struct qb_attr_code code_cgr_i_cnt_wr_bnd = QB_CODE(4, 1, 5); ++static struct qb_attr_code code_cgr_td_en = QB_CODE(4, 8, 1); ++static struct qb_attr_code code_cgr_cs_thres = QB_CODE(4, 16, 13); ++static struct qb_attr_code code_cgr_cs_thres_x = QB_CODE(5, 0, 13); ++static struct qb_attr_code code_cgr_td_thres = QB_CODE(5, 16, 13); ++static struct qb_attr_code code_cgr_cscn_tdcp = QB_CODE(6, 0, 16); ++static struct qb_attr_code code_cgr_cscn_wqid = QB_CODE(6, 16, 16); ++static struct qb_attr_code code_cgr_cscn_vcgid = QB_CODE(7, 0, 16); ++static struct qb_attr_code code_cgr_cg_icid = QB_CODE(7, 16, 15); ++static struct qb_attr_code code_cgr_cg_pl = QB_CODE(7, 31, 1); ++static struct qb_attr_code code_cgr_cg_wr_addr_lo = QB_CODE(8, 0, 32); ++static struct qb_attr_code code_cgr_cg_wr_addr_hi = QB_CODE(9, 0, 32); ++static struct qb_attr_code code_cgr_cscn_ctx_lo = QB_CODE(10, 0, 32); ++static struct qb_attr_code code_cgr_cscn_ctx_hi = QB_CODE(11, 0, 32); ++ ++static void qbman_cgr_attr_clear(struct qbman_attr *a) ++{ ++ memset(a, 0, sizeof(*a)); ++ attr_type_set(a, qbman_attr_usage_cgr); ++} ++ ++int qbman_cgr_query(struct qbman_swp *s, uint32_t cgid, struct qbman_attr *attr) ++{ ++ uint32_t *p; ++ uint32_t verb, rslt; ++ uint32_t *d[2]; ++ int i; ++ uint32_t query_verb; ++ ++ d[0] = ATTR32(attr); ++ d[1] = ATTR32_1(attr); ++ ++ qbman_cgr_attr_clear(attr); ++ ++ for (i = 0; i < 2; i++) { ++ p = qbman_swp_mc_start(s); ++ if (!p) ++ return -EBUSY; ++ query_verb = i ? QBMAN_WRED_QUERY : QBMAN_CGR_QUERY; ++ ++ qb_attr_code_encode(&code_cgr_cgid, p, cgid); ++ p = qbman_swp_mc_complete(s, p, p[0] | query_verb); ++ ++ /* Decode the outcome */ ++ verb = qb_attr_code_decode(&code_generic_verb, p); ++ rslt = qb_attr_code_decode(&code_generic_rslt, p); ++ BUG_ON(verb != query_verb); ++ ++ /* Determine success or failure */ ++ if (unlikely(rslt != QBMAN_MC_RSLT_OK)) { ++ pr_err("Query CGID 0x%x failed,", cgid); ++ pr_err(" verb=0x%02x, code=0x%02x\n", verb, rslt); ++ return -EIO; ++ } ++ /* For the configure, word[0] of the command contains only the ++ * verb/cgid. For the query, word[0] of the result contains ++ * only the verb/rslt fields. Skip word[0] in the latter case. ++ */ ++ word_copy(&d[i][1], &p[1], 15); ++ } ++ return 0; ++} ++ ++void qbman_cgr_attr_get_ctl1(struct qbman_attr *d, int *cscn_wq_en_enter, ++ int *cscn_wq_en_exit, int *cscn_wq_icd) ++ { ++ uint32_t *p = ATTR32(d); ++ *cscn_wq_en_enter = !!qb_attr_code_decode(&code_cgr_cscn_wq_en_enter, ++ p); ++ *cscn_wq_en_exit = !!qb_attr_code_decode(&code_cgr_cscn_wq_en_exit, p); ++ *cscn_wq_icd = !!qb_attr_code_decode(&code_cgr_cscn_wq_icd, p); ++} ++ ++void qbman_cgr_attr_get_mode(struct qbman_attr *d, uint32_t *mode, ++ int *rej_cnt_mode, int *cscn_bdi) ++{ ++ uint32_t *p = ATTR32(d); ++ *mode = qb_attr_code_decode(&code_cgr_mode, p); ++ *rej_cnt_mode = !!qb_attr_code_decode(&code_cgr_rej_cnt_mode, p); ++ *cscn_bdi = !!qb_attr_code_decode(&code_cgr_cscn_bdi, p); ++} ++ ++void qbman_cgr_attr_get_ctl2(struct qbman_attr *d, int *cscn_wr_en_enter, ++ int *cscn_wr_en_exit, int *cg_wr_ae, ++ int *cscn_dcp_en, int *cg_wr_va) ++{ ++ uint32_t *p = ATTR32(d); ++ *cscn_wr_en_enter = !!qb_attr_code_decode(&code_cgr_cscn_wr_en_enter, ++ p); ++ *cscn_wr_en_exit = !!qb_attr_code_decode(&code_cgr_cscn_wr_en_exit, p); ++ *cg_wr_ae = !!qb_attr_code_decode(&code_cgr_cg_wr_ae, p); ++ *cscn_dcp_en = !!qb_attr_code_decode(&code_cgr_cscn_dcp_en, p); ++ *cg_wr_va = !!qb_attr_code_decode(&code_cgr_cg_wr_va, p); ++} ++ ++void qbman_cgr_attr_get_iwc(struct qbman_attr *d, int *i_cnt_wr_en, ++ uint32_t *i_cnt_wr_bnd) ++{ ++ uint32_t *p = ATTR32(d); ++ *i_cnt_wr_en = !!qb_attr_code_decode(&code_cgr_i_cnt_wr_en, p); ++ *i_cnt_wr_bnd = qb_attr_code_decode(&code_cgr_i_cnt_wr_bnd, p); ++} ++ ++void qbman_cgr_attr_get_tdc(struct qbman_attr *d, int *td_en) ++{ ++ uint32_t *p = ATTR32(d); ++ *td_en = !!qb_attr_code_decode(&code_cgr_td_en, p); ++} ++ ++void qbman_cgr_attr_get_cs_thres(struct qbman_attr *d, uint32_t *cs_thres) ++{ ++ uint32_t *p = ATTR32(d); ++ *cs_thres = qbman_thresh_to_value(qb_attr_code_decode( ++ &code_cgr_cs_thres, p)); ++} ++ ++void qbman_cgr_attr_get_cs_thres_x(struct qbman_attr *d, ++ uint32_t *cs_thres_x) ++{ ++ uint32_t *p = ATTR32(d); ++ *cs_thres_x = qbman_thresh_to_value(qb_attr_code_decode( ++ &code_cgr_cs_thres_x, p)); ++} ++ ++void qbman_cgr_attr_get_td_thres(struct qbman_attr *d, uint32_t *td_thres) ++{ ++ uint32_t *p = ATTR32(d); ++ *td_thres = qbman_thresh_to_value(qb_attr_code_decode( ++ &code_cgr_td_thres, p)); ++} ++ ++void qbman_cgr_attr_get_cscn_tdcp(struct qbman_attr *d, uint32_t *cscn_tdcp) ++{ ++ uint32_t *p = ATTR32(d); ++ *cscn_tdcp = qb_attr_code_decode(&code_cgr_cscn_tdcp, p); ++} ++ ++void qbman_cgr_attr_get_cscn_wqid(struct qbman_attr *d, uint32_t *cscn_wqid) ++{ ++ uint32_t *p = ATTR32(d); ++ *cscn_wqid = qb_attr_code_decode(&code_cgr_cscn_wqid, p); ++} ++ ++void qbman_cgr_attr_get_cscn_vcgid(struct qbman_attr *d, ++ uint32_t *cscn_vcgid) ++{ ++ uint32_t *p = ATTR32(d); ++ *cscn_vcgid = qb_attr_code_decode(&code_cgr_cscn_vcgid, p); ++} ++ ++void qbman_cgr_attr_get_cg_icid(struct qbman_attr *d, uint32_t *icid, ++ int *pl) ++{ ++ uint32_t *p = ATTR32(d); ++ *icid = qb_attr_code_decode(&code_cgr_cg_icid, p); ++ *pl = !!qb_attr_code_decode(&code_cgr_cg_pl, p); ++} ++ ++void qbman_cgr_attr_get_cg_wr_addr(struct qbman_attr *d, ++ uint64_t *cg_wr_addr) ++{ ++ uint32_t *p = ATTR32(d); ++ *cg_wr_addr = ((uint64_t)qb_attr_code_decode(&code_cgr_cg_wr_addr_hi, ++ p) << 32) | ++ (uint64_t)qb_attr_code_decode(&code_cgr_cg_wr_addr_lo, ++ p); ++} ++ ++void qbman_cgr_attr_get_cscn_ctx(struct qbman_attr *d, uint64_t *cscn_ctx) ++{ ++ uint32_t *p = ATTR32(d); ++ *cscn_ctx = ((uint64_t)qb_attr_code_decode(&code_cgr_cscn_ctx_hi, p) ++ << 32) | ++ (uint64_t)qb_attr_code_decode(&code_cgr_cscn_ctx_lo, p); ++} ++ ++#define WRED_EDP_WORD(n) (18 + n/4) ++#define WRED_EDP_OFFSET(n) (8 * (n % 4)) ++#define WRED_PARM_DP_WORD(n) (n + 20) ++#define WRED_WE_EDP(n) (16 + n * 2) ++#define WRED_WE_PARM_DP(n) (17 + n * 2) ++void qbman_cgr_attr_wred_get_edp(struct qbman_attr *d, uint32_t idx, ++ int *edp) ++{ ++ uint32_t *p = ATTR32(d); ++ struct qb_attr_code code_wred_edp = QB_CODE(WRED_EDP_WORD(idx), ++ WRED_EDP_OFFSET(idx), 8); ++ *edp = (int)qb_attr_code_decode(&code_wred_edp, p); ++} ++ ++void qbman_cgr_attr_wred_dp_decompose(uint32_t dp, uint64_t *minth, ++ uint64_t *maxth, uint8_t *maxp) ++{ ++ uint8_t ma, mn, step_i, step_s, pn; ++ ++ ma = (uint8_t)(dp >> 24); ++ mn = (uint8_t)(dp >> 19) & 0x1f; ++ step_i = (uint8_t)(dp >> 11); ++ step_s = (uint8_t)(dp >> 6) & 0x1f; ++ pn = (uint8_t)dp & 0x3f; ++ ++ *maxp = (uint8_t)(((pn<<2) * 100)/256); ++ ++ if (mn == 0) ++ *maxth = ma; ++ else ++ *maxth = ((ma+256) * (1<<(mn-1))); ++ ++ if (step_s == 0) ++ *minth = *maxth - step_i; ++ else ++ *minth = *maxth - (256 + step_i) * (1<<(step_s - 1)); ++} ++ ++void qbman_cgr_attr_wred_get_parm_dp(struct qbman_attr *d, uint32_t idx, ++ uint32_t *dp) ++{ ++ uint32_t *p = ATTR32(d); ++ struct qb_attr_code code_wred_parm_dp = QB_CODE(WRED_PARM_DP_WORD(idx), ++ 0, 8); ++ *dp = qb_attr_code_decode(&code_wred_parm_dp, p); ++} ++ ++/* Query CGR/CCGR/CQ statistics */ ++static struct qb_attr_code code_cgr_stat_ct = QB_CODE(4, 0, 32); ++static struct qb_attr_code code_cgr_stat_frame_cnt_lo = QB_CODE(4, 0, 32); ++static struct qb_attr_code code_cgr_stat_frame_cnt_hi = QB_CODE(5, 0, 8); ++static struct qb_attr_code code_cgr_stat_byte_cnt_lo = QB_CODE(6, 0, 32); ++static struct qb_attr_code code_cgr_stat_byte_cnt_hi = QB_CODE(7, 0, 16); ++static int qbman_cgr_statistics_query(struct qbman_swp *s, uint32_t cgid, ++ int clear, uint32_t command_type, ++ uint64_t *frame_cnt, uint64_t *byte_cnt) ++{ ++ uint32_t *p; ++ uint32_t verb, rslt; ++ uint32_t query_verb; ++ uint32_t hi, lo; ++ ++ p = qbman_swp_mc_start(s); ++ if (!p) ++ return -EBUSY; ++ ++ qb_attr_code_encode(&code_cgr_cgid, p, cgid); ++ if (command_type < 2) ++ qb_attr_code_encode(&code_cgr_stat_ct, p, command_type); ++ query_verb = clear ? ++ QBMAN_CGR_STAT_QUERY_CLR : QBMAN_CGR_STAT_QUERY; ++ p = qbman_swp_mc_complete(s, p, p[0] | query_verb); ++ ++ /* Decode the outcome */ ++ verb = qb_attr_code_decode(&code_generic_verb, p); ++ rslt = qb_attr_code_decode(&code_generic_rslt, p); ++ BUG_ON(verb != query_verb); ++ ++ /* Determine success or failure */ ++ if (unlikely(rslt != QBMAN_MC_RSLT_OK)) { ++ pr_err("Query statistics of CGID 0x%x failed,", cgid); ++ pr_err(" verb=0x%02x code=0x%02x\n", verb, rslt); ++ return -EIO; ++ } ++ ++ if (*frame_cnt) { ++ hi = qb_attr_code_decode(&code_cgr_stat_frame_cnt_hi, p); ++ lo = qb_attr_code_decode(&code_cgr_stat_frame_cnt_lo, p); ++ *frame_cnt = ((uint64_t)hi << 32) | (uint64_t)lo; ++ } ++ if (*byte_cnt) { ++ hi = qb_attr_code_decode(&code_cgr_stat_byte_cnt_hi, p); ++ lo = qb_attr_code_decode(&code_cgr_stat_byte_cnt_lo, p); ++ *byte_cnt = ((uint64_t)hi << 32) | (uint64_t)lo; ++ } ++ ++ return 0; ++} ++ ++int qbman_cgr_reject_statistics(struct qbman_swp *s, uint32_t cgid, int clear, ++ uint64_t *frame_cnt, uint64_t *byte_cnt) ++{ ++ return qbman_cgr_statistics_query(s, cgid, clear, 0xff, ++ frame_cnt, byte_cnt); ++} ++ ++int qbman_ccgr_reject_statistics(struct qbman_swp *s, uint32_t cgid, int clear, ++ uint64_t *frame_cnt, uint64_t *byte_cnt) ++{ ++ return qbman_cgr_statistics_query(s, cgid, clear, 1, ++ frame_cnt, byte_cnt); ++} ++ ++int qbman_cq_dequeue_statistics(struct qbman_swp *s, uint32_t cgid, int clear, ++ uint64_t *frame_cnt, uint64_t *byte_cnt) ++{ ++ return qbman_cgr_statistics_query(s, cgid, clear, 0, ++ frame_cnt, byte_cnt); ++} ++ ++/* WQ Chan Query */ ++static struct qb_attr_code code_wqchan_chanid = QB_CODE(0, 16, 16); ++static struct qb_attr_code code_wqchan_cdan_ctx_lo = QB_CODE(2, 0, 32); ++static struct qb_attr_code code_wqchan_cdan_ctx_hi = QB_CODE(3, 0, 32); ++static struct qb_attr_code code_wqchan_cdan_wqid = QB_CODE(1, 16, 16); ++static struct qb_attr_code code_wqchan_ctrl = QB_CODE(1, 8, 8); ++ ++static void qbman_wqchan_attr_clear(struct qbman_attr *a) ++{ ++ memset(a, 0, sizeof(*a)); ++ attr_type_set(a, qbman_attr_usage_wqchan); ++} ++ ++int qbman_wqchan_query(struct qbman_swp *s, uint16_t chanid, ++ struct qbman_attr *a) ++{ ++ uint32_t *p; ++ uint32_t rslt; ++ uint32_t *attr = ATTR32(a); ++ ++ qbman_wqchan_attr_clear(a); ++ ++ /* Start the management command */ ++ p = qbman_swp_mc_start(s); ++ if (!p) ++ return -EBUSY; ++ ++ /* Encode the caller-provided attributes */ ++ qb_attr_code_encode(&code_wqchan_chanid, p, chanid); ++ ++ /* Complete the management command */ ++ p = qbman_swp_mc_complete(s, p, p[0] | QBMAN_WQ_QUERY); ++ ++ /* Decode the outcome */ ++ rslt = qb_attr_code_decode(&code_generic_rslt, p); ++ BUG_ON(qb_attr_code_decode(&code_generic_verb, p); != QBMAN_WQ_QUERY); ++ ++ /* Determine success or failure */ ++ if (unlikely(rslt != QBMAN_MC_RSLT_OK)) { ++ pr_err("Query of WQCHAN 0x%x failed, code=0x%02x\n", ++ chanid, rslt); ++ return -EIO; ++ } ++ ++ /* For the query, word[0] of the result contains only the ++ * verb/rslt fields, so skip word[0]. ++ */ ++ word_copy(&attr[1], &p[1], 15); ++ return 0; ++} ++ ++void qbman_wqchan_attr_get_wqlen(struct qbman_attr *attr, int wq, uint32_t *len) ++{ ++ uint32_t *p = ATTR32(attr); ++ struct qb_attr_code code_wqchan_len = QB_CODE(wq+ 8, 0, 24); ++ *len = qb_attr_code_decode(&code_wqchan_len, p); ++} ++ ++void qbman_wqchan_attr_get_cdan_ctx(struct qbman_attr *attr, uint64_t *cdan_ctx) ++{ ++ uint32_t lo, hi; ++ uint32_t *p = ATTR32(attr); ++ ++ lo = qb_attr_code_decode(&code_wqchan_cdan_ctx_lo, p); ++ hi = qb_attr_code_decode(&code_wqchan_cdan_ctx_hi, p); ++ *cdan_ctx = ((uint64_t)hi << 32) | (uint64_t)lo; ++} ++ ++void qbman_wqchan_attr_get_cdan_wqid(struct qbman_attr *attr, ++ uint16_t *cdan_wqid) ++{ ++ uint32_t *p = ATTR32(attr); ++ *cdan_wqid = (uint16_t)qb_attr_code_decode(&code_wqchan_cdan_wqid, p); ++} ++ ++void qbman_wqchan_attr_get_ctrl(struct qbman_attr *attr, uint8_t *ctrl) ++{ ++ uint32_t *p = ATTR32(attr); ++ *ctrl = (uint8_t)qb_attr_code_decode(&code_wqchan_ctrl, p); ++} ++void qbman_wqchan_attr_get_chanid(struct qbman_attr *attr, uint16_t *chanid) ++{ ++ uint32_t *p = ATTR32(attr); ++ *chanid = (uint16_t)qb_attr_code_decode(&code_wqchan_chanid, p); ++} ++ +diff --git a/drivers/net/dpaa2/qbman/driver/qbman_debug.h b/drivers/net/dpaa2/qbman/driver/qbman_debug.h +new file mode 100644 +index 0000000..8c89731 +--- /dev/null ++++ b/drivers/net/dpaa2/qbman/driver/qbman_debug.h +@@ -0,0 +1,140 @@ ++/* Copyright (C) 2015 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY ++ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++struct qbman_attr { ++ uint32_t dont_manipulate_directly[40]; ++}; ++ ++/* Buffer pool query commands */ ++int qbman_bp_query(struct qbman_swp *s, uint32_t bpid, ++ struct qbman_attr *a); ++void qbman_bp_attr_get_bdi(struct qbman_attr *a, int *bdi, int *va, int *wae); ++void qbman_bp_attr_get_swdet(struct qbman_attr *a, uint32_t *swdet); ++void qbman_bp_attr_get_swdxt(struct qbman_attr *a, uint32_t *swdxt); ++void qbman_bp_attr_get_hwdet(struct qbman_attr *a, uint32_t *hwdet); ++void qbman_bp_attr_get_hwdxt(struct qbman_attr *a, uint32_t *hwdxt); ++void qbman_bp_attr_get_swset(struct qbman_attr *a, uint32_t *swset); ++void qbman_bp_attr_get_swsxt(struct qbman_attr *a, uint32_t *swsxt); ++void qbman_bp_attr_get_vbpid(struct qbman_attr *a, uint32_t *vbpid); ++void qbman_bp_attr_get_icid(struct qbman_attr *a, uint32_t *icid, int *pl); ++void qbman_bp_attr_get_bpscn_addr(struct qbman_attr *a, uint64_t *bpscn_addr); ++void qbman_bp_attr_get_bpscn_ctx(struct qbman_attr *a, uint64_t *bpscn_ctx); ++void qbman_bp_attr_get_hw_targ(struct qbman_attr *a, uint32_t *hw_targ); ++int qbman_bp_info_has_free_bufs(struct qbman_attr *a); ++int qbman_bp_info_is_depleted(struct qbman_attr *a); ++int qbman_bp_info_is_surplus(struct qbman_attr *a); ++uint32_t qbman_bp_info_num_free_bufs(struct qbman_attr *a); ++uint32_t qbman_bp_info_hdptr(struct qbman_attr *a); ++uint32_t qbman_bp_info_sdcnt(struct qbman_attr *a); ++uint32_t qbman_bp_info_hdcnt(struct qbman_attr *a); ++uint32_t qbman_bp_info_sscnt(struct qbman_attr *a); ++ ++/* FQ query function for programmable fields */ ++int qbman_fq_query(struct qbman_swp *s, uint32_t fqid, ++ struct qbman_attr *desc); ++void qbman_fq_attr_get_fqctrl(struct qbman_attr *d, uint32_t *fqctrl); ++void qbman_fq_attr_get_cgrid(struct qbman_attr *d, uint32_t *cgrid); ++void qbman_fq_attr_get_destwq(struct qbman_attr *d, uint32_t *destwq); ++void qbman_fq_attr_get_icscred(struct qbman_attr *d, uint32_t *icscred); ++void qbman_fq_attr_get_tdthresh(struct qbman_attr *d, uint32_t *tdthresh); ++void qbman_fq_attr_get_oa(struct qbman_attr *d, ++ int *oa_ics, int *oa_cgr, int32_t *oa_len); ++void qbman_fq_attr_get_mctl(struct qbman_attr *d, ++ int *bdi, int *ff, int *va, int *ps); ++void qbman_fq_attr_get_ctx(struct qbman_attr *d, uint32_t *hi, uint32_t *lo); ++void qbman_fq_attr_get_icid(struct qbman_attr *d, uint32_t *icid, int *pl); ++void qbman_fq_attr_get_vfqid(struct qbman_attr *d, uint32_t *vfqid); ++void qbman_fq_attr_get_erfqid(struct qbman_attr *d, uint32_t *erfqid); ++ ++/* FQ query command for non-programmable fields*/ ++enum qbman_fq_schedstate_e { ++ qbman_fq_schedstate_oos = 0, ++ qbman_fq_schedstate_retired, ++ qbman_fq_schedstate_tentatively_scheduled, ++ qbman_fq_schedstate_truly_scheduled, ++ qbman_fq_schedstate_parked, ++ qbman_fq_schedstate_held_active, ++}; ++ ++int qbman_fq_query_state(struct qbman_swp *s, uint32_t fqid, ++ struct qbman_attr *state); ++uint32_t qbman_fq_state_schedstate(const struct qbman_attr *state); ++int qbman_fq_state_force_eligible(const struct qbman_attr *state); ++int qbman_fq_state_xoff(const struct qbman_attr *state); ++int qbman_fq_state_retirement_pending(const struct qbman_attr *state); ++int qbman_fq_state_overflow_error(const struct qbman_attr *state); ++uint32_t qbman_fq_state_frame_count(const struct qbman_attr *state); ++uint32_t qbman_fq_state_byte_count(const struct qbman_attr *state); ++ ++/* CGR query */ ++int qbman_cgr_query(struct qbman_swp *s, uint32_t cgid, ++ struct qbman_attr *attr); ++void qbman_cgr_attr_get_ctl1(struct qbman_attr *d, int *cscn_wq_en_enter, ++ int *cscn_wq_en_exit, int *cscn_wq_icd); ++void qbman_cgr_attr_get_mode(struct qbman_attr *d, uint32_t *mode, ++ int *rej_cnt_mode, int *cscn_bdi); ++void qbman_cgr_attr_get_ctl2(struct qbman_attr *d, int *cscn_wr_en_enter, ++ int *cscn_wr_en_exit, int *cg_wr_ae, ++ int *cscn_dcp_en, int *cg_wr_va); ++void qbman_cgr_attr_get_iwc(struct qbman_attr *d, int *i_cnt_wr_en, ++ uint32_t *i_cnt_wr_bnd); ++void qbman_cgr_attr_get_tdc(struct qbman_attr *d, int *td_en); ++void qbman_cgr_attr_get_cs_thres(struct qbman_attr *d, uint32_t *cs_thres); ++void qbman_cgr_attr_get_cs_thres_x(struct qbman_attr *d, ++ uint32_t *cs_thres_x); ++void qbman_cgr_attr_get_td_thres(struct qbman_attr *d, uint32_t *td_thres); ++void qbman_cgr_attr_get_cscn_tdcp(struct qbman_attr *d, uint32_t *cscn_tdcp); ++void qbman_cgr_attr_get_cscn_wqid(struct qbman_attr *d, uint32_t *cscn_wqid); ++void qbman_cgr_attr_get_cscn_vcgid(struct qbman_attr *d, ++ uint32_t *cscn_vcgid); ++void qbman_cgr_attr_get_cg_icid(struct qbman_attr *d, uint32_t *icid, ++ int *pl); ++void qbman_cgr_attr_get_cg_wr_addr(struct qbman_attr *d, ++ uint64_t *cg_wr_addr); ++void qbman_cgr_attr_get_cscn_ctx(struct qbman_attr *d, uint64_t *cscn_ctx); ++void qbman_cgr_attr_wred_get_edp(struct qbman_attr *d, uint32_t idx, ++ int *edp); ++void qbman_cgr_attr_wred_dp_decompose(uint32_t dp, uint64_t *minth, ++ uint64_t *maxth, uint8_t *maxp); ++void qbman_cgr_attr_wred_get_parm_dp(struct qbman_attr *d, uint32_t idx, ++ uint32_t *dp); ++ ++/* CGR/CCGR/CQ statistics query */ ++int qbman_cgr_reject_statistics(struct qbman_swp *s, uint32_t cgid, int clear, ++ uint64_t *frame_cnt, uint64_t *byte_cnt); ++int qbman_ccgr_reject_statistics(struct qbman_swp *s, uint32_t cgid, int clear, ++ uint64_t *frame_cnt, uint64_t *byte_cnt); ++int qbman_cq_dequeue_statistics(struct qbman_swp *s, uint32_t cgid, int clear, ++ uint64_t *frame_cnt, uint64_t *byte_cnt); ++ ++/* Query Work Queue Channel */ ++int qbman_wqchan_query(struct qbman_swp *s, uint16_t chanid, ++ struct qbman_attr *attr); ++void qbman_wqchan_attr_get_wqlen(struct qbman_attr *attr, int wq, uint32_t *len); ++void qbman_wqchan_attr_get_cdan_ctx(struct qbman_attr *attr, uint64_t *cdan_ctx); ++void qbman_wqchan_attr_get_cdan_wqid(struct qbman_attr *attr, ++ uint16_t *cdan_wqid); ++void qbman_wqchan_attr_get_ctrl(struct qbman_attr *attr, uint8_t *ctrl); ++void qbman_wqchan_attr_get_chanid(struct qbman_attr *attr, uint16_t *chanid); +diff --git a/drivers/net/dpaa2/qbman/driver/qbman_portal.c b/drivers/net/dpaa2/qbman/driver/qbman_portal.c +new file mode 100644 +index 0000000..464f386 +--- /dev/null ++++ b/drivers/net/dpaa2/qbman/driver/qbman_portal.c +@@ -0,0 +1,1407 @@ ++/* Copyright (C) 2014 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY ++ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include "qbman_portal.h" ++ ++/* QBMan portal management command codes */ ++#define QBMAN_MC_ACQUIRE 0x30 ++#define QBMAN_WQCHAN_CONFIGURE 0x46 ++ ++/* CINH register offsets */ ++#define QBMAN_CINH_SWP_EQCR_PI 0x800 ++#define QBMAN_CINH_SWP_EQCR_CI 0x840 ++#define QBMAN_CINH_SWP_EQAR 0x8c0 ++#define QBMAN_CINH_SWP_DQPI 0xa00 ++#define QBMAN_CINH_SWP_DCAP 0xac0 ++#define QBMAN_CINH_SWP_SDQCR 0xb00 ++#define QBMAN_CINH_SWP_RAR 0xcc0 ++#define QBMAN_CINH_SWP_ISR 0xe00 ++#define QBMAN_CINH_SWP_IER 0xe40 ++#define QBMAN_CINH_SWP_ISDR 0xe80 ++#define QBMAN_CINH_SWP_IIR 0xec0 ++ ++/* CENA register offsets */ ++#define QBMAN_CENA_SWP_EQCR(n) (0x000 + ((uint32_t)(n) << 6)) ++#define QBMAN_CENA_SWP_DQRR(n) (0x200 + ((uint32_t)(n) << 6)) ++#define QBMAN_CENA_SWP_RCR(n) (0x400 + ((uint32_t)(n) << 6)) ++#define QBMAN_CENA_SWP_CR 0x600 ++#define QBMAN_CENA_SWP_RR(vb) (0x700 + ((uint32_t)(vb) >> 1)) ++#define QBMAN_CENA_SWP_VDQCR 0x780 ++#define QBMAN_CENA_SWP_EQCR_CI 0x840 ++ ++/* Reverse mapping of QBMAN_CENA_SWP_DQRR() */ ++#define QBMAN_IDX_FROM_DQRR(p) (((unsigned long)p & 0x1ff) >> 6) ++ ++/* QBMan FQ management command codes */ ++#define QBMAN_FQ_SCHEDULE 0x48 ++#define QBMAN_FQ_FORCE 0x49 ++#define QBMAN_FQ_XON 0x4d ++#define QBMAN_FQ_XOFF 0x4e ++ ++/*******************************/ ++/* Pre-defined attribute codes */ ++/*******************************/ ++ ++struct qb_attr_code code_generic_verb = QB_CODE(0, 0, 7); ++struct qb_attr_code code_generic_rslt = QB_CODE(0, 8, 8); ++ ++/*************************/ ++/* SDQCR attribute codes */ ++/*************************/ ++ ++/* we put these here because at least some of them are required by ++ * qbman_swp_init() */ ++struct qb_attr_code code_sdqcr_dct = QB_CODE(0, 24, 2); ++struct qb_attr_code code_sdqcr_fc = QB_CODE(0, 29, 1); ++struct qb_attr_code code_sdqcr_tok = QB_CODE(0, 16, 8); ++#define CODE_SDQCR_DQSRC(n) QB_CODE(0, n, 1) ++enum qbman_sdqcr_dct { ++ qbman_sdqcr_dct_null = 0, ++ qbman_sdqcr_dct_prio_ics, ++ qbman_sdqcr_dct_active_ics, ++ qbman_sdqcr_dct_active ++}; ++enum qbman_sdqcr_fc { ++ qbman_sdqcr_fc_one = 0, ++ qbman_sdqcr_fc_up_to_3 = 1 ++}; ++struct qb_attr_code code_sdqcr_dqsrc = QB_CODE(0, 0, 16); ++ ++/*********************************/ ++/* Portal constructor/destructor */ ++/*********************************/ ++ ++/* Software portals should always be in the power-on state when we initialise, ++ * due to the CCSR-based portal reset functionality that MC has. ++ * ++ * Erk! Turns out that QMan versions prior to 4.1 do not correctly reset DQRR ++ * valid-bits, so we need to support a workaround where we don't trust ++ * valid-bits when detecting new entries until any stale ring entries have been ++ * overwritten at least once. The idea is that we read PI for the first few ++ * entries, then switch to valid-bit after that. The trick is to clear the ++ * bug-work-around boolean once the PI wraps around the ring for the first time. ++ * ++ * Note: this still carries a slight additional cost once the decrementer hits ++ * zero. ++ */ ++struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d) ++{ ++ int ret; ++ uint32_t eqcr_pi; ++ struct qbman_swp *p = kmalloc(sizeof(*p), GFP_KERNEL); ++ if (!p) ++ return NULL; ++ p->desc = d; ++#ifdef QBMAN_CHECKING ++ p->mc.check = swp_mc_can_start; ++#endif ++ p->mc.valid_bit = QB_VALID_BIT; ++ p->sdq = 0; ++ qb_attr_code_encode(&code_sdqcr_dct, &p->sdq, qbman_sdqcr_dct_prio_ics); ++ qb_attr_code_encode(&code_sdqcr_fc, &p->sdq, qbman_sdqcr_fc_up_to_3); ++ qb_attr_code_encode(&code_sdqcr_tok, &p->sdq, 0xbb); ++ atomic_set(&p->vdq.busy, 1); ++ p->vdq.valid_bit = QB_VALID_BIT; ++ p->dqrr.next_idx = 0; ++ p->dqrr.valid_bit = QB_VALID_BIT; ++ qman_version = p->desc->qman_version; ++ if ((qman_version & 0xFFFF0000) < QMAN_REV_4100) { ++ p->dqrr.dqrr_size = 4; ++ p->dqrr.reset_bug = 1; ++ } else { ++ p->dqrr.dqrr_size = 8; ++ p->dqrr.reset_bug = 0; ++ } ++ ++ ret = qbman_swp_sys_init(&p->sys, d, p->dqrr.dqrr_size); ++ if (ret) { ++ kfree(p); ++ pr_err("qbman_swp_sys_init() failed %d\n", ret); ++ return NULL; ++ } ++ /* SDQCR needs to be initialized to 0 when no channels are ++ being dequeued from or else the QMan HW will indicate an ++ error. The values that were calculated above will be ++ applied when dequeues from a specific channel are enabled */ ++ qbman_cinh_write(&p->sys, QBMAN_CINH_SWP_SDQCR, 0); ++ eqcr_pi = qbman_cinh_read(&p->sys, QBMAN_CINH_SWP_EQCR_PI); ++ p->eqcr.pi = eqcr_pi & 0xF; ++ p->eqcr.pi_vb = eqcr_pi & QB_VALID_BIT; ++ p->eqcr.ci = qbman_cinh_read(&p->sys, QBMAN_CINH_SWP_EQCR_CI) & 0xF; ++ p->eqcr.available = QBMAN_EQCR_SIZE - qm_cyc_diff(QBMAN_EQCR_SIZE, ++ p->eqcr.ci, p->eqcr.pi); ++ ++ return p; ++} ++ ++void qbman_swp_finish(struct qbman_swp *p) ++{ ++#ifdef QBMAN_CHECKING ++ BUG_ON(p->mc.check != swp_mc_can_start); ++#endif ++ qbman_swp_sys_finish(&p->sys); ++ kfree(p); ++} ++ ++const struct qbman_swp_desc *qbman_swp_get_desc(struct qbman_swp *p) ++{ ++ return p->desc; ++} ++ ++/**************/ ++/* Interrupts */ ++/**************/ ++ ++uint32_t qbman_swp_interrupt_get_vanish(struct qbman_swp *p) ++{ ++ return qbman_cinh_read(&p->sys, QBMAN_CINH_SWP_ISDR); ++} ++ ++void qbman_swp_interrupt_set_vanish(struct qbman_swp *p, uint32_t mask) ++{ ++ qbman_cinh_write(&p->sys, QBMAN_CINH_SWP_ISDR, mask); ++} ++ ++uint32_t qbman_swp_interrupt_read_status(struct qbman_swp *p) ++{ ++ return qbman_cinh_read(&p->sys, QBMAN_CINH_SWP_ISR); ++} ++ ++void qbman_swp_interrupt_clear_status(struct qbman_swp *p, uint32_t mask) ++{ ++ qbman_cinh_write(&p->sys, QBMAN_CINH_SWP_ISR, mask); ++} ++ ++uint32_t qbman_swp_interrupt_get_trigger(struct qbman_swp *p) ++{ ++ return qbman_cinh_read(&p->sys, QBMAN_CINH_SWP_IER); ++} ++ ++void qbman_swp_interrupt_set_trigger(struct qbman_swp *p, uint32_t mask) ++{ ++ qbman_cinh_write(&p->sys, QBMAN_CINH_SWP_IER, mask); ++} ++ ++int qbman_swp_interrupt_get_inhibit(struct qbman_swp *p) ++{ ++ return qbman_cinh_read(&p->sys, QBMAN_CINH_SWP_IIR); ++} ++ ++void qbman_swp_interrupt_set_inhibit(struct qbman_swp *p, int inhibit) ++{ ++ qbman_cinh_write(&p->sys, QBMAN_CINH_SWP_IIR, inhibit ? 0xffffffff : 0); ++} ++ ++/***********************/ ++/* Management commands */ ++/***********************/ ++ ++/* ++ * Internal code common to all types of management commands. ++ */ ++ ++void *qbman_swp_mc_start(struct qbman_swp *p) ++{ ++ void *ret; ++#ifdef QBMAN_CHECKING ++ BUG_ON(p->mc.check != swp_mc_can_start); ++#endif ++ ret = qbman_cena_write_start(&p->sys, QBMAN_CENA_SWP_CR); ++#ifdef QBMAN_CHECKING ++ if (!ret) ++ p->mc.check = swp_mc_can_submit; ++#endif ++ return ret; ++} ++ ++void qbman_swp_mc_submit(struct qbman_swp *p, void *cmd, uint32_t cmd_verb) ++{ ++ uint32_t *v = cmd; ++#ifdef QBMAN_CHECKING ++ BUG_ON(!p->mc.check != swp_mc_can_submit); ++#endif ++ /* TBD: "|=" is going to hurt performance. Need to move as many fields ++ * out of word zero, and for those that remain, the "OR" needs to occur ++ * at the caller side. This debug check helps to catch cases where the ++ * caller wants to OR but has forgotten to do so. */ ++ BUG_ON((*v & cmd_verb) != *v); ++ *v = cmd_verb | p->mc.valid_bit; ++ qbman_cena_write_complete(&p->sys, QBMAN_CENA_SWP_CR, cmd); ++#ifdef QBMAN_CHECKING ++ p->mc.check = swp_mc_can_poll; ++#endif ++} ++ ++void *qbman_swp_mc_result(struct qbman_swp *p) ++{ ++ uint32_t *ret, verb; ++#ifdef QBMAN_CHECKING ++ BUG_ON(p->mc.check != swp_mc_can_poll); ++#endif ++ qbman_cena_invalidate_prefetch(&p->sys, ++ QBMAN_CENA_SWP_RR(p->mc.valid_bit)); ++ ret = qbman_cena_read(&p->sys, QBMAN_CENA_SWP_RR(p->mc.valid_bit)); ++ /* Remove the valid-bit - command completed iff the rest is non-zero */ ++ verb = ret[0] & ~QB_VALID_BIT; ++ if (!verb) ++ return NULL; ++#ifdef QBMAN_CHECKING ++ p->mc.check = swp_mc_can_start; ++#endif ++ p->mc.valid_bit ^= QB_VALID_BIT; ++ return ret; ++} ++ ++/***********/ ++/* Enqueue */ ++/***********/ ++ ++/* These should be const, eventually */ ++static struct qb_attr_code code_eq_cmd = QB_CODE(0, 0, 2); ++static struct qb_attr_code code_eq_eqdi = QB_CODE(0, 3, 1); ++static struct qb_attr_code code_eq_dca_en = QB_CODE(0, 15, 1); ++static struct qb_attr_code code_eq_dca_pk = QB_CODE(0, 14, 1); ++static struct qb_attr_code code_eq_dca_idx = QB_CODE(0, 8, 2); ++static struct qb_attr_code code_eq_orp_en = QB_CODE(0, 2, 1); ++static struct qb_attr_code code_eq_orp_is_nesn = QB_CODE(0, 31, 1); ++static struct qb_attr_code code_eq_orp_nlis = QB_CODE(0, 30, 1); ++static struct qb_attr_code code_eq_orp_seqnum = QB_CODE(0, 16, 14); ++static struct qb_attr_code code_eq_opr_id = QB_CODE(1, 0, 16); ++static struct qb_attr_code code_eq_tgt_id = QB_CODE(2, 0, 24); ++/* static struct qb_attr_code code_eq_tag = QB_CODE(3, 0, 32); */ ++static struct qb_attr_code code_eq_qd_en = QB_CODE(0, 4, 1); ++static struct qb_attr_code code_eq_qd_bin = QB_CODE(4, 0, 16); ++static struct qb_attr_code code_eq_qd_pri = QB_CODE(4, 16, 4); ++static struct qb_attr_code code_eq_rsp_stash = QB_CODE(5, 16, 1); ++static struct qb_attr_code code_eq_rsp_id = QB_CODE(5, 24, 8); ++static struct qb_attr_code code_eq_rsp_lo = QB_CODE(6, 0, 32); ++ ++enum qbman_eq_cmd_e { ++ /* No enqueue, primarily for plugging ORP gaps for dropped frames */ ++ qbman_eq_cmd_empty, ++ /* DMA an enqueue response once complete */ ++ qbman_eq_cmd_respond, ++ /* DMA an enqueue response only if the enqueue fails */ ++ qbman_eq_cmd_respond_reject ++}; ++ ++void qbman_eq_desc_clear(struct qbman_eq_desc *d) ++{ ++ memset(d, 0, sizeof(*d)); ++} ++ ++void qbman_eq_desc_set_no_orp(struct qbman_eq_desc *d, int respond_success) ++{ ++ uint32_t *cl = qb_cl(d); ++ qb_attr_code_encode(&code_eq_orp_en, cl, 0); ++ qb_attr_code_encode(&code_eq_cmd, cl, ++ respond_success ? qbman_eq_cmd_respond : ++ qbman_eq_cmd_respond_reject); ++} ++ ++void qbman_eq_desc_set_orp(struct qbman_eq_desc *d, int respond_success, ++ uint32_t opr_id, uint32_t seqnum, int incomplete) ++{ ++ uint32_t *cl = qb_cl(d); ++ qb_attr_code_encode(&code_eq_orp_en, cl, 1); ++ qb_attr_code_encode(&code_eq_cmd, cl, ++ respond_success ? qbman_eq_cmd_respond : ++ qbman_eq_cmd_respond_reject); ++ qb_attr_code_encode(&code_eq_opr_id, cl, opr_id); ++ qb_attr_code_encode(&code_eq_orp_seqnum, cl, seqnum); ++ qb_attr_code_encode(&code_eq_orp_nlis, cl, !!incomplete); ++} ++ ++void qbman_eq_desc_set_orp_hole(struct qbman_eq_desc *d, uint32_t opr_id, ++ uint32_t seqnum) ++{ ++ uint32_t *cl = qb_cl(d); ++ qb_attr_code_encode(&code_eq_orp_en, cl, 1); ++ qb_attr_code_encode(&code_eq_cmd, cl, qbman_eq_cmd_empty); ++ qb_attr_code_encode(&code_eq_opr_id, cl, opr_id); ++ qb_attr_code_encode(&code_eq_orp_seqnum, cl, seqnum); ++ qb_attr_code_encode(&code_eq_orp_nlis, cl, 0); ++ qb_attr_code_encode(&code_eq_orp_is_nesn, cl, 0); ++} ++ ++void qbman_eq_desc_set_orp_nesn(struct qbman_eq_desc *d, uint32_t opr_id, ++ uint32_t seqnum) ++{ ++ uint32_t *cl = qb_cl(d); ++ qb_attr_code_encode(&code_eq_orp_en, cl, 1); ++ qb_attr_code_encode(&code_eq_cmd, cl, qbman_eq_cmd_empty); ++ qb_attr_code_encode(&code_eq_opr_id, cl, opr_id); ++ qb_attr_code_encode(&code_eq_orp_seqnum, cl, seqnum); ++ qb_attr_code_encode(&code_eq_orp_nlis, cl, 0); ++ qb_attr_code_encode(&code_eq_orp_is_nesn, cl, 1); ++} ++ ++void qbman_eq_desc_set_response(struct qbman_eq_desc *d, ++ dma_addr_t storage_phys, ++ int stash) ++{ ++ uint32_t *cl = qb_cl(d); ++ qb_attr_code_encode_64(&code_eq_rsp_lo, (uint64_t *)cl, storage_phys); ++ qb_attr_code_encode(&code_eq_rsp_stash, cl, !!stash); ++} ++ ++void qbman_eq_desc_set_token(struct qbman_eq_desc *d, uint8_t token) ++{ ++ uint32_t *cl = qb_cl(d); ++ qb_attr_code_encode(&code_eq_rsp_id, cl, (uint32_t)token); ++} ++ ++void qbman_eq_desc_set_fq(struct qbman_eq_desc *d, uint32_t fqid) ++{ ++ uint32_t *cl = qb_cl(d); ++ qb_attr_code_encode(&code_eq_qd_en, cl, 0); ++ qb_attr_code_encode(&code_eq_tgt_id, cl, fqid); ++} ++ ++void qbman_eq_desc_set_qd(struct qbman_eq_desc *d, uint32_t qdid, ++ uint32_t qd_bin, uint32_t qd_prio) ++{ ++ uint32_t *cl = qb_cl(d); ++ qb_attr_code_encode(&code_eq_qd_en, cl, 1); ++ qb_attr_code_encode(&code_eq_tgt_id, cl, qdid); ++ qb_attr_code_encode(&code_eq_qd_bin, cl, qd_bin); ++ qb_attr_code_encode(&code_eq_qd_pri, cl, qd_prio); ++} ++ ++void qbman_eq_desc_set_eqdi(struct qbman_eq_desc *d, int enable) ++{ ++ uint32_t *cl = qb_cl(d); ++ qb_attr_code_encode(&code_eq_eqdi, cl, !!enable); ++} ++ ++void qbman_eq_desc_set_dca(struct qbman_eq_desc *d, int enable, ++ uint32_t dqrr_idx, int park) ++{ ++ uint32_t *cl = qb_cl(d); ++ qb_attr_code_encode(&code_eq_dca_en, cl, !!enable); ++ if (enable) { ++ qb_attr_code_encode(&code_eq_dca_pk, cl, !!park); ++ qb_attr_code_encode(&code_eq_dca_idx, cl, dqrr_idx); ++ } ++} ++ ++#define EQAR_IDX(eqar) ((eqar) & 0x7) ++#define EQAR_VB(eqar) ((eqar) & 0x80) ++#define EQAR_SUCCESS(eqar) ((eqar) & 0x100) ++static int qbman_swp_enqueue_array_mode(struct qbman_swp *s, ++ const struct qbman_eq_desc *d, ++ const struct qbman_fd *fd) ++{ ++ uint32_t *p; ++ const uint32_t *cl = qb_cl(d); ++ uint32_t eqar = qbman_cinh_read(&s->sys, QBMAN_CINH_SWP_EQAR); ++ pr_debug("EQAR=%08x\n", eqar); ++ if (!EQAR_SUCCESS(eqar)) ++ return -EBUSY; ++ p = qbman_cena_write_start_wo_shadow(&s->sys, ++ QBMAN_CENA_SWP_EQCR(EQAR_IDX(eqar))); ++ word_copy(&p[1], &cl[1], 7); ++ word_copy(&p[8], fd, sizeof(*fd) >> 2); ++ /* Set the verb byte, have to substitute in the valid-bit */ ++ lwsync(); ++ p[0] = cl[0] | EQAR_VB(eqar); ++ qbman_cena_write_complete_wo_shadow(&s->sys, ++ QBMAN_CENA_SWP_EQCR(EQAR_IDX(eqar))); ++ return 0; ++} ++ ++static int qbman_swp_enqueue_ring_mode(struct qbman_swp *s, ++ const struct qbman_eq_desc *d, ++ const struct qbman_fd *fd) ++{ ++ uint32_t *p; ++ const uint32_t *cl = qb_cl(d); ++ uint32_t eqcr_ci; ++ uint8_t diff; ++ ++ if (!s->eqcr.available) { ++ eqcr_ci = s->eqcr.ci; ++ s->eqcr.ci = qbman_cena_read_reg(&s->sys, ++ QBMAN_CENA_SWP_EQCR_CI) & 0xF; ++ diff = qm_cyc_diff(QBMAN_EQCR_SIZE, ++ eqcr_ci, s->eqcr.ci); ++ s->eqcr.available += diff; ++ if (!diff) ++ return -EBUSY; ++ } ++ ++ p = qbman_cena_write_start_wo_shadow(&s->sys, ++ QBMAN_CENA_SWP_EQCR(s->eqcr.pi & 7)); ++ word_copy(&p[1], &cl[1], 7); ++ word_copy(&p[8], fd, sizeof(*fd) >> 2); ++ lwsync(); ++ /* Set the verb byte, have to substitute in the valid-bit */ ++ p[0] = cl[0] | s->eqcr.pi_vb; ++ qbman_cena_write_complete_wo_shadow(&s->sys, ++ QBMAN_CENA_SWP_EQCR(s->eqcr.pi & 7)); ++ s->eqcr.pi++; ++ s->eqcr.pi &= 0xF; ++ s->eqcr.available--; ++ if (!(s->eqcr.pi & 7)) ++ s->eqcr.pi_vb ^= QB_VALID_BIT; ++ return 0; ++} ++ ++int qbman_swp_fill_ring(struct qbman_swp *s, ++ const struct qbman_eq_desc *d, ++ const struct qbman_fd *fd, ++ __attribute__((unused)) uint8_t burst_index) ++{ ++ uint32_t *p; ++ const uint32_t *cl = qb_cl(d); ++ uint32_t eqcr_ci; ++ uint8_t diff; ++ ++ if (!s->eqcr.available) { ++ eqcr_ci = s->eqcr.ci; ++ s->eqcr.ci = qbman_cena_read_reg(&s->sys, ++ QBMAN_CENA_SWP_EQCR_CI) & 0xF; ++ diff = qm_cyc_diff(QBMAN_EQCR_SIZE, ++ eqcr_ci, s->eqcr.ci); ++ s->eqcr.available += diff; ++ if (!diff) { ++ return -EBUSY; ++ } ++ } ++ p = qbman_cena_write_start_wo_shadow(&s->sys, ++ QBMAN_CENA_SWP_EQCR((s->eqcr.pi/* +burst_index */) & 7)); ++ //word_copy(&p[1], &cl[1], 7); ++ memcpy(&p[1], &cl[1], 7); ++ /* word_copy(&p[8], fd, sizeof(*fd) >> 2); */ ++ memcpy(&p[8], fd, sizeof(struct qbman_fd)); ++ ++ //lwsync(); ++ ++ p[0] = cl[0] | s->eqcr.pi_vb; ++ ++ s->eqcr.pi++; ++ s->eqcr.pi &= 0xF; ++ s->eqcr.available--; ++ if (!(s->eqcr.pi & 7)) ++ s->eqcr.pi_vb ^= QB_VALID_BIT; ++ ++ return 0; ++} ++ ++int qbman_swp_flush_ring(struct qbman_swp *s) ++{ ++ void *ptr = s->sys.addr_cena; ++ dcbf((uint64_t)ptr); ++ dcbf((uint64_t)ptr + 0x40); ++ dcbf((uint64_t)ptr + 0x80); ++ dcbf((uint64_t)ptr + 0xc0); ++ dcbf((uint64_t)ptr + 0x100); ++ dcbf((uint64_t)ptr + 0x140); ++ dcbf((uint64_t)ptr + 0x180); ++ dcbf((uint64_t)ptr + 0x1c0); ++ ++ return 0; ++} ++ ++void qbman_sync(void) ++{ ++ lwsync(); ++} ++ ++int qbman_swp_enqueue(struct qbman_swp *s, const struct qbman_eq_desc *d, ++ const struct qbman_fd *fd) ++{ ++ if (s->sys.eqcr_mode == qman_eqcr_vb_array) ++ return qbman_swp_enqueue_array_mode(s, d, fd); ++ else /* Use ring mode by default */ ++ return qbman_swp_enqueue_ring_mode(s, d, fd); ++} ++ ++/*************************/ ++/* Static (push) dequeue */ ++/*************************/ ++ ++void qbman_swp_push_get(struct qbman_swp *s, uint8_t channel_idx, int *enabled) ++{ ++ struct qb_attr_code code = CODE_SDQCR_DQSRC(channel_idx); ++ ++ BUG_ON(channel_idx > 15); ++ *enabled = (int)qb_attr_code_decode(&code, &s->sdq); ++} ++ ++void qbman_swp_push_set(struct qbman_swp *s, uint8_t channel_idx, int enable) ++{ ++ uint16_t dqsrc; ++ struct qb_attr_code code = CODE_SDQCR_DQSRC(channel_idx); ++ BUG_ON(channel_idx > 15); ++ qb_attr_code_encode(&code, &s->sdq, !!enable); ++ /* Read make the complete src map. If no channels are enabled ++ the SDQCR must be 0 or else QMan will assert errors */ ++ dqsrc = (uint16_t)qb_attr_code_decode(&code_sdqcr_dqsrc, &s->sdq); ++ if (dqsrc != 0) ++ qbman_cinh_write(&s->sys, QBMAN_CINH_SWP_SDQCR, s->sdq); ++ else ++ qbman_cinh_write(&s->sys, QBMAN_CINH_SWP_SDQCR, 0); ++} ++ ++/***************************/ ++/* Volatile (pull) dequeue */ ++/***************************/ ++ ++/* These should be const, eventually */ ++static struct qb_attr_code code_pull_dct = QB_CODE(0, 0, 2); ++static struct qb_attr_code code_pull_dt = QB_CODE(0, 2, 2); ++static struct qb_attr_code code_pull_rls = QB_CODE(0, 4, 1); ++static struct qb_attr_code code_pull_stash = QB_CODE(0, 5, 1); ++static struct qb_attr_code code_pull_numframes = QB_CODE(0, 8, 4); ++static struct qb_attr_code code_pull_token = QB_CODE(0, 16, 8); ++static struct qb_attr_code code_pull_dqsource = QB_CODE(1, 0, 24); ++static struct qb_attr_code code_pull_rsp_lo = QB_CODE(2, 0, 32); ++ ++enum qb_pull_dt_e { ++ qb_pull_dt_channel, ++ qb_pull_dt_workqueue, ++ qb_pull_dt_framequeue ++}; ++ ++void qbman_pull_desc_clear(struct qbman_pull_desc *d) ++{ ++ memset(d, 0, sizeof(*d)); ++} ++ ++void qbman_pull_desc_set_storage(struct qbman_pull_desc *d, ++ struct qbman_result *storage, ++ dma_addr_t storage_phys, ++ int stash) ++{ ++ uint32_t *cl = qb_cl(d); ++ /* Squiggle the pointer 'storage' into the extra 2 words of the ++ * descriptor (which aren't copied to the hw command) */ ++ *(void **)&cl[4] = storage; ++ if (!storage) { ++ qb_attr_code_encode(&code_pull_rls, cl, 0); ++ return; ++ } ++ qb_attr_code_encode(&code_pull_rls, cl, 1); ++ qb_attr_code_encode(&code_pull_stash, cl, !!stash); ++ qb_attr_code_encode_64(&code_pull_rsp_lo, (uint64_t *)cl, storage_phys); ++} ++ ++void qbman_pull_desc_set_numframes(struct qbman_pull_desc *d, uint8_t numframes) ++{ ++ uint32_t *cl = qb_cl(d); ++ BUG_ON(!numframes || (numframes > 16)); ++ qb_attr_code_encode(&code_pull_numframes, cl, ++ (uint32_t)(numframes - 1)); ++} ++ ++void qbman_pull_desc_set_token(struct qbman_pull_desc *d, uint8_t token) ++{ ++ uint32_t *cl = qb_cl(d); ++ qb_attr_code_encode(&code_pull_token, cl, token); ++} ++ ++void qbman_pull_desc_set_fq(struct qbman_pull_desc *d, uint32_t fqid) ++{ ++ uint32_t *cl = qb_cl(d); ++ qb_attr_code_encode(&code_pull_dct, cl, 1); ++ qb_attr_code_encode(&code_pull_dt, cl, qb_pull_dt_framequeue); ++ qb_attr_code_encode(&code_pull_dqsource, cl, fqid); ++} ++ ++void qbman_pull_desc_set_wq(struct qbman_pull_desc *d, uint32_t wqid, ++ enum qbman_pull_type_e dct) ++{ ++ uint32_t *cl = qb_cl(d); ++ qb_attr_code_encode(&code_pull_dct, cl, dct); ++ qb_attr_code_encode(&code_pull_dt, cl, qb_pull_dt_workqueue); ++ qb_attr_code_encode(&code_pull_dqsource, cl, wqid); ++} ++ ++void qbman_pull_desc_set_channel(struct qbman_pull_desc *d, uint32_t chid, ++ enum qbman_pull_type_e dct) ++{ ++ uint32_t *cl = qb_cl(d); ++ qb_attr_code_encode(&code_pull_dct, cl, dct); ++ qb_attr_code_encode(&code_pull_dt, cl, qb_pull_dt_channel); ++ qb_attr_code_encode(&code_pull_dqsource, cl, chid); ++} ++ ++int qbman_swp_pull(struct qbman_swp *s, struct qbman_pull_desc *d) ++{ ++ uint32_t *p; ++ uint32_t *cl = qb_cl(d); ++ if (!atomic_dec_and_test(&s->vdq.busy)) { ++ atomic_inc(&s->vdq.busy); ++ return -EBUSY; ++ } ++ s->vdq.storage = *(void **)&cl[4]; ++ qb_attr_code_encode(&code_pull_token, cl, 1); ++ p = qbman_cena_write_start_wo_shadow(&s->sys, QBMAN_CENA_SWP_VDQCR); ++ word_copy(&p[1], &cl[1], 3); ++ /* Set the verb byte, have to substitute in the valid-bit */ ++ lwsync(); ++ p[0] = cl[0] | s->vdq.valid_bit; ++ s->vdq.valid_bit ^= QB_VALID_BIT; ++ qbman_cena_write_complete_wo_shadow(&s->sys, QBMAN_CENA_SWP_VDQCR); ++ return 0; ++} ++ ++/****************/ ++/* Polling DQRR */ ++/****************/ ++ ++static struct qb_attr_code code_dqrr_verb = QB_CODE(0, 0, 8); ++static struct qb_attr_code code_dqrr_response = QB_CODE(0, 0, 7); ++static struct qb_attr_code code_dqrr_stat = QB_CODE(0, 8, 8); ++static struct qb_attr_code code_dqrr_seqnum = QB_CODE(0, 16, 14); ++static struct qb_attr_code code_dqrr_odpid = QB_CODE(1, 0, 16); ++/* static struct qb_attr_code code_dqrr_tok = QB_CODE(1, 24, 8); */ ++static struct qb_attr_code code_dqrr_fqid = QB_CODE(2, 0, 24); ++static struct qb_attr_code code_dqrr_byte_count = QB_CODE(4, 0, 32); ++static struct qb_attr_code code_dqrr_frame_count = QB_CODE(5, 0, 24); ++static struct qb_attr_code code_dqrr_ctx_lo = QB_CODE(6, 0, 32); ++ ++#define QBMAN_RESULT_DQ 0x60 ++#define QBMAN_RESULT_FQRN 0x21 ++#define QBMAN_RESULT_FQRNI 0x22 ++#define QBMAN_RESULT_FQPN 0x24 ++#define QBMAN_RESULT_FQDAN 0x25 ++#define QBMAN_RESULT_CDAN 0x26 ++#define QBMAN_RESULT_CSCN_MEM 0x27 ++#define QBMAN_RESULT_CGCU 0x28 ++#define QBMAN_RESULT_BPSCN 0x29 ++#define QBMAN_RESULT_CSCN_WQ 0x2a ++ ++static struct qb_attr_code code_dqpi_pi = QB_CODE(0, 0, 4); ++ ++/* NULL return if there are no unconsumed DQRR entries. Returns a DQRR entry ++ * only once, so repeated calls can return a sequence of DQRR entries, without ++ * requiring they be consumed immediately or in any particular order. */ ++const struct qbman_result *qbman_swp_dqrr_next(struct qbman_swp *s) ++{ ++ uint32_t verb; ++ uint32_t response_verb; ++ uint32_t flags; ++ const struct qbman_result *dq; ++ const uint32_t *p; ++ ++ /* Before using valid-bit to detect if something is there, we have to ++ * handle the case of the DQRR reset bug... */ ++ if (unlikely(s->dqrr.reset_bug)) { ++ /* We pick up new entries by cache-inhibited producer index, ++ * which means that a non-coherent mapping would require us to ++ * invalidate and read *only* once that PI has indicated that ++ * there's an entry here. The first trip around the DQRR ring ++ * will be much less efficient than all subsequent trips around ++ * it... ++ */ ++ uint32_t dqpi = qbman_cinh_read(&s->sys, QBMAN_CINH_SWP_DQPI); ++ uint32_t pi = qb_attr_code_decode(&code_dqpi_pi, &dqpi); ++ /* there are new entries iff pi != next_idx */ ++ if (pi == s->dqrr.next_idx) ++ return NULL; ++ /* if next_idx is/was the last ring index, and 'pi' is ++ * different, we can disable the workaround as all the ring ++ * entries have now been DMA'd to so valid-bit checking is ++ * repaired. Note: this logic needs to be based on next_idx ++ * (which increments one at a time), rather than on pi (which ++ * can burst and wrap-around between our snapshots of it). ++ */ ++ BUG_ON((s->dqrr.dqrr_size - 1) < 0); ++ if (s->dqrr.next_idx == (s->dqrr.dqrr_size - 1u)) { ++ pr_debug("DEBUG: next_idx=%d, pi=%d, clear reset bug\n", ++ s->dqrr.next_idx, pi); ++ s->dqrr.reset_bug = 0; ++ } ++ qbman_cena_invalidate_prefetch(&s->sys, ++ QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)); ++ } ++ dq = qbman_cena_read_wo_shadow(&s->sys, ++ QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)); ++ p = qb_cl(dq); ++ verb = qb_attr_code_decode(&code_dqrr_verb, p); ++ /* If the valid-bit isn't of the expected polarity, nothing there. Note, ++ * in the DQRR reset bug workaround, we shouldn't need to skip these ++ * check, because we've already determined that a new entry is available ++ * and we've invalidated the cacheline before reading it, so the ++ * valid-bit behaviour is repaired and should tell us what we already ++ * knew from reading PI. ++ */ ++ if ((verb & QB_VALID_BIT) != s->dqrr.valid_bit) ++ return NULL; ++ ++ /* There's something there. Move "next_idx" attention to the next ring ++ * entry (and prefetch it) before returning what we found. */ ++ s->dqrr.next_idx++; ++ if (s->dqrr.next_idx == QBMAN_DQRR_SIZE) { ++ s->dqrr.next_idx = 0; ++ s->dqrr.valid_bit ^= QB_VALID_BIT; ++ } ++ /* If this is the final response to a volatile dequeue command ++ indicate that the vdq is no longer busy */ ++ flags = qbman_result_DQ_flags(dq); ++ response_verb = qb_attr_code_decode(&code_dqrr_response, &verb); ++ if ((response_verb == QBMAN_RESULT_DQ) && ++ (flags & QBMAN_DQ_STAT_VOLATILE) && ++ (flags & QBMAN_DQ_STAT_EXPIRED)) ++ atomic_inc(&s->vdq.busy); ++ ++ return dq; ++} ++ ++/* Consume DQRR entries previously returned from qbman_swp_dqrr_next(). */ ++void qbman_swp_dqrr_consume(struct qbman_swp *s, ++ const struct qbman_result *dq) ++{ ++ qbman_cinh_write(&s->sys, QBMAN_CINH_SWP_DCAP, QBMAN_IDX_FROM_DQRR(dq)); ++} ++ ++/*********************************/ ++/* Polling user-provided storage */ ++/*********************************/ ++ ++int qbman_result_has_new_result(__attribute__((unused)) struct qbman_swp *s, ++ const struct qbman_result *dq) ++{ ++ /* To avoid converting the little-endian DQ entry to host-endian prior ++ * to us knowing whether there is a valid entry or not (and run the ++ * risk of corrupting the incoming hardware LE write), we detect in ++ * hardware endianness rather than host. This means we need a different ++ * "code" depending on whether we are BE or LE in software, which is ++ * where DQRR_TOK_OFFSET comes in... */ ++ static struct qb_attr_code code_dqrr_tok_detect = ++ QB_CODE(0, DQRR_TOK_OFFSET, 8); ++ /* The user trying to poll for a result treats "dq" as const. It is ++ * however the same address that was provided to us non-const in the ++ * first place, for directing hardware DMA to. So we can cast away the ++ * const because it is mutable from our perspective. */ ++ uint32_t *p = (uint32_t *)(unsigned long)qb_cl(dq); ++ uint32_t token; ++ ++ token = qb_attr_code_decode(&code_dqrr_tok_detect, &p[1]); ++ if (token != 1) ++ return 0; ++ qb_attr_code_encode(&code_dqrr_tok_detect, &p[1], 0); ++ ++ /* Only now do we convert from hardware to host endianness. Also, as we ++ * are returning success, the user has promised not to call us again, so ++ * there's no risk of us converting the endianness twice... */ ++ make_le32_n(p, 16); ++ return 1; ++} ++ ++int qbman_check_command_complete(struct qbman_swp *s, ++ const struct qbman_result *dq) ++{ ++ /* To avoid converting the little-endian DQ entry to host-endian prior ++ * to us knowing whether there is a valid entry or not (and run the ++ * risk of corrupting the incoming hardware LE write), we detect in ++ * hardware endianness rather than host. This means we need a different ++ * "code" depending on whether we are BE or LE in software, which is ++ * where DQRR_TOK_OFFSET comes in... */ ++ static struct qb_attr_code code_dqrr_tok_detect = ++ QB_CODE(0, DQRR_TOK_OFFSET, 8); ++ /* The user trying to poll for a result treats "dq" as const. It is ++ * however the same address that was provided to us non-const in the ++ * first place, for directing hardware DMA to. So we can cast away the ++ * const because it is mutable from our perspective. */ ++ uint32_t *p = (uint32_t *)(unsigned long)qb_cl(dq); ++ uint32_t token; ++ ++ token = qb_attr_code_decode(&code_dqrr_tok_detect, &p[1]); ++ if(token!=1) ++ return 0; ++ /*When token is set it indicates that VDQ command has been fetched by qbman and ++ *is working on it. It is safe for software to issue another VDQ command, so ++ *incrementing the busy variable.*/ ++ if (s->vdq.storage == dq) { ++ s->vdq.storage = NULL; ++ atomic_inc(&s->vdq.busy); ++ } ++ return 1; ++} ++ ++/********************************/ ++/* Categorising qbman results */ ++/********************************/ ++ ++static struct qb_attr_code code_result_in_mem = ++ QB_CODE(0, QBMAN_RESULT_VERB_OFFSET_IN_MEM, 7); ++ ++static inline int __qbman_result_is_x(const struct qbman_result *dq, ++ uint32_t x) ++{ ++ const uint32_t *p = qb_cl(dq); ++ uint32_t response_verb = qb_attr_code_decode(&code_dqrr_response, p); ++ return (response_verb == x); ++} ++ ++static inline int __qbman_result_is_x_in_mem(const struct qbman_result *dq, ++ uint32_t x) ++{ ++ const uint32_t *p = qb_cl(dq); ++ uint32_t response_verb = qb_attr_code_decode(&code_result_in_mem, p); ++ ++ return (response_verb == x); ++} ++ ++int qbman_result_is_DQ(const struct qbman_result *dq) ++{ ++ return __qbman_result_is_x(dq, QBMAN_RESULT_DQ); ++} ++ ++int qbman_result_is_FQDAN(const struct qbman_result *dq) ++{ ++ return __qbman_result_is_x(dq, QBMAN_RESULT_FQDAN); ++} ++ ++int qbman_result_is_CDAN(const struct qbman_result *dq) ++{ ++ return __qbman_result_is_x(dq, QBMAN_RESULT_CDAN); ++} ++ ++int qbman_result_is_CSCN(const struct qbman_result *dq) ++{ ++ return __qbman_result_is_x_in_mem(dq, QBMAN_RESULT_CSCN_MEM) || ++ __qbman_result_is_x(dq, QBMAN_RESULT_CSCN_WQ); ++} ++ ++int qbman_result_is_BPSCN(const struct qbman_result *dq) ++{ ++ return __qbman_result_is_x_in_mem(dq, QBMAN_RESULT_BPSCN); ++} ++ ++int qbman_result_is_CGCU(const struct qbman_result *dq) ++{ ++ return __qbman_result_is_x_in_mem(dq, QBMAN_RESULT_CGCU); ++} ++ ++int qbman_result_is_FQRN(const struct qbman_result *dq) ++{ ++ return __qbman_result_is_x_in_mem(dq, QBMAN_RESULT_FQRN); ++} ++ ++int qbman_result_is_FQRNI(const struct qbman_result *dq) ++{ ++ return __qbman_result_is_x_in_mem(dq, QBMAN_RESULT_FQRNI); ++} ++ ++int qbman_result_is_FQPN(const struct qbman_result *dq) ++{ ++ return __qbman_result_is_x(dq, QBMAN_RESULT_FQPN); ++} ++ ++/*********************************/ ++/* Parsing frame dequeue results */ ++/*********************************/ ++ ++/* These APIs assume qbman_result_is_DQ() is TRUE */ ++ ++uint32_t qbman_result_DQ_flags(const struct qbman_result *dq) ++{ ++ const uint32_t *p = qb_cl(dq); ++ return qb_attr_code_decode(&code_dqrr_stat, p); ++} ++ ++uint16_t qbman_result_DQ_seqnum(const struct qbman_result *dq) ++{ ++ const uint32_t *p = qb_cl(dq); ++ return (uint16_t)qb_attr_code_decode(&code_dqrr_seqnum, p); ++} ++ ++uint16_t qbman_result_DQ_odpid(const struct qbman_result *dq) ++{ ++ const uint32_t *p = qb_cl(dq); ++ return (uint16_t)qb_attr_code_decode(&code_dqrr_odpid, p); ++} ++ ++uint32_t qbman_result_DQ_fqid(const struct qbman_result *dq) ++{ ++ const uint32_t *p = qb_cl(dq); ++ return qb_attr_code_decode(&code_dqrr_fqid, p); ++} ++ ++uint32_t qbman_result_DQ_byte_count(const struct qbman_result *dq) ++{ ++ const uint32_t *p = qb_cl(dq); ++ return qb_attr_code_decode(&code_dqrr_byte_count, p); ++} ++ ++uint32_t qbman_result_DQ_frame_count(const struct qbman_result *dq) ++{ ++ const uint32_t *p = qb_cl(dq); ++ return qb_attr_code_decode(&code_dqrr_frame_count, p); ++} ++ ++uint64_t qbman_result_DQ_fqd_ctx(const struct qbman_result *dq) ++{ ++ const uint64_t *p = (const uint64_t *)qb_cl(dq); ++ ++ return qb_attr_code_decode_64(&code_dqrr_ctx_lo, p); ++} ++ ++const struct qbman_fd *qbman_result_DQ_fd(const struct qbman_result *dq) ++{ ++ const uint32_t *p = qb_cl(dq); ++ return (const struct qbman_fd *)&p[8]; ++} ++ ++/**************************************/ ++/* Parsing state-change notifications */ ++/**************************************/ ++ ++static struct qb_attr_code code_scn_state = QB_CODE(0, 16, 8); ++static struct qb_attr_code code_scn_rid = QB_CODE(1, 0, 24); ++static struct qb_attr_code code_scn_state_in_mem = ++ QB_CODE(0, SCN_STATE_OFFSET_IN_MEM, 8); ++static struct qb_attr_code code_scn_rid_in_mem = ++ QB_CODE(1, SCN_RID_OFFSET_IN_MEM, 24); ++static struct qb_attr_code code_scn_ctx_lo = QB_CODE(2, 0, 32); ++ ++uint8_t qbman_result_SCN_state(const struct qbman_result *scn) ++{ ++ const uint32_t *p = qb_cl(scn); ++ return (uint8_t)qb_attr_code_decode(&code_scn_state, p); ++} ++ ++uint32_t qbman_result_SCN_rid(const struct qbman_result *scn) ++{ ++ const uint32_t *p = qb_cl(scn); ++ return qb_attr_code_decode(&code_scn_rid, p); ++} ++ ++uint64_t qbman_result_SCN_ctx(const struct qbman_result *scn) ++{ ++ const uint64_t *p = (const uint64_t *)qb_cl(scn); ++ ++ return qb_attr_code_decode_64(&code_scn_ctx_lo, p); ++} ++ ++uint8_t qbman_result_SCN_state_in_mem(const struct qbman_result *scn) ++{ ++ const uint32_t *p = qb_cl(scn); ++ ++ return (uint8_t)qb_attr_code_decode(&code_scn_state_in_mem, p); ++} ++ ++uint32_t qbman_result_SCN_rid_in_mem(const struct qbman_result *scn) ++{ ++ const uint32_t *p = qb_cl(scn); ++ uint32_t result_rid; ++ ++ result_rid = qb_attr_code_decode(&code_scn_rid_in_mem, p); ++ return make_le24(result_rid); ++} ++ ++/*****************/ ++/* Parsing BPSCN */ ++/*****************/ ++uint16_t qbman_result_bpscn_bpid(const struct qbman_result *scn) ++{ ++ return (uint16_t)qbman_result_SCN_rid_in_mem(scn) & 0x3FFF; ++} ++ ++int qbman_result_bpscn_has_free_bufs(const struct qbman_result *scn) ++{ ++ return !(int)(qbman_result_SCN_state_in_mem(scn) & 0x1); ++} ++ ++int qbman_result_bpscn_is_depleted(const struct qbman_result *scn) ++{ ++ return (int)(qbman_result_SCN_state_in_mem(scn) & 0x2); ++} ++ ++int qbman_result_bpscn_is_surplus(const struct qbman_result *scn) ++{ ++ return (int)(qbman_result_SCN_state_in_mem(scn) & 0x4); ++} ++ ++uint64_t qbman_result_bpscn_ctx(const struct qbman_result *scn) ++{ ++ uint64_t ctx; ++ uint32_t ctx_hi, ctx_lo; ++ ++ ctx = qbman_result_SCN_ctx(scn); ++ ctx_hi = upper32(ctx); ++ ctx_lo = lower32(ctx); ++ return ((uint64_t)make_le32(ctx_hi) << 32 | ++ (uint64_t)make_le32(ctx_lo)); ++} ++ ++/*****************/ ++/* Parsing CGCU */ ++/*****************/ ++uint16_t qbman_result_cgcu_cgid(const struct qbman_result *scn) ++{ ++ return (uint16_t)qbman_result_SCN_rid_in_mem(scn) & 0xFFFF; ++} ++ ++uint64_t qbman_result_cgcu_icnt(const struct qbman_result *scn) ++{ ++ uint64_t ctx; ++ uint32_t ctx_hi, ctx_lo; ++ ++ ctx = qbman_result_SCN_ctx(scn); ++ ctx_hi = upper32(ctx); ++ ctx_lo = lower32(ctx); ++ return ((uint64_t)(make_le32(ctx_hi) & 0xFF) << 32) | ++ (uint64_t)make_le32(ctx_lo); ++} ++ ++/******************/ ++/* Buffer release */ ++/******************/ ++ ++/* These should be const, eventually */ ++/* static struct qb_attr_code code_release_num = QB_CODE(0, 0, 3); */ ++static struct qb_attr_code code_release_set_me = QB_CODE(0, 5, 1); ++static struct qb_attr_code code_release_rcdi = QB_CODE(0, 6, 1); ++static struct qb_attr_code code_release_bpid = QB_CODE(0, 16, 16); ++ ++void qbman_release_desc_clear(struct qbman_release_desc *d) ++{ ++ uint32_t *cl; ++ memset(d, 0, sizeof(*d)); ++ cl = qb_cl(d); ++ qb_attr_code_encode(&code_release_set_me, cl, 1); ++} ++ ++void qbman_release_desc_set_bpid(struct qbman_release_desc *d, uint32_t bpid) ++{ ++ uint32_t *cl = qb_cl(d); ++ qb_attr_code_encode(&code_release_bpid, cl, bpid); ++} ++ ++void qbman_release_desc_set_rcdi(struct qbman_release_desc *d, int enable) ++{ ++ uint32_t *cl = qb_cl(d); ++ qb_attr_code_encode(&code_release_rcdi, cl, !!enable); ++} ++ ++#define RAR_IDX(rar) ((rar) & 0x7) ++#define RAR_VB(rar) ((rar) & 0x80) ++#define RAR_SUCCESS(rar) ((rar) & 0x100) ++ ++int qbman_swp_release(struct qbman_swp *s, const struct qbman_release_desc *d, ++ const uint64_t *buffers, unsigned int num_buffers) ++{ ++ uint32_t *p; ++ const uint32_t *cl = qb_cl(d); ++ uint32_t rar = qbman_cinh_read(&s->sys, QBMAN_CINH_SWP_RAR); ++ pr_debug("RAR=%08x\n", rar); ++ if (!RAR_SUCCESS(rar)) ++ return -EBUSY; ++ BUG_ON(!num_buffers || (num_buffers > 7)); ++ /* Start the release command */ ++ p = qbman_cena_write_start_wo_shadow(&s->sys, ++ QBMAN_CENA_SWP_RCR(RAR_IDX(rar))); ++ /* Copy the caller's buffer pointers to the command */ ++ u64_to_le32_copy(&p[2], buffers, num_buffers); ++ /* Set the verb byte, have to substitute in the valid-bit and the number ++ * of buffers. */ ++ lwsync(); ++ p[0] = cl[0] | RAR_VB(rar) | num_buffers; ++ qbman_cena_write_complete_wo_shadow(&s->sys, ++ QBMAN_CENA_SWP_RCR(RAR_IDX(rar))); ++ return 0; ++} ++ ++/*******************/ ++/* Buffer acquires */ ++/*******************/ ++ ++/* These should be const, eventually */ ++static struct qb_attr_code code_acquire_bpid = QB_CODE(0, 16, 16); ++static struct qb_attr_code code_acquire_num = QB_CODE(1, 0, 3); ++static struct qb_attr_code code_acquire_r_num = QB_CODE(1, 0, 3); ++ ++int qbman_swp_acquire(struct qbman_swp *s, uint32_t bpid, uint64_t *buffers, ++ unsigned int num_buffers) ++{ ++ uint32_t *p; ++ uint32_t rslt, num; ++ BUG_ON(!num_buffers || (num_buffers > 7)); ++ ++ /* Start the management command */ ++ p = qbman_swp_mc_start(s); ++ ++ if (!p) ++ return -EBUSY; ++ ++ /* Encode the caller-provided attributes */ ++ qb_attr_code_encode(&code_acquire_bpid, p, bpid); ++ qb_attr_code_encode(&code_acquire_num, p, num_buffers); ++ ++ /* Complete the management command */ ++ p = qbman_swp_mc_complete(s, p, p[0] | QBMAN_MC_ACQUIRE); ++ ++ /* Decode the outcome */ ++ rslt = qb_attr_code_decode(&code_generic_rslt, p); ++ num = qb_attr_code_decode(&code_acquire_r_num, p); ++ BUG_ON(qb_attr_code_decode(&code_generic_verb, p) != QBMAN_MC_ACQUIRE); ++ ++ /* Determine success or failure */ ++ if (unlikely(rslt != QBMAN_MC_RSLT_OK)) { ++ pr_err("Acquire buffers from BPID 0x%x failed, code=0x%02x\n", ++ bpid, rslt); ++ return -EIO; ++ } ++ BUG_ON(num > num_buffers); ++ /* Copy the acquired buffers to the caller's array */ ++ u64_from_le32_copy(buffers, &p[2], num); ++ return (int)num; ++} ++ ++/*****************/ ++/* FQ management */ ++/*****************/ ++ ++static struct qb_attr_code code_fqalt_fqid = QB_CODE(1, 0, 32); ++ ++static int qbman_swp_alt_fq_state(struct qbman_swp *s, uint32_t fqid, ++ uint8_t alt_fq_verb) ++{ ++ uint32_t *p; ++ uint32_t rslt; ++ ++ /* Start the management command */ ++ p = qbman_swp_mc_start(s); ++ if (!p) ++ return -EBUSY; ++ ++ qb_attr_code_encode(&code_fqalt_fqid, p, fqid); ++ /* Complete the management command */ ++ p = qbman_swp_mc_complete(s, p, p[0] | alt_fq_verb); ++ ++ /* Decode the outcome */ ++ rslt = qb_attr_code_decode(&code_generic_rslt, p); ++ BUG_ON(qb_attr_code_decode(&code_generic_verb, p) != alt_fq_verb); ++ ++ /* Determine success or failure */ ++ if (unlikely(rslt != QBMAN_MC_RSLT_OK)) { ++ pr_err("ALT FQID %d failed: verb = 0x%08x, code = 0x%02x\n", ++ fqid, alt_fq_verb, rslt); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++int qbman_swp_fq_schedule(struct qbman_swp *s, uint32_t fqid) ++{ ++ return qbman_swp_alt_fq_state(s, fqid, QBMAN_FQ_SCHEDULE); ++} ++ ++int qbman_swp_fq_force(struct qbman_swp *s, uint32_t fqid) ++{ ++ return qbman_swp_alt_fq_state(s, fqid, QBMAN_FQ_FORCE); ++} ++ ++int qbman_swp_fq_xon(struct qbman_swp *s, uint32_t fqid) ++{ ++ return qbman_swp_alt_fq_state(s, fqid, QBMAN_FQ_XON); ++} ++ ++int qbman_swp_fq_xoff(struct qbman_swp *s, uint32_t fqid) ++{ ++ return qbman_swp_alt_fq_state(s, fqid, QBMAN_FQ_XOFF); ++} ++ ++/**********************/ ++/* Channel management */ ++/**********************/ ++ ++static struct qb_attr_code code_cdan_cid = QB_CODE(0, 16, 12); ++static struct qb_attr_code code_cdan_we = QB_CODE(1, 0, 8); ++static struct qb_attr_code code_cdan_en = QB_CODE(1, 8, 1); ++static struct qb_attr_code code_cdan_ctx_lo = QB_CODE(2, 0, 32); ++ ++/* Hide "ICD" for now as we don't use it, don't set it, and don't test it, so it ++ * would be irresponsible to expose it. */ ++#define CODE_CDAN_WE_EN 0x1 ++#define CODE_CDAN_WE_CTX 0x4 ++ ++static int qbman_swp_CDAN_set(struct qbman_swp *s, uint16_t channelid, ++ uint8_t we_mask, uint8_t cdan_en, ++ uint64_t ctx) ++{ ++ uint32_t *p; ++ uint32_t rslt; ++ ++ /* Start the management command */ ++ p = qbman_swp_mc_start(s); ++ if (!p) ++ return -EBUSY; ++ ++ /* Encode the caller-provided attributes */ ++ qb_attr_code_encode(&code_cdan_cid, p, channelid); ++ qb_attr_code_encode(&code_cdan_we, p, we_mask); ++ qb_attr_code_encode(&code_cdan_en, p, cdan_en); ++ qb_attr_code_encode_64(&code_cdan_ctx_lo, (uint64_t *)p, ctx); ++ /* Complete the management command */ ++ p = qbman_swp_mc_complete(s, p, p[0] | QBMAN_WQCHAN_CONFIGURE); ++ ++ /* Decode the outcome */ ++ rslt = qb_attr_code_decode(&code_generic_rslt, p); ++ BUG_ON(qb_attr_code_decode(&code_generic_verb, p) ++ != QBMAN_WQCHAN_CONFIGURE); ++ ++ /* Determine success or failure */ ++ if (unlikely(rslt != QBMAN_MC_RSLT_OK)) { ++ pr_err("CDAN cQID %d failed: code = 0x%02x\n", ++ channelid, rslt); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++int qbman_swp_CDAN_set_context(struct qbman_swp *s, uint16_t channelid, ++ uint64_t ctx) ++{ ++ return qbman_swp_CDAN_set(s, channelid, ++ CODE_CDAN_WE_CTX, ++ 0, ctx); ++} ++ ++int qbman_swp_CDAN_enable(struct qbman_swp *s, uint16_t channelid) ++{ ++ return qbman_swp_CDAN_set(s, channelid, ++ CODE_CDAN_WE_EN, ++ 1, 0); ++} ++ ++int qbman_swp_CDAN_disable(struct qbman_swp *s, uint16_t channelid) ++{ ++ return qbman_swp_CDAN_set(s, channelid, ++ CODE_CDAN_WE_EN, ++ 0, 0); ++} ++ ++int qbman_swp_CDAN_set_context_enable(struct qbman_swp *s, uint16_t channelid, ++ uint64_t ctx) ++{ ++ return qbman_swp_CDAN_set(s, channelid, ++ CODE_CDAN_WE_EN | CODE_CDAN_WE_CTX, ++ 1, ctx); ++} ++ ++uint8_t qbman_get_dqrr_idx(struct qbman_result *dqrr) ++{ ++ return QBMAN_IDX_FROM_DQRR(dqrr); ++} ++ ++struct qbman_result *qbman_get_dqrr_from_idx(struct qbman_swp *s, uint8_t idx) ++{ ++ struct qbman_result *dq; ++ dq = qbman_cena_read(&s->sys, QBMAN_CENA_SWP_DQRR(idx)); ++ return dq; ++} ++ ++int qbman_swp_send_multiple(struct qbman_swp *s, ++ const struct qbman_eq_desc *d, ++ const struct qbman_fd *fd, ++ int frames_to_send) ++{ ++ uint32_t *p; ++ const uint32_t *cl = qb_cl(d); ++ uint32_t eqcr_ci; ++ uint8_t diff; ++ int sent = 0; ++ int i; ++ int initial_pi = s->eqcr.pi; ++ uint64_t start_pointer; ++ ++ ++ /* we are trying to send frames_to_send if we have enough space in the ring */ ++ while(frames_to_send--) ++ { ++ if (!s->eqcr.available) { ++ eqcr_ci = s->eqcr.ci; ++ s->eqcr.ci = qbman_cena_read_reg(&s->sys, ++ QBMAN_CENA_SWP_EQCR_CI) & 0xF; ++ diff = qm_cyc_diff(QBMAN_EQCR_SIZE, ++ eqcr_ci, s->eqcr.ci); ++ s->eqcr.available += diff; ++ if (!diff) ++ { ++ goto done; ++ } ++ } ++ ++ p = qbman_cena_write_start_wo_shadow_fast(&s->sys, ++ QBMAN_CENA_SWP_EQCR((initial_pi) & 7)); ++ /* Write command (except of first byte) and FD */ ++ memcpy(&p[1], &cl[1], 7); ++ memcpy(&p[8], &fd[sent], sizeof(struct qbman_fd)); ++ ++ initial_pi++; ++ initial_pi &= 0xF; ++ s->eqcr.available--; ++ sent++; ++ ++ } ++ ++ done: ++ initial_pi = s->eqcr.pi; ++ lwsync(); ++ ++ /* in order for flushes to complete faster */ ++ /*For that we use a following trick: we record all lines in 32 bit word */ ++ ++ initial_pi = s->eqcr.pi; ++ for(i = 0; i < sent; i++) ++ { ++ p = qbman_cena_write_start_wo_shadow_fast(&s->sys, ++ QBMAN_CENA_SWP_EQCR((initial_pi) & 7)); ++ ++ p[0] = cl[0] | s->eqcr.pi_vb; ++ initial_pi++; ++ initial_pi &= 0xF; ++ ++ if (!(initial_pi & 7)) ++ s->eqcr.pi_vb ^= QB_VALID_BIT; ++ ++ } ++ ++ initial_pi = s->eqcr.pi; ++ ++ /* We need to flush all the lines but without load/store operations between them */ ++ /* We assign start_pointer before we start loop so that in loop we do not read it from memory */ ++ start_pointer = (uint64_t) s->sys.addr_cena; ++ for(i = 0; i < sent; i++) ++ { ++ p = (uint32_t *)(start_pointer + QBMAN_CENA_SWP_EQCR(initial_pi & 7)); ++ dcbf((uint64_t)p); ++ initial_pi++; ++ initial_pi &= 0xF; ++ } ++ ++ /* Update producer index for the next call */ ++ s->eqcr.pi = initial_pi; ++ ++ return sent; ++} +diff --git a/drivers/net/dpaa2/qbman/driver/qbman_portal.h b/drivers/net/dpaa2/qbman/driver/qbman_portal.h +new file mode 100644 +index 0000000..f6ba86a +--- /dev/null ++++ b/drivers/net/dpaa2/qbman/driver/qbman_portal.h +@@ -0,0 +1,266 @@ ++/* Copyright (C) 2014 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY ++ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include "qbman_private.h" ++#include ++ ++uint32_t qman_version; ++/* All QBMan command and result structures use this "valid bit" encoding */ ++#define QB_VALID_BIT ((uint32_t)0x80) ++ ++/* Management command result codes */ ++#define QBMAN_MC_RSLT_OK 0xf0 ++ ++/* TBD: as of QBMan 4.1, DQRR will be 8 rather than 4! */ ++#define QBMAN_DQRR_SIZE 4 ++ ++#define QBMAN_EQCR_SIZE 8 ++ ++static inline u8 qm_cyc_diff(u8 ringsize, u8 first, u8 last) ++{ ++ /* 'first' is included, 'last' is excluded */ ++ if (first <= last) ++ return last - first; ++ return (2 * ringsize) + last - first; ++} ++ ++/* --------------------- */ ++/* portal data structure */ ++/* --------------------- */ ++ ++struct qbman_swp { ++ const struct qbman_swp_desc *desc; ++ /* The qbman_sys (ie. arch/OS-specific) support code can put anything it ++ * needs in here. */ ++ struct qbman_swp_sys sys; ++ /* Management commands */ ++ struct { ++#ifdef QBMAN_CHECKING ++ enum swp_mc_check { ++ swp_mc_can_start, /* call __qbman_swp_mc_start() */ ++ swp_mc_can_submit, /* call __qbman_swp_mc_submit() */ ++ swp_mc_can_poll, /* call __qbman_swp_mc_result() */ ++ } check; ++#endif ++ uint32_t valid_bit; /* 0x00 or 0x80 */ ++ } mc; ++ /* Push dequeues */ ++ uint32_t sdq; ++ /* Volatile dequeues */ ++ struct { ++ /* VDQCR supports a "1 deep pipeline", meaning that if you know ++ * the last-submitted command is already executing in the ++ * hardware (as evidenced by at least 1 valid dequeue result), ++ * you can write another dequeue command to the register, the ++ * hardware will start executing it as soon as the ++ * already-executing command terminates. (This minimises latency ++ * and stalls.) With that in mind, this "busy" variable refers ++ * to whether or not a command can be submitted, not whether or ++ * not a previously-submitted command is still executing. In ++ * other words, once proof is seen that the previously-submitted ++ * command is executing, "vdq" is no longer "busy". */ ++ atomic_t busy; ++ uint32_t valid_bit; /* 0x00 or 0x80 */ ++ /* We need to determine when vdq is no longer busy. This depends ++ * on whether the "busy" (last-submitted) dequeue command is ++ * targetting DQRR or main-memory, and detected is based on the ++ * presence of the dequeue command's "token" showing up in ++ * dequeue entries in DQRR or main-memory (respectively). */ ++ struct qbman_result *storage; /* NULL if DQRR */ ++ } vdq; ++ /* DQRR */ ++ struct { ++ uint32_t next_idx; ++ uint32_t valid_bit; ++ uint8_t dqrr_size; ++ int reset_bug; ++ } dqrr; ++ struct { ++ uint32_t pi; ++ uint32_t pi_vb; ++ uint32_t ci; ++ int available; ++ } eqcr; ++}; ++ ++/* -------------------------- */ ++/* portal management commands */ ++/* -------------------------- */ ++ ++/* Different management commands all use this common base layer of code to issue ++ * commands and poll for results. The first function returns a pointer to where ++ * the caller should fill in their MC command (though they should ignore the ++ * verb byte), the second function commits merges in the caller-supplied command ++ * verb (which should not include the valid-bit) and submits the command to ++ * hardware, and the third function checks for a completed response (returns ++ * non-NULL if only if the response is complete). */ ++void *qbman_swp_mc_start(struct qbman_swp *p); ++void qbman_swp_mc_submit(struct qbman_swp *p, void *cmd, uint32_t cmd_verb); ++void *qbman_swp_mc_result(struct qbman_swp *p); ++ ++/* Wraps up submit + poll-for-result */ ++static inline void *qbman_swp_mc_complete(struct qbman_swp *swp, void *cmd, ++ uint32_t cmd_verb) ++{ ++ int loopvar; ++ qbman_swp_mc_submit(swp, cmd, cmd_verb); ++ DBG_POLL_START(loopvar); ++ do { ++ DBG_POLL_CHECK(loopvar); ++ cmd = qbman_swp_mc_result(swp); ++ } while (!cmd); ++ return cmd; ++} ++ ++/* ------------ */ ++/* qb_attr_code */ ++/* ------------ */ ++ ++/* This struct locates a sub-field within a QBMan portal (CENA) cacheline which ++ * is either serving as a configuration command or a query result. The ++ * representation is inherently little-endian, as the indexing of the words is ++ * itself little-endian in nature and DPAA2 QBMan is little endian for anything ++ * that crosses a word boundary too (64-bit fields are the obvious examples). ++ */ ++struct qb_attr_code { ++ unsigned int word; /* which uint32_t[] array member encodes the field */ ++ unsigned int lsoffset; /* encoding offset from ls-bit */ ++ unsigned int width; /* encoding width. (bool must be 1.) */ ++}; ++ ++/* Some pre-defined codes */ ++extern struct qb_attr_code code_generic_verb; ++extern struct qb_attr_code code_generic_rslt; ++ ++/* Macros to define codes */ ++#define QB_CODE(a, b, c) { a, b, c} ++#define QB_CODE_NULL \ ++ QB_CODE((unsigned int)-1, (unsigned int)-1, (unsigned int)-1) ++ ++/* Rotate a code "ms", meaning that it moves from less-significant bytes to ++ * more-significant, from less-significant words to more-significant, etc. The ++ * "ls" version does the inverse, from more-significant towards ++ * less-significant. ++ */ ++static inline void qb_attr_code_rotate_ms(struct qb_attr_code *code, ++ unsigned int bits) ++{ ++ code->lsoffset += bits; ++ while (code->lsoffset > 31) { ++ code->word++; ++ code->lsoffset -= 32; ++ } ++} ++static inline void qb_attr_code_rotate_ls(struct qb_attr_code *code, ++ unsigned int bits) ++{ ++ /* Don't be fooled, this trick should work because the types are ++ * unsigned. So the case that interests the while loop (the rotate has ++ * gone too far and the word count needs to compensate for it), is ++ * manifested when lsoffset is negative. But that equates to a really ++ * large unsigned value, starting with lots of "F"s. As such, we can ++ * continue adding 32 back to it until it wraps back round above zero, ++ * to a value of 31 or less... ++ */ ++ code->lsoffset -= bits; ++ while (code->lsoffset > 31) { ++ code->word--; ++ code->lsoffset += 32; ++ } ++} ++/* Implement a loop of code rotations until 'expr' evaluates to FALSE (0). */ ++#define qb_attr_code_for_ms(code, bits, expr) \ ++ for (; expr; qb_attr_code_rotate_ms(code, bits)) ++#define qb_attr_code_for_ls(code, bits, expr) \ ++ for (; expr; qb_attr_code_rotate_ls(code, bits)) ++ ++/* decode a field from a cacheline */ ++static inline uint32_t qb_attr_code_decode(const struct qb_attr_code *code, ++ const uint32_t *cacheline) ++{ ++ return d32_uint32_t(code->lsoffset, code->width, cacheline[code->word]); ++} ++static inline uint64_t qb_attr_code_decode_64(const struct qb_attr_code *code, ++ const uint64_t *cacheline) ++{ ++ return cacheline[code->word / 2]; ++} ++ ++/* encode a field to a cacheline */ ++static inline void qb_attr_code_encode(const struct qb_attr_code *code, ++ uint32_t *cacheline, uint32_t val) ++{ ++ cacheline[code->word] = ++ r32_uint32_t(code->lsoffset, code->width, cacheline[code->word]) ++ | e32_uint32_t(code->lsoffset, code->width, val); ++} ++static inline void qb_attr_code_encode_64(const struct qb_attr_code *code, ++ uint64_t *cacheline, uint64_t val) ++{ ++ cacheline[code->word / 2] = val; ++} ++ ++/* Small-width signed values (two's-complement) will decode into medium-width ++ * positives. (Eg. for an 8-bit signed field, which stores values from -128 to ++ * +127, a setting of -7 would appear to decode to the 32-bit unsigned value ++ * 249. Likewise -120 would decode as 136.) This function allows the caller to ++ * "re-sign" such fields to 32-bit signed. (Eg. -7, which was 249 with an 8-bit ++ * encoding, will become 0xfffffff9 if you cast the return value to uint32_t). ++ */ ++static inline int32_t qb_attr_code_makesigned(const struct qb_attr_code *code, ++ uint32_t val) ++{ ++ BUG_ON(val >= (1u << code->width)); ++ /* code->width should never exceed the width of val. If it does then a ++ * different function with larger val size must be used to translate ++ * from unsigned to signed */ ++ BUG_ON(code->width > sizeof(val) * CHAR_BIT); ++ /* If the high bit was set, it was encoding a negative */ ++ if (val >= 1u << (code->width - 1)) ++ return (int32_t)0 - (int32_t)(((uint32_t)1 << code->width) - ++ val); ++ /* Otherwise, it was encoding a positive */ ++ return (int32_t)val; ++} ++ ++/* ---------------------- */ ++/* Descriptors/cachelines */ ++/* ---------------------- */ ++ ++/* To avoid needless dynamic allocation, the driver API often gives the caller ++ * a "descriptor" type that the caller can instantiate however they like. ++ * Ultimately though, it is just a cacheline of binary storage (or something ++ * smaller when it is known that the descriptor doesn't need all 64 bytes) for ++ * holding pre-formatted pieces of harware commands. The performance-critical ++ * code can then copy these descriptors directly into hardware command ++ * registers more efficiently than trying to construct/format commands ++ * on-the-fly. The API user sees the descriptor as an array of 32-bit words in ++ * order for the compiler to know its size, but the internal details are not ++ * exposed. The following macro is used within the driver for converting *any* ++ * descriptor pointer to a usable array pointer. The use of a macro (instead of ++ * an inline) is necessary to work with different descriptor types and to work ++ * correctly with const and non-const inputs (and similarly-qualified outputs). ++ */ ++#define qb_cl(d) (&(d)->dont_manipulate_directly[0]) +diff --git a/drivers/net/dpaa2/qbman/driver/qbman_private.h b/drivers/net/dpaa2/qbman/driver/qbman_private.h +new file mode 100644 +index 0000000..4e50b61 +--- /dev/null ++++ b/drivers/net/dpaa2/qbman/driver/qbman_private.h +@@ -0,0 +1,165 @@ ++/* Copyright (C) 2014 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY ++ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++*/ ++ ++/* Perform extra checking */ ++#define QBMAN_CHECKING ++ ++/* To maximise the amount of logic that is common between the Linux driver and ++ * other targets (such as the embedded MC firmware), we pivot here between the ++ * inclusion of two platform-specific headers. ++ * ++ * The first, qbman_sys_decl.h, includes any and all required system headers as ++ * well as providing any definitions for the purposes of compatibility. The ++ * second, qbman_sys.h, is where platform-specific routines go. ++ * ++ * The point of the split is that the platform-independent code (including this ++ * header) may depend on platform-specific declarations, yet other ++ * platform-specific routines may depend on platform-independent definitions. ++ */ ++ ++#include "qbman_sys_decl.h" ++ ++/* When things go wrong, it is a convenient trick to insert a few FOO() ++ * statements in the code to trace progress. TODO: remove this once we are ++ * hacking the code less actively. ++ */ ++#define FOO() fsl_os_print("FOO: %s:%d\n", __FILE__, __LINE__) ++ ++/* Any time there is a register interface which we poll on, this provides a ++ * "break after x iterations" scheme for it. It's handy for debugging, eg. ++ * where you don't want millions of lines of log output from a polling loop ++ * that won't, because such things tend to drown out the earlier log output ++ * that might explain what caused the problem. (NB: put ";" after each macro!) ++ * TODO: we should probably remove this once we're done sanitising the ++ * simulator... ++ */ ++#define DBG_POLL_START(loopvar) (loopvar = 10) ++#define DBG_POLL_CHECK(loopvar) \ ++ do {if (!(loopvar--)) BUG_ON(NULL == "DBG_POLL_CHECK"); } while (0) ++ ++/* For CCSR or portal-CINH registers that contain fields at arbitrary offsets ++ * and widths, these macro-generated encode/decode/isolate/remove inlines can ++ * be used. ++ * ++ * Eg. to "d"ecode a 14-bit field out of a register (into a "uint16_t" type), ++ * where the field is located 3 bits "up" from the least-significant bit of the ++ * register (ie. the field location within the 32-bit register corresponds to a ++ * mask of 0x0001fff8), you would do; ++ * uint16_t field = d32_uint16_t(3, 14, reg_value); ++ * ++ * Or to "e"ncode a 1-bit boolean value (input type is "int", zero is FALSE, ++ * non-zero is TRUE, so must convert all non-zero inputs to 1, hence the "!!" ++ * operator) into a register at bit location 0x00080000 (19 bits "in" from the ++ * LS bit), do; ++ * reg_value |= e32_int(19, 1, !!field); ++ * ++ * If you wish to read-modify-write a register, such that you leave the 14-bit ++ * field as-is but have all other fields set to zero, then "i"solate the 14-bit ++ * value using; ++ * reg_value = i32_uint16_t(3, 14, reg_value); ++ * ++ * Alternatively, you could "r"emove the 1-bit boolean field (setting it to ++ * zero) but leaving all other fields as-is; ++ * reg_val = r32_int(19, 1, reg_value); ++ * ++ */ ++#define MAKE_MASK32(width) (width == 32 ? 0xffffffff : \ ++ (uint32_t)((1 << width) - 1)) ++#define DECLARE_CODEC32(t) \ ++static inline uint32_t e32_##t(uint32_t lsoffset, uint32_t width, t val) \ ++{ \ ++ BUG_ON(width > (sizeof(t) * 8)); \ ++ return ((uint32_t)val & MAKE_MASK32(width)) << lsoffset; \ ++} \ ++static inline t d32_##t(uint32_t lsoffset, uint32_t width, uint32_t val) \ ++{ \ ++ BUG_ON(width > (sizeof(t) * 8)); \ ++ return (t)((val >> lsoffset) & MAKE_MASK32(width)); \ ++} \ ++static inline uint32_t i32_##t(uint32_t lsoffset, uint32_t width, \ ++ uint32_t val) \ ++{ \ ++ BUG_ON(width > (sizeof(t) * 8)); \ ++ return e32_##t(lsoffset, width, d32_##t(lsoffset, width, val)); \ ++} \ ++static inline uint32_t r32_##t(uint32_t lsoffset, uint32_t width, \ ++ uint32_t val) \ ++{ \ ++ BUG_ON(width > (sizeof(t) * 8)); \ ++ return ~(MAKE_MASK32(width) << lsoffset) & val; \ ++} ++DECLARE_CODEC32(uint32_t) ++DECLARE_CODEC32(uint16_t) ++DECLARE_CODEC32(uint8_t) ++DECLARE_CODEC32(int) ++ ++ /*********************/ ++ /* Debugging assists */ ++ /*********************/ ++ ++static inline void __hexdump(unsigned long start, unsigned long end, ++ unsigned long p, size_t sz, const unsigned char *c) ++{ ++ while (start < end) { ++ unsigned int pos = 0; ++ char buf[64]; ++ int nl = 0; ++ pos += sprintf(buf + pos, "%08lx: ", start); ++ do { ++ if ((start < p) || (start >= (p + sz))) ++ pos += sprintf(buf + pos, ".."); ++ else ++ pos += sprintf(buf + pos, "%02x", *(c++)); ++ if (!(++start & 15)) { ++ buf[pos++] = '\n'; ++ nl = 1; ++ } else { ++ nl = 0; ++ if (!(start & 1)) ++ buf[pos++] = ' '; ++ if (!(start & 3)) ++ buf[pos++] = ' '; ++ } ++ } while (start & 15); ++ if (!nl) ++ buf[pos++] = '\n'; ++ buf[pos] = '\0'; ++ pr_info("%s", buf); ++ } ++} ++static inline void hexdump(const void *ptr, size_t sz) ++{ ++ unsigned long p = (unsigned long)ptr; ++ unsigned long start = p & ~(unsigned long)15; ++ unsigned long end = (p + sz + 15) & ~(unsigned long)15; ++ const unsigned char *c = ptr; ++ __hexdump(start, end, p, sz, c); ++} ++ ++#define QMAN_REV_4000 0x04000000 ++#define QMAN_REV_4100 0x04010000 ++#define QMAN_REV_4101 0x04010001 ++ ++#include "qbman_sys.h" +diff --git a/drivers/net/dpaa2/qbman/driver/qbman_sys.h b/drivers/net/dpaa2/qbman/driver/qbman_sys.h +new file mode 100644 +index 0000000..d912ab0 +--- /dev/null ++++ b/drivers/net/dpaa2/qbman/driver/qbman_sys.h +@@ -0,0 +1,367 @@ ++/* Copyright (C) 2014 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY ++ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++/* qbman_sys_decl.h and qbman_sys.h are the two platform-specific files in the ++ * driver. They are only included via qbman_private.h, which is itself a ++ * platform-independent file and is included by all the other driver source. ++ * ++ * qbman_sys_decl.h is included prior to all other declarations and logic, and ++ * it exists to provide compatibility with any linux interfaces our ++ * single-source driver code is dependent on (eg. kmalloc). Ie. this file ++ * provides linux compatibility. ++ * ++ * This qbman_sys.h header, on the other hand, is included *after* any common ++ * and platform-neutral declarations and logic in qbman_private.h, and exists to ++ * implement any platform-specific logic of the qbman driver itself. Ie. it is ++ * *not* to provide linux compatibility. ++ */ ++ ++/* Trace the 3 different classes of read/write access to QBMan. #undef as ++ * required. */ ++#undef QBMAN_CCSR_TRACE ++#undef QBMAN_CINH_TRACE ++#undef QBMAN_CENA_TRACE ++ ++static inline void word_copy(void *d, const void *s, unsigned int cnt) ++{ ++ uint32_t *dd = d; ++ const uint32_t *ss = s; ++ while (cnt--) ++ *(dd++) = *(ss++); ++} ++ ++/* Currently, the CENA support code expects each 32-bit word to be written in ++ * host order, and these are converted to hardware (little-endian) order on ++ * command submission. However, 64-bit quantities are must be written (and read) ++ * as two 32-bit words with the least-significant word first, irrespective of ++ * host endianness. */ ++static inline void u64_to_le32_copy(void *d, const uint64_t *s, ++ unsigned int cnt) ++{ ++ uint32_t *dd = d; ++ const uint32_t *ss = (const uint32_t *)s; ++ while (cnt--) { ++ /* TBD: the toolchain was choking on the use of 64-bit types up ++ * until recently so this works entirely with 32-bit variables. ++ * When 64-bit types become usable again, investigate better ++ * ways of doing this. */ ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ++ *(dd++) = ss[1]; ++ *(dd++) = ss[0]; ++ ss += 2; ++#else ++ *(dd++) = *(ss++); ++ *(dd++) = *(ss++); ++#endif ++ } ++} ++static inline void u64_from_le32_copy(uint64_t *d, const void *s, ++ unsigned int cnt) ++{ ++ const uint32_t *ss = s; ++ uint32_t *dd = (uint32_t *)d; ++ while (cnt--) { ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ++ dd[1] = *(ss++); ++ dd[0] = *(ss++); ++ dd += 2; ++#else ++ *(dd++) = *(ss++); ++ *(dd++) = *(ss++); ++#endif ++ } ++} ++ ++/* Convert a host-native 32bit value into little endian */ ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ++static inline uint32_t make_le32(uint32_t val) ++{ ++ return ((val & 0xff) << 24) | ((val & 0xff00) << 8) | ++ ((val & 0xff0000) >> 8) | ((val & 0xff000000) >> 24); ++} ++static inline uint32_t make_le24(uint32_t val) ++{ ++ return (((val & 0xff) << 16) | (val & 0xff00) | ++ ((val & 0xff0000) >> 16)); ++} ++#else ++#define make_le32(val) (val) ++#define make_le24(val) (val) ++#endif ++static inline void make_le32_n(uint32_t *val, unsigned int num) ++{ ++ while (num--) { ++ *val = make_le32(*val); ++ val++; ++ } ++} ++ ++ /******************/ ++ /* Portal access */ ++ /******************/ ++struct qbman_swp_sys { ++ /* On GPP, the sys support for qbman_swp is here. The CENA region isi ++ * not an mmap() of the real portal registers, but an allocated ++ * place-holder, because the actual writes/reads to/from the portal are ++ * marshalled from these allocated areas using QBMan's "MC access ++ * registers". CINH accesses are atomic so there's no need for a ++ * place-holder. */ ++ uint8_t *cena; ++ uint8_t __iomem *addr_cena; ++ uint8_t __iomem *addr_cinh; ++ uint32_t idx; ++ enum qbman_eqcr_mode eqcr_mode; ++}; ++ ++/* P_OFFSET is (ACCESS_CMD,0,12) - offset within the portal ++ * C is (ACCESS_CMD,12,1) - is inhibited? (0==CENA, 1==CINH) ++ * SWP_IDX is (ACCESS_CMD,16,10) - Software portal index ++ * P is (ACCESS_CMD,28,1) - (0==special portal, 1==any portal) ++ * T is (ACCESS_CMD,29,1) - Command type (0==READ, 1==WRITE) ++ * E is (ACCESS_CMD,31,1) - Command execute (1 to issue, poll for 0==complete) ++ */ ++ ++static inline void qbman_cinh_write(struct qbman_swp_sys *s, uint32_t offset, ++ uint32_t val) ++{ ++ ++ __raw_writel(val, s->addr_cinh + offset); ++#ifdef QBMAN_CINH_TRACE ++ pr_info("qbman_cinh_write(%p:%d:0x%03x) 0x%08x\n", ++ s->addr_cinh, s->idx, offset, val); ++#endif ++} ++ ++static inline uint32_t qbman_cinh_read(struct qbman_swp_sys *s, uint32_t offset) ++{ ++ uint32_t reg = __raw_readl(s->addr_cinh + offset); ++#ifdef QBMAN_CINH_TRACE ++ pr_info("qbman_cinh_read(%p:%d:0x%03x) 0x%08x\n", ++ s->addr_cinh, s->idx, offset, reg); ++#endif ++ return reg; ++} ++ ++static inline void *qbman_cena_write_start(struct qbman_swp_sys *s, ++ uint32_t offset) ++{ ++ void *shadow = s->cena + offset; ++ ++#ifdef QBMAN_CENA_TRACE ++ pr_info("qbman_cena_write_start(%p:%d:0x%03x) %p\n", ++ s->addr_cena, s->idx, offset, shadow); ++#endif ++ BUG_ON(offset & 63); ++ dcbz(shadow); ++ return shadow; ++} ++ ++static inline void *qbman_cena_write_start_wo_shadow(struct qbman_swp_sys *s, ++ uint32_t offset) ++{ ++#ifdef QBMAN_CENA_TRACE ++ pr_info("qbman_cena_write_start(%p:%d:0x%03x)\n", ++ s->addr_cena, s->idx, offset); ++#endif ++ BUG_ON(offset & 63); ++ return (s->addr_cena + offset); ++} ++ ++static inline void qbman_cena_write_complete(struct qbman_swp_sys *s, ++ uint32_t offset, void *cmd) ++{ ++ const uint32_t *shadow = cmd; ++ int loop; ++#ifdef QBMAN_CENA_TRACE ++ pr_info("qbman_cena_write_complete(%p:%d:0x%03x) %p\n", ++ s->addr_cena, s->idx, offset, shadow); ++ hexdump(cmd, 64); ++#endif ++ for (loop = 15; loop >= 1; loop--) ++ __raw_writel(shadow[loop], s->addr_cena + ++ offset + loop * 4); ++ lwsync(); ++ __raw_writel(shadow[0], s->addr_cena + offset); ++ dcbf(s->addr_cena + offset); ++} ++ ++static inline void qbman_cena_write_complete_wo_shadow(struct qbman_swp_sys *s, ++ uint32_t offset) ++{ ++#ifdef QBMAN_CENA_TRACE ++ pr_info("qbman_cena_write_complete(%p:%d:0x%03x)\n", ++ s->addr_cena, s->idx, offset); ++ hexdump(cmd, 64); ++#endif ++ dcbf(s->addr_cena + offset); ++} ++ ++static inline uint32_t qbman_cena_read_reg(struct qbman_swp_sys *s, ++ uint32_t offset) ++{ ++ return __raw_readl(s->addr_cena + offset); ++} ++ ++static inline void *qbman_cena_read(struct qbman_swp_sys *s, uint32_t offset) ++{ ++ uint32_t *shadow = (uint32_t *)(s->cena + offset); ++ unsigned int loop; ++#ifdef QBMAN_CENA_TRACE ++ pr_info("qbman_cena_read(%p:%d:0x%03x) %p\n", ++ s->addr_cena, s->idx, offset, shadow); ++#endif ++ ++ for (loop = 0; loop < 16; loop++) ++ shadow[loop] = __raw_readl(s->addr_cena + offset ++ + loop * 4); ++#ifdef QBMAN_CENA_TRACE ++ hexdump(shadow, 64); ++#endif ++ return shadow; ++} ++ ++static inline void *qbman_cena_read_wo_shadow(struct qbman_swp_sys *s, ++ uint32_t offset) ++{ ++#ifdef QBMAN_CENA_TRACE ++ pr_info("qbman_cena_read(%p:%d:0x%03x) %p\n", ++ s->addr_cena, s->idx, offset, shadow); ++#endif ++ ++#ifdef QBMAN_CENA_TRACE ++ hexdump(shadow, 64); ++#endif ++ return s->addr_cena + offset; ++} ++ ++static inline void qbman_cena_invalidate(struct qbman_swp_sys *s, ++ uint32_t offset) ++{ ++ dccivac(s->addr_cena + offset); ++} ++ ++static inline void qbman_cena_invalidate_prefetch(struct qbman_swp_sys *s, ++ uint32_t offset) ++{ ++ dccivac(s->addr_cena + offset); ++ prefetch_for_load(s->addr_cena + offset); ++} ++ ++static inline void qbman_cena_prefetch(struct qbman_swp_sys *s, ++ uint32_t offset) ++{ ++ prefetch_for_load(s->addr_cena + offset); ++} ++ ++ /******************/ ++ /* Portal support */ ++ /******************/ ++ ++/* The SWP_CFG portal register is special, in that it is used by the ++ * platform-specific code rather than the platform-independent code in ++ * qbman_portal.c. So use of it is declared locally here. */ ++#define QBMAN_CINH_SWP_CFG 0xd00 ++ ++/* For MC portal use, we always configure with ++ * DQRR_MF is (SWP_CFG,20,3) - DQRR max fill (<- 0x4) ++ * EST is (SWP_CFG,16,3) - EQCR_CI stashing threshold (<- 0x2) ++ * RPM is (SWP_CFG,12,2) - RCR production notification mode (<- 0x3) ++ * DCM is (SWP_CFG,10,2) - DQRR consumption notification mode (<- 0x2) ++ * EPM is (SWP_CFG,8,2) - EQCR production notification mode (<- 0x2) ++ * SD is (SWP_CFG,5,1) - memory stashing drop enable (<- TRUE) ++ * SP is (SWP_CFG,4,1) - memory stashing priority (<- TRUE) ++ * SE is (SWP_CFG,3,1) - memory stashing enable (<- TRUE) ++ * DP is (SWP_CFG,2,1) - dequeue stashing priority (<- TRUE) ++ * DE is (SWP_CFG,1,1) - dequeue stashing enable (<- TRUE) ++ * EP is (SWP_CFG,0,1) - EQCR_CI stashing priority (<- TRUE) ++ */ ++static inline uint32_t qbman_set_swp_cfg(uint8_t max_fill, uint8_t wn, ++ uint8_t est, uint8_t rpm, uint8_t dcm, ++ uint8_t epm, int sd, int sp, int se, ++ int dp, int de, int ep) ++{ ++ uint32_t reg; ++ reg = e32_uint8_t(20, (uint32_t)(3 + (max_fill >> 3)), max_fill) | ++ e32_uint8_t(16, 3, est) | ++ e32_uint8_t(12, 2, rpm) | e32_uint8_t(10, 2, dcm) | ++ e32_uint8_t(8, 2, epm) | e32_int(5, 1, sd) | ++ e32_int(4, 1, sp) | e32_int(3, 1, se) | e32_int(2, 1, dp) | ++ e32_int(1, 1, de) | e32_int(0, 1, ep) | e32_uint8_t(14, 1, wn); ++ return reg; ++} ++ ++static inline int qbman_swp_sys_init(struct qbman_swp_sys *s, ++ const struct qbman_swp_desc *d, ++ uint8_t dqrr_size) ++{ ++ uint32_t reg; ++ s->addr_cena = d->cena_bar; ++ s->addr_cinh = d->cinh_bar; ++ s->idx = (uint32_t)d->idx; ++ s->cena = (void *)get_zeroed_page(GFP_KERNEL); ++ if (!s->cena) { ++ pr_err("Could not allocate page for cena shadow\n"); ++ return -1; ++ } ++ s->eqcr_mode = d->eqcr_mode; ++ BUG_ON(d->idx < 0); ++#ifdef QBMAN_CHECKING ++ /* We should never be asked to initialise for a portal that isn't in ++ * the power-on state. (Ie. don't forget to reset portals when they are ++ * decommissioned!) ++ */ ++ reg = qbman_cinh_read(s, QBMAN_CINH_SWP_CFG); ++ BUG_ON(reg); ++#endif ++ if (s->eqcr_mode == qman_eqcr_vb_array) ++ reg = qbman_set_swp_cfg(dqrr_size, 0, 0, 3, 2, 3, 1, 1, 1, 1, ++ 1, 1); ++ else ++ reg = qbman_set_swp_cfg(dqrr_size, 0, 2, 3, 2, 2, 1, 1, 1, 1, ++ 1, 1); ++ qbman_cinh_write(s, QBMAN_CINH_SWP_CFG, reg); ++ reg = qbman_cinh_read(s, QBMAN_CINH_SWP_CFG); ++ if (!reg) { ++ pr_err("The portal %d is not enabled!\n", s->idx); ++ kfree(s->cena); ++ return -1; ++ } ++ return 0; ++} ++ ++static inline void qbman_swp_sys_finish(struct qbman_swp_sys *s) ++{ ++ free_page((unsigned long)s->cena); ++} ++ ++static inline void *qbman_cena_write_start_wo_shadow_fast(struct qbman_swp_sys *s, ++ uint32_t offset) ++{ ++ #ifdef QBMAN_CENA_TRACE ++ pr_info("qbman_cena_write_start(%p:%d:0x%03x)\n", ++ s->addr_cena, s->idx, offset); ++ #endif ++ BUG_ON(offset & 63); ++ return (s->addr_cena + offset); ++} +diff --git a/drivers/net/dpaa2/qbman/driver/qbman_sys_decl.h b/drivers/net/dpaa2/qbman/driver/qbman_sys_decl.h +new file mode 100644 +index 0000000..ae7ef97 +--- /dev/null ++++ b/drivers/net/dpaa2/qbman/driver/qbman_sys_decl.h +@@ -0,0 +1,68 @@ ++/* Copyright (C) 2014 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY ++ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++ ++/* Sanity check */ ++#if (__BYTE_ORDER__ != __ORDER_BIG_ENDIAN__) && \ ++ (__BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__) ++#error "Unknown endianness!" ++#endif ++ ++/* The platform-independent code shouldn't need endianness, except for ++ * weird/fast-path cases like qbman_result_has_token(), which needs to ++ * perform a passive and endianness-specific test on a read-only data structure ++ * very quickly. It's an exception, and this symbol is used for that case. */ ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ++#define DQRR_TOK_OFFSET 0 ++#define QBMAN_RESULT_VERB_OFFSET_IN_MEM 24 ++#define SCN_STATE_OFFSET_IN_MEM 8 ++#define SCN_RID_OFFSET_IN_MEM 8 ++#else ++#define DQRR_TOK_OFFSET 24 ++#define QBMAN_RESULT_VERB_OFFSET_IN_MEM 0 ++#define SCN_STATE_OFFSET_IN_MEM 16 ++#define SCN_RID_OFFSET_IN_MEM 0 ++#endif ++ ++/* Similarly-named functions */ ++#define upper32(a) upper_32_bits(a) ++#define lower32(a) lower_32_bits(a) ++ ++ /****************/ ++ /* arch assists */ ++ /****************/ ++#define dcbz(p) { asm volatile("dc zva, %0" : : "r" (p) : "memory"); } ++#define lwsync() { asm volatile("dmb st" : : : "memory"); } ++#define dcbf(p) { asm volatile("dc cvac, %0" : : "r"(p) : "memory"); } ++#define dccivac(p) { asm volatile("dc civac, %0" : : "r"(p) : "memory"); } ++static inline void prefetch_for_load(void *p) ++{ ++ asm volatile("prfm pldl1keep, [%0, #64]" : : "r" (p)); ++} ++static inline void prefetch_for_store(void *p) ++{ ++ asm volatile("prfm pstl1keep, [%0, #64]" : : "r" (p)); ++} +diff --git a/drivers/net/dpaa2/qbman/include/compat.h b/drivers/net/dpaa2/qbman/include/compat.h +new file mode 100644 +index 0000000..0d14b58 +--- /dev/null ++++ b/drivers/net/dpaa2/qbman/include/compat.h +@@ -0,0 +1,597 @@ ++/* Copyright (c) 2008-2011 Freescale Semiconductor, Inc. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY ++ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#ifndef HEADER_COMPAT_H ++#define HEADER_COMPAT_H ++ ++#include ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE ++#endif ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* The following definitions are primarily to allow the single-source driver ++ * interfaces to be included by arbitrary program code. Ie. for interfaces that ++ * are also available in kernel-space, these definitions provide compatibility ++ * with certain attributes and types used in those interfaces. */ ++ ++/* Required compiler attributes */ ++#define __maybe_unused __attribute__((unused)) ++#define __always_unused __attribute__((unused)) ++#define __packed __attribute__((__packed__)) ++#define __user ++#define likely(x) __builtin_expect(!!(x), 1) ++#define unlikely(x) __builtin_expect(!!(x), 0) ++#define ____cacheline_aligned __attribute__((aligned(L1_CACHE_BYTES))) ++#define container_of(p, t, f) (t *)((void *)p - offsetof(t, f)) ++#define __stringify_1(x) #x ++#define __stringify(x) __stringify_1(x) ++#define panic(x) \ ++do { \ ++ printf("panic: %s", x); \ ++ abort(); \ ++} while (0) ++ ++#ifdef ARRAY_SIZE ++#undef ARRAY_SIZE ++#endif ++#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) ++ ++/* Required types */ ++typedef uint8_t u8; ++typedef uint16_t u16; ++typedef uint32_t u32; ++typedef uint64_t u64; ++typedef uint64_t dma_addr_t; ++typedef cpu_set_t cpumask_t; ++#define spinlock_t pthread_mutex_t ++typedef u32 compat_uptr_t; ++static inline void __user *compat_ptr(compat_uptr_t uptr) ++{ ++ return (void __user *)(unsigned long)uptr; ++} ++ ++static inline compat_uptr_t ptr_to_compat(void __user *uptr) ++{ ++ return (u32)(unsigned long)uptr; ++} ++ ++/* I/O operations */ ++static inline u32 in_be32(volatile void *__p) ++{ ++ volatile u32 *p = __p; ++ return *p; ++} ++static inline void out_be32(volatile void *__p, u32 val) ++{ ++ volatile u32 *p = __p; ++ *p = val; ++} ++ ++/* Debugging */ ++#define prflush(fmt, args...) \ ++ do { \ ++ printf(fmt, ##args); \ ++ fflush(stdout); \ ++ } while (0) ++#define pr_crit(fmt, args...) prflush("CRIT:" fmt, ##args) ++#define pr_err(fmt, args...) prflush("ERR:" fmt, ##args) ++#define pr_warning(fmt, args...) prflush("WARN:" fmt, ##args) ++#define pr_info(fmt, args...) prflush(fmt, ##args) ++ ++#define BUG() abort() ++#ifdef CONFIG_BUGON ++#ifdef pr_debug ++#undef pr_debug ++#endif ++#define pr_debug(fmt, args...) printf(fmt, ##args) ++#define BUG_ON(c) \ ++do { \ ++ if (c) { \ ++ pr_crit("BUG: %s:%d\n", __FILE__, __LINE__); \ ++ abort(); \ ++ } \ ++} while(0) ++#define might_sleep_if(c) BUG_ON(c) ++#define msleep(x) \ ++do { \ ++ pr_crit("BUG: illegal call %s:%d\n", __FILE__, __LINE__); \ ++ exit(EXIT_FAILURE); \ ++} while(0) ++#else ++#ifdef pr_debug ++#undef pr_debug ++#endif ++#define pr_debug(fmt, args...) do { ; } while(0) ++#define BUG_ON(c) do { ; } while(0) ++#define might_sleep_if(c) do { ; } while(0) ++#define msleep(x) do { ; } while(0) ++#endif ++#define WARN_ON(c, str) \ ++do { \ ++ static int warned_##__LINE__; \ ++ if ((c) && !warned_##__LINE__) { \ ++ pr_warning("%s\n", str); \ ++ pr_warning("(%s:%d)\n", __FILE__, __LINE__); \ ++ warned_##__LINE__ = 1; \ ++ } \ ++} while (0) ++ ++#define ALIGN(x, a) (((x) + ((typeof(x))(a) - 1)) & ~((typeof(x))(a) - 1)) ++ ++/****************/ ++/* Linked-lists */ ++/****************/ ++ ++struct list_head { ++ struct list_head *prev; ++ struct list_head *next; ++}; ++ ++#define LIST_HEAD(n) \ ++struct list_head n = { \ ++ .prev = &n, \ ++ .next = &n \ ++} ++#define INIT_LIST_HEAD(p) \ ++do { \ ++ struct list_head *__p298 = (p); \ ++ __p298->prev = __p298->next =__p298; \ ++} while(0) ++#define list_entry(node, type, member) \ ++ (type *)((void *)node - offsetof(type, member)) ++#define list_empty(p) \ ++({ \ ++ const struct list_head *__p298 = (p); \ ++ ((__p298->next == __p298) && (__p298->prev == __p298)); \ ++}) ++#define list_add(p,l) \ ++do { \ ++ struct list_head *__p298 = (p); \ ++ struct list_head *__l298 = (l); \ ++ __p298->next = __l298->next; \ ++ __p298->prev = __l298; \ ++ __l298->next->prev = __p298; \ ++ __l298->next = __p298; \ ++} while(0) ++#define list_add_tail(p,l) \ ++do { \ ++ struct list_head *__p298 = (p); \ ++ struct list_head *__l298 = (l); \ ++ __p298->prev = __l298->prev; \ ++ __p298->next = __l298; \ ++ __l298->prev->next = __p298; \ ++ __l298->prev = __p298; \ ++} while(0) ++#define list_for_each(i, l) \ ++ for (i = (l)->next; i != (l); i = i->next) ++#define list_for_each_safe(i, j, l) \ ++ for (i = (l)->next, j = i->next; i != (l); \ ++ i = j, j = i->next) ++#define list_for_each_entry(i, l, name) \ ++ for (i = list_entry((l)->next, typeof(*i), name); &i->name != (l); \ ++ i = list_entry(i->name.next, typeof(*i), name)) ++#define list_for_each_entry_safe(i, j, l, name) \ ++ for (i = list_entry((l)->next, typeof(*i), name), \ ++ j = list_entry(i->name.next, typeof(*j), name); \ ++ &i->name != (l); \ ++ i = j, j = list_entry(j->name.next, typeof(*j), name)) ++#define list_del(i) \ ++do { \ ++ (i)->next->prev = (i)->prev; \ ++ (i)->prev->next = (i)->next; \ ++} while(0) ++ ++/* Other miscellaneous interfaces our APIs depend on; */ ++ ++#define lower_32_bits(x) ((u32)(x)) ++#define upper_32_bits(x) ((u32)(((x) >> 16) >> 16)) ++ ++/* Compiler/type stuff */ ++typedef unsigned int gfp_t; ++typedef uint32_t phandle; ++ ++#define noinline __attribute__((noinline)) ++#define __iomem ++#define EINTR 4 ++#define ENODEV 19 ++#define MODULE_AUTHOR(s) ++#define MODULE_LICENSE(s) ++#define MODULE_DESCRIPTION(s) ++#define MODULE_PARM_DESC(x, y) ++#define EXPORT_SYMBOL(x) ++#define module_init(fn) int m_##fn(void) { return fn(); } ++#define module_exit(fn) void m_##fn(void) { fn(); } ++#define module_param(x, y, z) ++#define module_param_string(w, x, y, z) ++#define GFP_KERNEL 0 ++#define __KERNEL__ ++#define __init ++#define __raw_readb(p) *(const volatile unsigned char *)(p) ++#define __raw_readl(p) *(const volatile unsigned int *)(p) ++#define __raw_writel(v, p) \ ++do { \ ++ *(volatile unsigned int *)(p) = (v); \ ++} while (0) ++ ++/* printk() stuff */ ++#define printk(fmt, args...) do_not_use_printk ++#define nada(fmt, args...) do { ; } while(0) ++ ++/* Interrupt stuff */ ++typedef uint32_t irqreturn_t; ++#define IRQ_HANDLED 0 ++ ++/* memcpy() stuff - when you know alignments in advance */ ++#ifdef CONFIG_TRY_BETTER_MEMCPY ++static inline void copy_words(void *dest, const void *src, size_t sz) ++{ ++ u32 *__dest = dest; ++ const u32 *__src = src; ++ size_t __sz = sz >> 2; ++ BUG_ON((unsigned long)dest & 0x3); ++ BUG_ON((unsigned long)src & 0x3); ++ BUG_ON(sz & 0x3); ++ while (__sz--) ++ *(__dest++) = *(__src++); ++} ++static inline void copy_shorts(void *dest, const void *src, size_t sz) ++{ ++ u16 *__dest = dest; ++ const u16 *__src = src; ++ size_t __sz = sz >> 1; ++ BUG_ON((unsigned long)dest & 0x1); ++ BUG_ON((unsigned long)src & 0x1); ++ BUG_ON(sz & 0x1); ++ while (__sz--) ++ *(__dest++) = *(__src++); ++} ++static inline void copy_bytes(void *dest, const void *src, size_t sz) ++{ ++ u8 *__dest = dest; ++ const u8 *__src = src; ++ while (sz--) ++ *(__dest++) = *(__src++); ++} ++#else ++#define copy_words memcpy ++#define copy_shorts memcpy ++#define copy_bytes memcpy ++#endif ++ ++/* Spinlock stuff */ ++#define spinlock_t pthread_mutex_t ++#define __SPIN_LOCK_UNLOCKED(x) PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP ++#define DEFINE_SPINLOCK(x) spinlock_t x = __SPIN_LOCK_UNLOCKED(x) ++#define spin_lock_init(x) \ ++ do { \ ++ __maybe_unused int __foo; \ ++ pthread_mutexattr_t __foo_attr; \ ++ __foo = pthread_mutexattr_init(&__foo_attr); \ ++ BUG_ON(__foo); \ ++ __foo = pthread_mutexattr_settype(&__foo_attr, \ ++ PTHREAD_MUTEX_ADAPTIVE_NP); \ ++ BUG_ON(__foo); \ ++ __foo = pthread_mutex_init(x, &__foo_attr); \ ++ BUG_ON(__foo); \ ++ } while (0) ++#define spin_lock(x) \ ++ do { \ ++ __maybe_unused int __foo = pthread_mutex_lock(x); \ ++ BUG_ON(__foo); \ ++ } while (0) ++#define spin_unlock(x) \ ++ do { \ ++ __maybe_unused int __foo = pthread_mutex_unlock(x); \ ++ BUG_ON(__foo); \ ++ } while (0) ++#define spin_lock_irq(x) do { \ ++ local_irq_disable(); \ ++ spin_lock(x); \ ++ } while (0) ++#define spin_unlock_irq(x) do { \ ++ spin_unlock(x); \ ++ local_irq_enable(); \ ++ } while (0) ++#define spin_lock_irqsave(x, f) do { spin_lock_irq(x); } while (0) ++#define spin_unlock_irqrestore(x, f) do { spin_unlock_irq(x); } while (0) ++ ++#define raw_spinlock_t spinlock_t ++#define raw_spin_lock_init(x) spin_lock_init(x) ++#define raw_spin_lock_irqsave(x, f) spin_lock(x) ++#define raw_spin_unlock_irqrestore(x, f) spin_unlock(x) ++ ++/* Completion stuff */ ++#define DECLARE_COMPLETION(n) int n = 0; ++#define complete(n) \ ++do { \ ++ *n = 1; \ ++} while(0) ++#define wait_for_completion(n) \ ++do { \ ++ while (!*n) { \ ++ bman_poll(); \ ++ qman_poll(); \ ++ } \ ++ *n = 0; \ ++} while(0) ++ ++/* Platform device stuff */ ++struct platform_device { void *dev; }; ++static inline struct ++platform_device *platform_device_alloc(const char *name __always_unused, ++ int id __always_unused) ++{ ++ struct platform_device *ret = malloc(sizeof(*ret)); ++ if (ret) ++ ret->dev = NULL; ++ return ret; ++} ++#define platform_device_add(pdev) 0 ++#define platform_device_del(pdev) do { ; } while(0) ++static inline void platform_device_put(struct platform_device *pdev) ++{ ++ free(pdev); ++} ++struct resource { ++ int unused; ++}; ++ ++/* Allocator stuff */ ++#define kmalloc(sz, t) malloc(sz) ++#define vmalloc(sz) malloc(sz) ++#define kfree(p) do { if (p) free(p); } while (0) ++static inline void *kzalloc(size_t sz, gfp_t __foo __always_unused) ++{ ++ void *ptr = malloc(sz); ++ if (ptr) ++ memset(ptr, 0, sz); ++ return ptr; ++} ++static inline unsigned long get_zeroed_page(gfp_t __foo __always_unused) ++{ ++ void *p; ++ if (posix_memalign(&p, 4096, 4096)) ++ return 0; ++ memset(p, 0, 4096); ++ return (unsigned long)p; ++} ++static inline void free_page(unsigned long p) ++{ ++ free((void *)p); ++} ++struct kmem_cache { ++ size_t sz; ++ size_t align; ++}; ++#define SLAB_HWCACHE_ALIGN 0 ++static inline struct kmem_cache *kmem_cache_create(const char *n __always_unused, ++ size_t sz, size_t align, unsigned long flags __always_unused, ++ void (*c)(void *) __always_unused) ++{ ++ struct kmem_cache *ret = malloc(sizeof(*ret)); ++ if (ret) { ++ ret->sz = sz; ++ ret->align = align; ++ } ++ return ret; ++} ++static inline void kmem_cache_destroy(struct kmem_cache *c) ++{ ++ free(c); ++} ++static inline void *kmem_cache_alloc(struct kmem_cache *c, gfp_t f __always_unused) ++{ ++ void *p; ++ if (posix_memalign(&p, c->align, c->sz)) ++ return NULL; ++ return p; ++} ++static inline void kmem_cache_free(struct kmem_cache *c __always_unused, void *p) ++{ ++ free(p); ++} ++static inline void *kmem_cache_zalloc(struct kmem_cache *c, gfp_t f) ++{ ++ void *ret = kmem_cache_alloc(c, f); ++ if (ret) ++ memset(ret, 0, c->sz); ++ return ret; ++} ++ ++/* Bitfield stuff. */ ++#define BITS_PER_ULONG (sizeof(unsigned long) << 3) ++#define SHIFT_PER_ULONG (((1 << 5) == BITS_PER_ULONG) ? 5 : 6) ++#define BITS_MASK(idx) ((unsigned long)1 << ((idx) & (BITS_PER_ULONG - 1))) ++#define BITS_IDX(idx) ((idx) >> SHIFT_PER_ULONG) ++static inline unsigned long test_bits(unsigned long mask, ++ volatile unsigned long *p) ++{ ++ return *p & mask; ++} ++static inline int test_bit(int idx, volatile unsigned long *bits) ++{ ++ return test_bits(BITS_MASK(idx), bits + BITS_IDX(idx)); ++} ++static inline void set_bits(unsigned long mask, volatile unsigned long *p) ++{ ++ *p |= mask; ++} ++static inline void set_bit(int idx, volatile unsigned long *bits) ++{ ++ set_bits(BITS_MASK(idx), bits + BITS_IDX(idx)); ++} ++static inline void clear_bits(unsigned long mask, volatile unsigned long *p) ++{ ++ *p &= ~mask; ++} ++static inline void clear_bit(int idx, volatile unsigned long *bits) ++{ ++ clear_bits(BITS_MASK(idx), bits + BITS_IDX(idx)); ++} ++static inline unsigned long test_and_set_bits(unsigned long mask, ++ volatile unsigned long *p) ++{ ++ unsigned long ret = test_bits(mask, p); ++ set_bits(mask, p); ++ return ret; ++} ++static inline int test_and_set_bit(int idx, volatile unsigned long *bits) ++{ ++ int ret = test_bit(idx, bits); ++ set_bit(idx, bits); ++ return ret; ++} ++static inline int test_and_clear_bit(int idx, volatile unsigned long *bits) ++{ ++ int ret = test_bit(idx, bits); ++ clear_bit(idx, bits); ++ return ret; ++} ++static inline int find_next_zero_bit(unsigned long *bits, int limit, int idx) ++{ ++ while ((++idx < limit) && test_bit(idx, bits)) ++ ; ++ return idx; ++} ++static inline int find_first_zero_bit(unsigned long *bits, int limit) ++{ ++ int idx = 0; ++ while (test_bit(idx, bits) && (++idx < limit)) ++ ; ++ return idx; ++} ++ ++static inline u64 div64_u64(u64 n, u64 d) ++{ ++ return n / d; ++} ++ ++#define dmb(opt) { asm volatile("dmb " #opt : : : "memory"); } ++#define smp_mb() dmb(ish) ++ ++/* Atomic stuff */ ++typedef struct { ++ int counter; ++} atomic_t; ++ ++#define atomic_read(v) (*(volatile int *)&(v)->counter) ++#define atomic_set(v, i) (((v)->counter) = (i)) ++static inline void atomic_add(int i, atomic_t *v) ++{ ++ unsigned long tmp; ++ int result; ++ ++ asm volatile("// atomic_add\n" ++ "1: ldxr %w0, %2\n" ++ " add %w0, %w0, %w3\n" ++ " stxr %w1, %w0, %2\n" ++ " cbnz %w1, 1b" ++ : "=&r" (result), "=&r" (tmp), "+Q" (v->counter) ++ : "Ir" (i)); ++} ++ ++static inline int atomic_add_return(int i, atomic_t *v) ++{ ++ unsigned long tmp; ++ int result; ++ ++ asm volatile("// atomic_add_return\n" ++ "1: ldxr %w0, %2\n" ++ " add %w0, %w0, %w3\n" ++ " stlxr %w1, %w0, %2\n" ++ " cbnz %w1, 1b" ++ : "=&r" (result), "=&r" (tmp), "+Q" (v->counter) ++ : "Ir" (i) ++ : "memory"); ++ ++ smp_mb(); ++ return result; ++} ++ ++static inline void atomic_sub(int i, atomic_t *v) ++{ ++ unsigned long tmp; ++ int result; ++ ++ asm volatile("// atomic_sub\n" ++ "1: ldxr %w0, %2\n" ++ " sub %w0, %w0, %w3\n" ++ " stxr %w1, %w0, %2\n" ++ " cbnz %w1, 1b" ++ : "=&r" (result), "=&r" (tmp), "+Q" (v->counter) ++ : "Ir" (i)); ++} ++ ++static inline int atomic_sub_return(int i, atomic_t *v) ++{ ++ unsigned long tmp; ++ int result; ++ ++ asm volatile("// atomic_sub_return\n" ++ "1: ldxr %w0, %2\n" ++ " sub %w0, %w0, %w3\n" ++ " stlxr %w1, %w0, %2\n" ++ " cbnz %w1, 1b" ++ : "=&r" (result), "=&r" (tmp), "+Q" (v->counter) ++ : "Ir" (i) ++ : "memory"); ++ ++ smp_mb(); ++ return result; ++} ++ ++#define atomic_inc(v) atomic_add(1, v) ++#define atomic_dec(v) atomic_sub(1, v) ++ ++#define atomic_inc_and_test(v) (atomic_add_return(1, v) == 0) ++#define atomic_dec_and_test(v) (atomic_sub_return(1, v) == 0) ++#define atomic_inc_return(v) (atomic_add_return(1, v)) ++#define atomic_dec_return(v) (atomic_sub_return(1, v)) ++#define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0) ++ ++#endif /* HEADER_COMPAT_H */ +diff --git a/drivers/net/dpaa2/qbman/include/drivers/fsl_qbman_base.h b/drivers/net/dpaa2/qbman/include/drivers/fsl_qbman_base.h +new file mode 100644 +index 0000000..4cb784c +--- /dev/null ++++ b/drivers/net/dpaa2/qbman/include/drivers/fsl_qbman_base.h +@@ -0,0 +1,151 @@ ++/* Copyright (C) 2014 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY ++ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_QBMAN_BASE_H ++#define _FSL_QBMAN_BASE_H ++ ++/** ++ * DOC: QBMan basic structures ++ * ++ * The QBMan block descriptor, software portal descriptor and Frame descriptor ++ * are defined here. ++ * ++ */ ++ ++/** ++ * struct qbman_block_desc - qbman block descriptor structure ++ * @ccsr_reg_bar: CCSR register map. ++ * @irq_rerr: Recoverable error interrupt line. ++ * @irq_nrerr: Non-recoverable error interrupt line ++ * ++ * Descriptor for a QBMan instance on the SoC. On partitions/targets that do not ++ * control this QBMan instance, these values may simply be place-holders. The ++ * idea is simply that we be able to distinguish between them, eg. so that SWP ++ * descriptors can identify which QBMan instance they belong to. ++ */ ++struct qbman_block_desc { ++ void *ccsr_reg_bar; ++ int irq_rerr; ++ int irq_nrerr; ++}; ++ ++enum qbman_eqcr_mode { ++ qman_eqcr_vb_ring = 2, /* Valid bit, with eqcr in ring mode */ ++ qman_eqcr_vb_array, /* Valid bit, with eqcr in array mode */ ++}; ++ ++/** ++ * struct qbman_swp_desc - qbman software portal descriptor structure ++ * @block: The QBMan instance. ++ * @cena_bar: Cache-enabled portal register map. ++ * @cinh_bar: Cache-inhibited portal register map. ++ * @irq: -1 if unused (or unassigned) ++ * @idx: SWPs within a QBMan are indexed. -1 if opaque to the user. ++ * @qman_version: the qman version. ++ * @eqcr_mode: Select the eqcr mode, currently only valid bit ring mode and ++ * valid bit array mode are supported. ++ * ++ * Descriptor for a QBMan software portal, expressed in terms that make sense to ++ * the user context. Ie. on MC, this information is likely to be true-physical, ++ * and instantiated statically at compile-time. On GPP, this information is ++ * likely to be obtained via "discovery" over a partition's "MC bus" ++ * (ie. in response to a MC portal command), and would take into account any ++ * virtualisation of the GPP user's address space and/or interrupt numbering. ++ */ ++struct qbman_swp_desc { ++ const struct qbman_block_desc *block; ++ uint8_t *cena_bar; ++ uint8_t *cinh_bar; ++ int irq; ++ int idx; ++ uint32_t qman_version; ++ enum qbman_eqcr_mode eqcr_mode; ++}; ++ ++/* Driver object for managing a QBMan portal */ ++struct qbman_swp; ++ ++/** ++ * struct qbman_fd - basci structure for qbman frame descriptor ++ * @words: for easier/faster copying the whole FD structure. ++ * @addr_lo: the lower 32 bits of the address in FD. ++ * @addr_hi: the upper 32 bits of the address in FD. ++ * @len: the length field in FD. ++ * @bpid_offset: represent the bpid and offset fields in FD. offset in ++ * the MS 16 bits, BPID in the LS 16 bits. ++ * @frc: frame context ++ * @ctrl: the 32bit control bits including dd, sc,... va, err. ++ * @flc_lo: the lower 32bit of flow context. ++ * @flc_hi: the upper 32bits of flow context. ++ * ++ * Place-holder for FDs, we represent it via the simplest form that we need for ++ * now. Different overlays may be needed to support different options, etc. (It ++ * is impractical to define One True Struct, because the resulting encoding ++ * routines (lots of read-modify-writes) would be worst-case performance whether ++ * or not circumstances required them.) ++ * ++ * Note, as with all data-structures exchanged between software and hardware (be ++ * they located in the portal register map or DMA'd to and from main-memory), ++ * the driver ensures that the caller of the driver API sees the data-structures ++ * in host-endianness. "struct qbman_fd" is no exception. The 32-bit words ++ * contained within this structure are represented in host-endianness, even if ++ * hardware always treats them as little-endian. As such, if any of these fields ++ * are interpreted in a binary (rather than numerical) fashion by hardware ++ * blocks (eg. accelerators), then the user should be careful. We illustrate ++ * with an example; ++ * ++ * Suppose the desired behaviour of an accelerator is controlled by the "frc" ++ * field of the FDs that are sent to it. Suppose also that the behaviour desired ++ * by the user corresponds to an "frc" value which is expressed as the literal ++ * sequence of bytes 0xfe, 0xed, 0xab, and 0xba. So "frc" should be the 32-bit ++ * value in which 0xfe is the first byte and 0xba is the last byte, and as ++ * hardware is little-endian, this amounts to a 32-bit "value" of 0xbaabedfe. If ++ * the software is little-endian also, this can simply be achieved by setting ++ * frc=0xbaabedfe. On the other hand, if software is big-endian, it should set ++ * frc=0xfeedabba! The best away of avoiding trouble with this sort of thing is ++ * to treat the 32-bit words as numerical values, in which the offset of a field ++ * from the beginning of the first byte (as required or generated by hardware) ++ * is numerically encoded by a left-shift (ie. by raising the field to a ++ * corresponding power of 2). Ie. in the current example, software could set ++ * "frc" in the following way, and it would work correctly on both little-endian ++ * and big-endian operation; ++ * fd.frc = (0xfe << 0) | (0xed << 8) | (0xab << 16) | (0xba << 24); ++ */ ++struct qbman_fd { ++ union { ++ uint32_t words[8]; ++ struct qbman_fd_simple { ++ uint32_t addr_lo; ++ uint32_t addr_hi; ++ uint32_t len; ++ uint32_t bpid_offset; ++ uint32_t frc; ++ uint32_t ctrl; ++ uint32_t flc_lo; ++ uint32_t flc_hi; ++ } simple; ++ }; ++}; ++ ++#endif /* !_FSL_QBMAN_BASE_H */ +diff --git a/drivers/net/dpaa2/qbman/include/drivers/fsl_qbman_portal.h b/drivers/net/dpaa2/qbman/include/drivers/fsl_qbman_portal.h +new file mode 100644 +index 0000000..ddcabcf +--- /dev/null ++++ b/drivers/net/dpaa2/qbman/include/drivers/fsl_qbman_portal.h +@@ -0,0 +1,1089 @@ ++/* Copyright (C) 2014 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY ++ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_QBMAN_PORTAL_H ++#define _FSL_QBMAN_PORTAL_H ++ ++#include ++ ++/** ++ * DOC - QBMan portal APIs to implement the following functions: ++ * - Initialize and destroy Software portal object. ++ * - Read and write Software portal interrupt registers. ++ * - Enqueue, including setting the enqueue descriptor, and issuing enqueue ++ * command etc. ++ * - Dequeue, including setting the dequeue descriptor, issuing dequeue command, ++ * parsing the dequeue response in DQRR and memeory, parsing the state change ++ * notifications etc. ++ * - Release, including setting the release descriptor, and issuing the buffer ++ * release command. ++ * - Acquire, acquire the buffer from the given buffer pool. ++ * - FQ management. ++ * - Channel management, enable/disable CDAN with or without context. ++ */ ++ ++/** ++ * qbman_swp_init() - Create a functional object representing the given ++ * QBMan portal descriptor. ++ * @d: the given qbman swp descriptor ++ * ++ * Return qbman_swp portal object for success, NULL if the object cannot ++ * be created. ++ */ ++struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d); ++ ++/** ++ * qbman_swp_finish() - Create and destroy a functional object representing ++ * the given QBMan portal descriptor. ++ * @p: the qbman_swp object to be destroyed. ++ * ++ */ ++void qbman_swp_finish(struct qbman_swp *p); ++ ++/** ++ * qbman_swp_get_desc() - Get the descriptor of the given portal object. ++ * @p: the given portal object. ++ * ++ * Return the descriptor for this portal. ++ */ ++const struct qbman_swp_desc *qbman_swp_get_desc(struct qbman_swp *); ++ ++ /**************/ ++ /* Interrupts */ ++ /**************/ ++ ++/* EQCR ring interrupt */ ++#define QBMAN_SWP_INTERRUPT_EQRI ((uint32_t)0x00000001) ++/* Enqueue command dispatched interrupt */ ++#define QBMAN_SWP_INTERRUPT_EQDI ((uint32_t)0x00000002) ++/* DQRR non-empty interrupt */ ++#define QBMAN_SWP_INTERRUPT_DQRI ((uint32_t)0x00000004) ++/* RCR ring interrupt */ ++#define QBMAN_SWP_INTERRUPT_RCRI ((uint32_t)0x00000008) ++/* Release command dispatched interrupt */ ++#define QBMAN_SWP_INTERRUPT_RCDI ((uint32_t)0x00000010) ++/* Volatile dequeue command interrupt */ ++#define QBMAN_SWP_INTERRUPT_VDCI ((uint32_t)0x00000020) ++ ++/** ++ * qbman_swp_interrupt_get_vanish() - Get the data in software portal ++ * interrupt status disable register. ++ * @p: the given software portal object. ++ * ++ * Return the settings in SWP_ISDR register. ++ */ ++uint32_t qbman_swp_interrupt_get_vanish(struct qbman_swp *p); ++ ++/** ++ * qbman_swp_interrupt_set_vanish() - Set the data in software portal ++ * interrupt status disable register. ++ * @p: the given software portal object. ++ * @mask: The value to set in SWP_IDSR register. ++ */ ++void qbman_swp_interrupt_set_vanish(struct qbman_swp *p, uint32_t mask); ++ ++/** ++ * qbman_swp_interrupt_read_status() - Get the data in software portal ++ * interrupt status register. ++ * @p: the given software portal object. ++ * ++ * Return the settings in SWP_ISR register. ++ */ ++uint32_t qbman_swp_interrupt_read_status(struct qbman_swp *p); ++ ++/** ++ * qbman_swp_interrupt_clear_status() - Set the data in software portal ++ * interrupt status register. ++ * @p: the given software portal object. ++ * @mask: The value to set in SWP_ISR register. ++ */ ++void qbman_swp_interrupt_clear_status(struct qbman_swp *p, uint32_t mask); ++ ++/** ++ * qbman_swp_interrupt_get_trigger() - Get the data in software portal ++ * interrupt enable register. ++ * @p: the given software portal object. ++ * ++ * Return the settings in SWP_IER register. ++ */ ++uint32_t qbman_swp_interrupt_get_trigger(struct qbman_swp *p); ++ ++/** ++ * qbman_swp_interrupt_set_trigger() - Set the data in software portal ++ * interrupt enable register. ++ * @p: the given software portal object. ++ * @mask: The value to set in SWP_IER register. ++ */ ++void qbman_swp_interrupt_set_trigger(struct qbman_swp *p, uint32_t mask); ++ ++/** ++ * qbman_swp_interrupt_get_inhibit() - Get the data in software portal ++ * interrupt inhibit register. ++ * @p: the given software portal object. ++ * ++ * Return the settings in SWP_IIR register. ++ */ ++int qbman_swp_interrupt_get_inhibit(struct qbman_swp *p); ++ ++/** ++ * qbman_swp_interrupt_set_inhibit() - Set the data in software portal ++ * interrupt inhibit register. ++ * @p: the given software portal object. ++ * @mask: The value to set in SWP_IIR register. ++ */ ++void qbman_swp_interrupt_set_inhibit(struct qbman_swp *p, int inhibit); ++ ++ /************/ ++ /* Dequeues */ ++ /************/ ++ ++/** ++ * struct qbman_result - structure for qbman dequeue response and/or ++ * notification. ++ * @dont_manipulate_directly: the 16 32bit data to represent the whole ++ * possible qbman dequeue result. ++ */ ++struct qbman_result { ++ uint32_t dont_manipulate_directly[16]; ++}; ++ ++/* TODO: ++ *A DQRI interrupt can be generated when there are dequeue results on the ++ * portal's DQRR (this mechanism does not deal with "pull" dequeues to ++ * user-supplied 'storage' addresses). There are two parameters to this ++ * interrupt source, one is a threshold and the other is a timeout. The ++ * interrupt will fire if either the fill-level of the ring exceeds 'thresh', or ++ * if the ring has been non-empty for been longer than 'timeout' nanoseconds. ++ * For timeout, an approximation to the desired nanosecond-granularity value is ++ * made, so there are get and set APIs to allow the user to see what actual ++ * timeout is set (compared to the timeout that was requested). */ ++int qbman_swp_dequeue_thresh(struct qbman_swp *s, unsigned int thresh); ++int qbman_swp_dequeue_set_timeout(struct qbman_swp *s, unsigned int timeout); ++int qbman_swp_dequeue_get_timeout(struct qbman_swp *s, unsigned int *timeout); ++ ++ ++/* ------------------- */ ++/* Push-mode dequeuing */ ++/* ------------------- */ ++ ++/* The user of a portal can enable and disable push-mode dequeuing of up to 16 ++ * channels independently. It does not specify this toggling by channel IDs, but ++ * rather by specifing the index (from 0 to 15) that has been mapped to the ++ * desired channel. ++ */ ++ ++/** ++ * qbman_swp_push_get() - Get the push dequeue setup. ++ * @s: the software portal object. ++ * @channel_idx: the channel index to query. ++ * @enabled: returned boolean to show whether the push dequeue is enabled for ++ * the given channel. ++ */ ++void qbman_swp_push_get(struct qbman_swp *s, uint8_t channel_idx, int *enabled); ++ ++/** ++ * qbman_swp_push_set() - Enable or disable push dequeue. ++ * @s: the software portal object. ++ * @channel_idx: the channel index.. ++ * @enable: enable or disable push dequeue. ++ * ++ * The user of a portal can enable and disable push-mode dequeuing of up to 16 ++ * channels independently. It does not specify this toggling by channel IDs, but ++ * rather by specifying the index (from 0 to 15) that has been mapped to the ++ * desired channel. ++ */ ++void qbman_swp_push_set(struct qbman_swp *s, uint8_t channel_idx, int enable); ++ ++/* ------------------- */ ++/* Pull-mode dequeuing */ ++/* ------------------- */ ++ ++/** ++ * struct qbman_pull_desc - the structure for pull dequeue descriptor ++ * @dont_manipulate_directly: the 6 32bit data to represent the whole ++ * possible settings for pull dequeue descriptor. ++ */ ++struct qbman_pull_desc { ++ uint32_t dont_manipulate_directly[6]; ++}; ++ ++enum qbman_pull_type_e { ++ /* dequeue with priority precedence, respect intra-class scheduling */ ++ qbman_pull_type_prio = 1, ++ /* dequeue with active FQ precedence, respect ICS */ ++ qbman_pull_type_active, ++ /* dequeue with active FQ precedence, no ICS */ ++ qbman_pull_type_active_noics ++}; ++ ++/** ++ * qbman_pull_desc_clear() - Clear the contents of a descriptor to ++ * default/starting state. ++ * @d: the pull dequeue descriptor to be cleared. ++ */ ++void qbman_pull_desc_clear(struct qbman_pull_desc *d); ++ ++/** ++ * qbman_pull_desc_set_storage()- Set the pull dequeue storage ++ * @d: the pull dequeue descriptor to be set. ++ * @storage: the pointer of the memory to store the dequeue result. ++ * @storage_phys: the physical address of the storage memory. ++ * @stash: to indicate whether write allocate is enabled. ++ * ++ * If not called, or if called with 'storage' as NULL, the result pull dequeues ++ * will produce results to DQRR. If 'storage' is non-NULL, then results are ++ * produced to the given memory location (using the physical/DMA address which ++ * the caller provides in 'storage_phys'), and 'stash' controls whether or not ++ * those writes to main-memory express a cache-warming attribute. ++ */ ++void qbman_pull_desc_set_storage(struct qbman_pull_desc *d, ++ struct qbman_result *storage, ++ dma_addr_t storage_phys, ++ int stash); ++/** ++ * qbman_pull_desc_set_numframes() - Set the number of frames to be dequeued. ++ * @d: the pull dequeue descriptor to be set. ++ * @numframes: number of frames to be set, must be between 1 and 16, inclusive. ++ */ ++void qbman_pull_desc_set_numframes(struct qbman_pull_desc *d, ++ uint8_t numframes); ++/** ++ * qbman_pull_desc_set_token() - Set dequeue token for pull command ++ * @d: the dequeue descriptor ++ * @token: the token to be set ++ * ++ * token is the value that shows up in the dequeue response that can be used to ++ * detect when the results have been published. The easiest technique is to zero ++ * result "storage" before issuing a dequeue, and use any non-zero 'token' value ++ */ ++void qbman_pull_desc_set_token(struct qbman_pull_desc *d, uint8_t token); ++ ++/* Exactly one of the following descriptor "actions" should be set. (Calling any ++ * one of these will replace the effect of any prior call to one of these.) ++ * - pull dequeue from the given frame queue (FQ) ++ * - pull dequeue from any FQ in the given work queue (WQ) ++ * - pull dequeue from any FQ in any WQ in the given channel ++ */ ++/** ++ * qbman_pull_desc_set_fq() - Set fqid from which the dequeue command dequeues. ++ * @fqid: the frame queue index of the given FQ. ++ */ ++void qbman_pull_desc_set_fq(struct qbman_pull_desc *d, uint32_t fqid); ++ ++/** ++ * qbman_pull_desc_set_wq() - Set wqid from which the dequeue command dequeues. ++ * @wqid: composed of channel id and wqid within the channel. ++ * @dct: the dequeue command type. ++ */ ++void qbman_pull_desc_set_wq(struct qbman_pull_desc *d, uint32_t wqid, ++ enum qbman_pull_type_e dct); ++ ++/* qbman_pull_desc_set_channel() - Set channelid from which the dequeue command ++ * dequeues. ++ * @chid: the channel id to be dequeued. ++ * @dct: the dequeue command type. ++ */ ++void qbman_pull_desc_set_channel(struct qbman_pull_desc *d, uint32_t chid, ++ enum qbman_pull_type_e dct); ++ ++/** ++ * qbman_swp_pull() - Issue the pull dequeue command ++ * @s: the software portal object. ++ * @d: the software portal descriptor which has been configured with ++ * the set of qbman_pull_desc_set_*() calls. ++ * ++ * Return 0 for success, and -EBUSY if the software portal is not ready ++ * to do pull dequeue. ++ */ ++int qbman_swp_pull(struct qbman_swp *s, struct qbman_pull_desc *d); ++ ++/* -------------------------------- */ ++/* Polling DQRR for dequeue results */ ++/* -------------------------------- */ ++ ++/** ++ * qbman_swp_dqrr_next() - Get an valid DQRR entry. ++ * @s: the software portal object. ++ * ++ * Return NULL if there are no unconsumed DQRR entries. Return a DQRR entry ++ * only once, so repeated calls can return a sequence of DQRR entries, without ++ * requiring they be consumed immediately or in any particular order. ++ */ ++const struct qbman_result *qbman_swp_dqrr_next(struct qbman_swp *); ++ ++/** ++ * qbman_swp_dqrr_consume() - Consume DQRR entries previously returned from ++ * qbman_swp_dqrr_next(). ++ * @s: the software portal object. ++ * @dq: the DQRR entry to be consumed. ++ */ ++void qbman_swp_dqrr_consume(struct qbman_swp *s, const struct qbman_result *dq); ++ ++/** ++ * qbman_get_dqrr_idx() - Get dqrr index from the given dqrr ++ * @dqrr: the given dqrr object. ++ * ++ * Return dqrr index. ++ */ ++uint8_t qbman_get_dqrr_idx(struct qbman_result *dqrr); ++ ++/** ++ * qbman_get_dqrr_from_idx() - Use index to get the dqrr entry from the ++ * given portal ++ * @s: the given portal. ++ * @idx: the dqrr index. ++ * ++ * Return dqrr entry object. ++ */ ++struct qbman_result *qbman_get_dqrr_from_idx(struct qbman_swp *s, uint8_t idx); ++ ++/* ------------------------------------------------- */ ++/* Polling user-provided storage for dequeue results */ ++/* ------------------------------------------------- */ ++ ++/** ++ * qbman_result_has_new_result() - Check and get the dequeue response from the ++ * dq storage memory set in pull dequeue command ++ * @s: the software portal object. ++ * @dq: the dequeue result read from the memory. ++ * ++ * Only used for user-provided storage of dequeue results, not DQRR. For ++ * efficiency purposes, the driver will perform any required endianness ++ * conversion to ensure that the user's dequeue result storage is in host-endian ++ * format (whether or not that is the same as the little-endian format that ++ * hardware DMA'd to the user's storage). As such, once the user has called ++ * qbman_result_has_new_result() and been returned a valid dequeue result, ++ * they should not call it again on the same memory location (except of course ++ * if another dequeue command has been executed to produce a new result to that ++ * location). ++ * ++ * Return 1 for getting a valid dequeue result, or 0 for not getting a valid ++ * dequeue result. ++ */ ++int qbman_result_has_new_result(struct qbman_swp *s, ++ const struct qbman_result *dq); ++ ++/* -------------------------------------------------------- */ ++/* Parsing dequeue entries (DQRR and user-provided storage) */ ++/* -------------------------------------------------------- */ ++ ++/** ++ * qbman_result_is_DQ() - check the dequeue result is a dequeue response or not ++ * @dq: the dequeue result to be checked. ++ * ++ * DQRR entries may contain non-dequeue results, ie. notifications ++ */ ++int qbman_result_is_DQ(const struct qbman_result *); ++ ++/** ++ * qbman_result_is_SCN() - Check the dequeue result is notification or not ++ * @dq: the dequeue result to be checked. ++ * ++ * All the non-dequeue results (FQDAN/CDAN/CSCN/...) are "state change ++ * notifications" of one type or another. Some APIs apply to all of them, of the ++ * form qbman_result_SCN_***(). ++ */ ++static inline int qbman_result_is_SCN(const struct qbman_result *dq) ++{ ++ return !qbman_result_is_DQ(dq); ++} ++ ++/* Recognise different notification types, only required if the user allows for ++ * these to occur, and cares about them when they do. ++ */ ++ ++/** ++ * qbman_result_is_FQDAN() - Check for FQ Data Availability ++ * @dq: the qbman_result object. ++ * ++ * Return 1 if this is FQDAN. ++ */ ++int qbman_result_is_FQDAN(const struct qbman_result *dq); ++ ++/** ++ * qbman_result_is_CDAN() - Check for Channel Data Availability ++ * @dq: the qbman_result object to check. ++ * ++ * Return 1 if this is CDAN. ++ */ ++int qbman_result_is_CDAN(const struct qbman_result *dq); ++ ++/** ++ * qbman_result_is_CSCN() - Check for Congestion State Change ++ * @dq: the qbman_result object to check. ++ * ++ * Return 1 if this is CSCN. ++ */ ++int qbman_result_is_CSCN(const struct qbman_result *dq); ++ ++/** ++ * qbman_result_is_BPSCN() - Check for Buffer Pool State Change. ++ * @dq: the qbman_result object to check. ++ * ++ * Return 1 if this is BPSCN. ++ */ ++int qbman_result_is_BPSCN(const struct qbman_result *dq); ++ ++/** ++ * qbman_result_is_CGCU() - Check for Congestion Group Count Update. ++ * @dq: the qbman_result object to check. ++ * ++ * Return 1 if this is CGCU. ++ */ ++int qbman_result_is_CGCU(const struct qbman_result *dq); ++ ++/* Frame queue state change notifications; (FQDAN in theory counts too as it ++ * leaves a FQ parked, but it is primarily a data availability notification) ++ */ ++ ++/** ++ * qbman_result_is_FQRN() - Check for FQ Retirement Notification. ++ * @dq: the qbman_result object to check. ++ * ++ * Return 1 if this is FQRN. ++ */ ++int qbman_result_is_FQRN(const struct qbman_result *); ++ ++/** ++ * qbman_result_is_FQRNI() - Check for FQ Retirement Immediate ++ * @dq: the qbman_result object to check. ++ * ++ * Return 1 if this is FQRNI. ++ */ ++int qbman_result_is_FQRNI(const struct qbman_result *); ++ ++/** ++ * qbman_result_is_FQPN() - Check for FQ Park Notification ++ * @dq: the qbman_result object to check. ++ * ++ * Return 1 if this is FQPN. ++ */ ++int qbman_result_is_FQPN(const struct qbman_result *dq); ++ ++/* Parsing frame dequeue results (qbman_result_is_DQ() must be TRUE) ++ */ ++/* FQ empty */ ++#define QBMAN_DQ_STAT_FQEMPTY 0x80 ++/* FQ held active */ ++#define QBMAN_DQ_STAT_HELDACTIVE 0x40 ++/* FQ force eligible */ ++#define QBMAN_DQ_STAT_FORCEELIGIBLE 0x20 ++/* Valid frame */ ++#define QBMAN_DQ_STAT_VALIDFRAME 0x10 ++/* FQ ODP enable */ ++#define QBMAN_DQ_STAT_ODPVALID 0x04 ++/* Volatile dequeue */ ++#define QBMAN_DQ_STAT_VOLATILE 0x02 ++/* volatile dequeue command is expired */ ++#define QBMAN_DQ_STAT_EXPIRED 0x01 ++ ++/** ++ * qbman_result_DQ_flags() - Get the STAT field of dequeue response ++ * @dq: the dequeue result. ++ * ++ * Return the state field. ++ */ ++uint32_t qbman_result_DQ_flags(const struct qbman_result *dq); ++ ++/** ++ * qbman_result_DQ_is_pull() - Check whether the dq response is from a pull ++ * command. ++ * @dq: the dequeue result. ++ * ++ * Return 1 for volatile(pull) dequeue, 0 for static dequeue. ++ */ ++static inline int qbman_result_DQ_is_pull(const struct qbman_result *dq) ++{ ++ return (int)(qbman_result_DQ_flags(dq) & QBMAN_DQ_STAT_VOLATILE); ++} ++ ++/** ++ * qbman_result_DQ_is_pull_complete() - Check whether the pull command is ++ * completed. ++ * @dq: the dequeue result. ++ * ++ * Return boolean. ++ */ ++static inline int qbman_result_DQ_is_pull_complete( ++ const struct qbman_result *dq) ++{ ++ return (int)(qbman_result_DQ_flags(dq) & QBMAN_DQ_STAT_EXPIRED); ++} ++ ++/** ++ * qbman_result_DQ_seqnum() - Get the seqnum field in dequeue response ++ * seqnum is valid only if VALIDFRAME flag is TRUE ++ * @dq: the dequeue result. ++ * ++ * Return seqnum. ++ */ ++uint16_t qbman_result_DQ_seqnum(const struct qbman_result *dq); ++ ++/** ++ * qbman_result_DQ_odpid() - Get the seqnum field in dequeue response ++ * odpid is valid only if ODPVAILD flag is TRUE. ++ * @dq: the dequeue result. ++ * ++ * Return odpid. ++ */ ++uint16_t qbman_result_DQ_odpid(const struct qbman_result *dq); ++ ++/** ++ * qbman_result_DQ_fqid() - Get the fqid in dequeue response ++ * @dq: the dequeue result. ++ * ++ * Return fqid. ++ */ ++uint32_t qbman_result_DQ_fqid(const struct qbman_result *dq); ++ ++/** ++ * qbman_result_DQ_byte_count() - Get the byte count in dequeue response ++ * @dq: the dequeue result. ++ * ++ * Return the byte count remaining in the FQ. ++ */ ++uint32_t qbman_result_DQ_byte_count(const struct qbman_result *dq); ++ ++/** ++ * qbman_result_DQ_frame_count - Get the frame count in dequeue response ++ * @dq: the dequeue result. ++ * ++ * Return the frame count remaining in the FQ. ++ */ ++uint32_t qbman_result_DQ_frame_count(const struct qbman_result *dq); ++ ++/** ++ * qbman_result_DQ_fqd_ctx() - Get the frame queue context in dequeue response ++ * @dq: the dequeue result. ++ * ++ * Return the frame queue context. ++ */ ++uint64_t qbman_result_DQ_fqd_ctx(const struct qbman_result *dq); ++ ++/** ++ * qbman_result_DQ_fd() - Get the frame descriptor in dequeue response ++ * @dq: the dequeue result. ++ * ++ * Return the frame descriptor. ++ */ ++const struct qbman_fd *qbman_result_DQ_fd(const struct qbman_result *dq); ++ ++/* State-change notifications (FQDAN/CDAN/CSCN/...). */ ++ ++/** ++ * qbman_result_SCN_state() - Get the state field in State-change notification ++ * @scn: the state change notification. ++ * ++ * Return the state in the notifiation. ++ */ ++uint8_t qbman_result_SCN_state(const struct qbman_result *scn); ++ ++/** ++ * qbman_result_SCN_rid() - Get the resource id from the notification ++ * @scn: the state change notification. ++ * ++ * Return the resource id. ++ */ ++uint32_t qbman_result_SCN_rid(const struct qbman_result *scn); ++ ++/** ++ * qbman_result_SCN_ctx() - get the context from the notification ++ * @scn: the state change notification. ++ * ++ * Return the context. ++ */ ++uint64_t qbman_result_SCN_ctx(const struct qbman_result *scn); ++ ++/** ++ * qbman_result_SCN_state_in_mem() - Get the state in notification written ++ * in memory ++ * @scn: the state change notification. ++ * ++ * Return the state. ++ */ ++uint8_t qbman_result_SCN_state_in_mem(const struct qbman_result *scn); ++ ++/** ++ * qbman_result_SCN_rid_in_mem() - Get the resource id in notification written ++ * in memory. ++ * @scn: the state change notification. ++ * ++ * Return the resource id. ++ */ ++uint32_t qbman_result_SCN_rid_in_mem(const struct qbman_result *scn); ++ ++ ++/* Type-specific "resource IDs". Mainly for illustration purposes, though it ++ * also gives the appropriate type widths. ++ */ ++/* Get the FQID from the FQDAN */ ++#define qbman_result_FQDAN_fqid(dq) qbman_result_SCN_rid(dq) ++/* Get the FQID from the FQRN */ ++#define qbman_result_FQRN_fqid(dq) qbman_result_SCN_rid(dq) ++/* Get the FQID from the FQRNI */ ++#define qbman_result_FQRNI_fqid(dq) qbman_result_SCN_rid(dq) ++/* Get the FQID from the FQPN */ ++#define qbman_result_FQPN_fqid(dq) qbman_result_SCN_rid(dq) ++/* Get the channel ID from the CDAN */ ++#define qbman_result_CDAN_cid(dq) ((uint16_t)qbman_result_SCN_rid(dq)) ++/* Get the CGID from the CSCN */ ++#define qbman_result_CSCN_cgid(dq) ((uint16_t)qbman_result_SCN_rid(dq)) ++ ++/** ++ * qbman_result_bpscn_bpid() - Get the bpid from BPSCN ++ * @scn: the state change notification. ++ * ++ * Return the buffer pool id. ++ */ ++uint16_t qbman_result_bpscn_bpid(const struct qbman_result *scn); ++ ++/** ++ * qbman_result_bpscn_has_free_bufs() - Check whether there are free ++ * buffers in the pool from BPSCN. ++ * @scn: the state change notification. ++ * ++ * Return the number of free buffers. ++ */ ++int qbman_result_bpscn_has_free_bufs(const struct qbman_result *scn); ++ ++/** ++ * qbman_result_bpscn_is_depleted() - Check BPSCN to see whether the ++ * buffer pool is depleted. ++ * @scn: the state change notification. ++ * ++ * Return the status of buffer pool depletion. ++ */ ++int qbman_result_bpscn_is_depleted(const struct qbman_result *scn); ++ ++/** ++ * qbman_result_bpscn_is_surplus() - Check BPSCN to see whether the buffer ++ * pool is surplus or not. ++ * @scn: the state change notification. ++ * ++ * Return the status of buffer pool surplus. ++ */ ++int qbman_result_bpscn_is_surplus(const struct qbman_result *scn); ++ ++/** ++ * qbman_result_bpscn_ctx() - Get the BPSCN CTX from BPSCN message ++ * @scn: the state change notification. ++ * ++ * Return the BPSCN context. ++ */ ++uint64_t qbman_result_bpscn_ctx(const struct qbman_result *scn); ++ ++/* Parsing CGCU */ ++/** ++ * qbman_result_cgcu_cgid() - Check CGCU resouce id, i.e. cgid ++ * @scn: the state change notification. ++ * ++ * Return the CGCU resource id. ++ */ ++uint16_t qbman_result_cgcu_cgid(const struct qbman_result *scn); ++ ++/** ++ * qbman_result_cgcu_icnt() - Get the I_CNT from CGCU ++ * @scn: the state change notification. ++ * ++ * Return instantaneous count in the CGCU notification. ++ */ ++uint64_t qbman_result_cgcu_icnt(const struct qbman_result *scn); ++ ++ /************/ ++ /* Enqueues */ ++ /************/ ++ ++/** ++ * struct qbman_eq_desc - structure of enqueue descriptor ++ * @dont_manipulate_directly: the 8 32bit data to represent the whole ++ * possible qbman enqueue setting in enqueue descriptor. ++ */ ++struct qbman_eq_desc { ++ uint32_t dont_manipulate_directly[8]; ++}; ++ ++/** ++ * struct qbman_eq_response - structure of enqueue response ++ * @dont_manipulate_directly: the 16 32bit data to represent the whole ++ * enqueue response. ++ */ ++struct qbman_eq_response { ++ uint32_t dont_manipulate_directly[16]; ++}; ++ ++/** ++ * qbman_eq_desc_clear() - Clear the contents of a descriptor to ++ * default/starting state. ++ * @d: the given enqueue descriptor. ++ */ ++void qbman_eq_desc_clear(struct qbman_eq_desc *d); ++ ++/* Exactly one of the following descriptor "actions" should be set. (Calling ++ * any one of these will replace the effect of any prior call to one of these.) ++ * - enqueue without order-restoration ++ * - enqueue with order-restoration ++ * - fill a hole in the order-restoration sequence, without any enqueue ++ * - advance NESN (Next Expected Sequence Number), without any enqueue ++ * 'respond_success' indicates whether an enqueue response should be DMA'd ++ * after success (otherwise a response is DMA'd only after failure). ++ * 'incomplete' indicates that other fragments of the same 'seqnum' are yet to ++ * be enqueued. ++ */ ++ ++/** ++ * qbman_eq_desc_set_no_orp() - Set enqueue descriptor without orp ++ * @d: the enqueue descriptor. ++ * @response_success: 1 = enqueue with response always; 0 = enqueue with ++ * rejections returned on a FQ. ++ */ ++void qbman_eq_desc_set_no_orp(struct qbman_eq_desc *d, int respond_success); ++/** ++ * qbman_eq_desc_set_orp() - Set order-resotration in the enqueue descriptor ++ * @d: the enqueue descriptor. ++ * @response_success: 1 = enqueue with response always; 0 = enqueue with ++ * rejections returned on a FQ. ++ * @opr_id: the order point record id. ++ * @seqnum: the order restoration sequence number. ++ * @incomplete: indiates whether this is the last fragments using the same ++ * sequeue number. ++ */ ++void qbman_eq_desc_set_orp(struct qbman_eq_desc *d, int respond_success, ++ uint32_t opr_id, uint32_t seqnum, int incomplete); ++ ++/** ++ * qbman_eq_desc_set_orp_hole() - fill a hole in the order-restoration sequence ++ * without any enqueue ++ * @d: the enqueue descriptor. ++ * @opr_id: the order point record id. ++ * @seqnum: the order restoration sequence number. ++ */ ++void qbman_eq_desc_set_orp_hole(struct qbman_eq_desc *d, uint32_t opr_id, ++ uint32_t seqnum); ++ ++/** ++ * qbman_eq_desc_set_orp_nesn() - advance NESN (Next Expected Sequence Number) ++ * without any enqueue ++ * @d: the enqueue descriptor. ++ * @opr_id: the order point record id. ++ * @seqnum: the order restoration sequence number. ++ */ ++void qbman_eq_desc_set_orp_nesn(struct qbman_eq_desc *d, uint32_t opr_id, ++ uint32_t seqnum); ++/** ++ * qbman_eq_desc_set_response() - Set the enqueue response info. ++ * @d: the enqueue descriptor ++ * @storage_phys: the physical address of the enqueue response in memory. ++ * @stash: indicate that the write allocation enabled or not. ++ * ++ * In the case where an enqueue response is DMA'd, this determines where that ++ * response should go. (The physical/DMA address is given for hardware's ++ * benefit, but software should interpret it as a "struct qbman_eq_response" ++ * data structure.) 'stash' controls whether or not the write to main-memory ++ * expresses a cache-warming attribute. ++ */ ++void qbman_eq_desc_set_response(struct qbman_eq_desc *d, ++ dma_addr_t storage_phys, ++ int stash); ++ ++/** ++ * qbman_eq_desc_set_token() - Set token for the enqueue command ++ * @d: the enqueue descriptor ++ * @token: the token to be set. ++ * ++ * token is the value that shows up in an enqueue response that can be used to ++ * detect when the results have been published. The easiest technique is to zero ++ * result "storage" before issuing an enqueue, and use any non-zero 'token' ++ * value. ++ */ ++void qbman_eq_desc_set_token(struct qbman_eq_desc *d, uint8_t token); ++ ++/** ++ * Exactly one of the following descriptor "targets" should be set. (Calling any ++ * one of these will replace the effect of any prior call to one of these.) ++ * - enqueue to a frame queue ++ * - enqueue to a queuing destination ++ * Note, that none of these will have any affect if the "action" type has been ++ * set to "orp_hole" or "orp_nesn". ++ */ ++/** ++ * qbman_eq_desc_set_fq() - Set Frame Queue id for the enqueue command ++ * @d: the enqueue descriptor ++ * @fqid: the id of the frame queue to be enqueued. ++ */ ++void qbman_eq_desc_set_fq(struct qbman_eq_desc *d, uint32_t fqid); ++ ++/** ++ * qbman_eq_desc_set_qd() - Set Queuing Destination for the enqueue command. ++ * @d: the enqueue descriptor ++ * @qdid: the id of the queuing destination to be enqueued. ++ * @qd_bin: the queuing destination bin ++ * @qd_prio: the queuing destination priority. ++ */ ++void qbman_eq_desc_set_qd(struct qbman_eq_desc *d, uint32_t qdid, ++ uint32_t qd_bin, uint32_t qd_prio); ++ ++/** ++ * qbman_eq_desc_set_eqdi() - enable/disable EQDI interrupt ++ * @d: the enqueue descriptor ++ * @enable: boolean to enable/disable EQDI ++ * ++ * Determines whether or not the portal's EQDI interrupt source should be ++ * asserted after the enqueue command is completed. ++ */ ++void qbman_eq_desc_set_eqdi(struct qbman_eq_desc *d, int enable); ++ ++/** ++ * qbman_eq_desc_set_dca() - Set DCA mode in the enqueue command. ++ * @d: the enqueue descriptor. ++ * @enable: enabled/disable DCA mode. ++ * @dqrr_idx: DCAP_CI, the DCAP consumer index. ++ * @park: determine the whether park the FQ or not ++ * ++ * Determines whether or not a portal DQRR entry should be consumed once the ++ * enqueue command is completed. (And if so, and the DQRR entry corresponds to a ++ * held-active (order-preserving) FQ, whether the FQ should be parked instead of ++ * being rescheduled.) ++ */ ++void qbman_eq_desc_set_dca(struct qbman_eq_desc *d, int enable, ++ uint32_t dqrr_idx, int park); ++ ++/** ++ * qbman_swp_enqueue() - Issue an enqueue command. ++ * @s: the software portal used for enqueue. ++ * @d: the enqueue descriptor. ++ * @fd: the frame descriptor to be enqueued. ++ * ++ * Please note that 'fd' should only be NULL if the "action" of the ++ * descriptor is "orp_hole" or "orp_nesn". ++ * ++ * Return 0 for a successful enqueue, -EBUSY if the EQCR is not ready. ++ */ ++int qbman_swp_enqueue(struct qbman_swp *s, const struct qbman_eq_desc *d, ++ const struct qbman_fd *fd); ++ ++/* TODO: ++ * qbman_swp_enqueue_thresh() - Set threshold for EQRI interrupt. ++ * @s: the software portal. ++ * @thresh: the threshold to trigger the EQRI interrupt. ++ * ++ * An EQRI interrupt can be generated when the fill-level of EQCR falls below ++ * the 'thresh' value set here. Setting thresh==0 (the default) disables. ++ */ ++int qbman_swp_enqueue_thresh(struct qbman_swp *s, unsigned int thresh); ++ ++ /*******************/ ++ /* Buffer releases */ ++ /*******************/ ++/** ++ * struct qbman_release_desc - The structure for buffer release descriptor ++ * @dont_manipulate_directly: the 32bit data to represent the whole ++ * possible settings of qbman release descriptor. ++ */ ++struct qbman_release_desc { ++ uint32_t dont_manipulate_directly[1]; ++}; ++ ++/** ++ * qbman_release_desc_clear() - Clear the contents of a descriptor to ++ * default/starting state. ++ * @d: the qbman release descriptor. ++ */ ++void qbman_release_desc_clear(struct qbman_release_desc *d); ++ ++/** ++ * qbman_release_desc_set_bpid() - Set the ID of the buffer pool to release to ++ * @d: the qbman release descriptor. ++ */ ++void qbman_release_desc_set_bpid(struct qbman_release_desc *d, uint32_t bpid); ++ ++/** ++ * qbman_release_desc_set_rcdi() - Determines whether or not the portal's RCDI ++ * interrupt source should be asserted after the release command is completed. ++ * @d: the qbman release descriptor. ++ */ ++void qbman_release_desc_set_rcdi(struct qbman_release_desc *d, int enable); ++ ++/** ++ * qbman_swp_release() - Issue a buffer release command. ++ * @s: the software portal object. ++ * @d: the release descriptor. ++ * @buffers: a pointer pointing to the buffer address to be released. ++ * @num_buffers: number of buffers to be released, must be less than 8. ++ * ++ * Return 0 for success, -EBUSY if the release command ring is not ready. ++ */ ++int qbman_swp_release(struct qbman_swp *s, const struct qbman_release_desc *d, ++ const uint64_t *buffers, unsigned int num_buffers); ++ ++/* TODO: ++ * qbman_swp_release_thresh() - Set threshold for RCRI interrupt ++ * @s: the software portal. ++ * @thresh: the threshold. ++ * An RCRI interrupt can be generated when the fill-level of RCR falls below ++ * the 'thresh' value set here. Setting thresh==0 (the default) disables. ++ */ ++int qbman_swp_release_thresh(struct qbman_swp *s, unsigned int thresh); ++ ++ /*******************/ ++ /* Buffer acquires */ ++ /*******************/ ++/** ++ * qbman_swp_acquire() - Issue a buffer acquire command. ++ * @s: the software portal object. ++ * @bpid: the buffer pool index. ++ * @buffers: a pointer pointing to the acquired buffer address|es. ++ * @num_buffers: number of buffers to be acquired, must be less than 8. ++ * ++ * Return 0 for success, or negative error code if the acquire command ++ * fails. ++ */ ++int qbman_swp_acquire(struct qbman_swp *s, uint32_t bpid, uint64_t *buffers, ++ unsigned int num_buffers); ++ ++ /*****************/ ++ /* FQ management */ ++ /*****************/ ++/** ++ * qbman_swp_fq_schedule() - Move the fq to the scheduled state. ++ * @s: the software portal object. ++ * @fqid: the index of frame queue to be scheduled. ++ * ++ * There are a couple of different ways that a FQ can end up parked state, ++ * This schedules it. ++ * ++ * Return 0 for success, or negative error code for failure. ++ */ ++int qbman_swp_fq_schedule(struct qbman_swp *s, uint32_t fqid); ++ ++/** ++ * qbman_swp_fq_force() - Force the FQ to fully scheduled state. ++ * @s: the software portal object. ++ * @fqid: the index of frame queue to be forced. ++ * ++ * Force eligible will force a tentatively-scheduled FQ to be fully-scheduled ++ * and thus be available for selection by any channel-dequeuing behaviour (push ++ * or pull). If the FQ is subsequently "dequeued" from the channel and is still ++ * empty at the time this happens, the resulting dq_entry will have no FD. ++ * (qbman_result_DQ_fd() will return NULL.) ++ * ++ * Return 0 for success, or negative error code for failure. ++ */ ++int qbman_swp_fq_force(struct qbman_swp *s, uint32_t fqid); ++ ++/** ++ * These functions change the FQ flow-control stuff between XON/XOFF. (The ++ * default is XON.) This setting doesn't affect enqueues to the FQ, just ++ * dequeues. XOFF FQs will remain in the tenatively-scheduled state, even when ++ * non-empty, meaning they won't be selected for scheduled dequeuing. If a FQ is ++ * changed to XOFF after it had already become truly-scheduled to a channel, and ++ * a pull dequeue of that channel occurs that selects that FQ for dequeuing, ++ * then the resulting dq_entry will have no FD. (qbman_result_DQ_fd() will ++ * return NULL.) ++ */ ++/** ++ * qbman_swp_fq_xon() - XON the frame queue. ++ * @s: the software portal object. ++ * @fqid: the index of frame queue. ++ * ++ * Return 0 for success, or negative error code for failure. ++ */ ++int qbman_swp_fq_xon(struct qbman_swp *s, uint32_t fqid); ++/** ++ * qbman_swp_fq_xoff() - XOFF the frame queue. ++ * @s: the software portal object. ++ * @fqid: the index of frame queue. ++ * ++ * Return 0 for success, or negative error code for failure. ++ */ ++int qbman_swp_fq_xoff(struct qbman_swp *s, uint32_t fqid); ++ ++ /**********************/ ++ /* Channel management */ ++ /**********************/ ++ ++/** ++ * If the user has been allocated a channel object that is going to generate ++ * CDANs to another channel, then these functions will be necessary. ++ * CDAN-enabled channels only generate a single CDAN notification, after which ++ * it they need to be reenabled before they'll generate another. (The idea is ++ * that pull dequeuing will occur in reaction to the CDAN, followed by a ++ * reenable step.) Each function generates a distinct command to hardware, so a ++ * combination function is provided if the user wishes to modify the "context" ++ * (which shows up in each CDAN message) each time they reenable, as a single ++ * command to hardware. ++ */ ++ ++/** ++ * qbman_swp_CDAN_set_context() - Set CDAN context ++ * @s: the software portal object. ++ * @channelid: the channel index. ++ * @ctx: the context to be set in CDAN. ++ * ++ * Return 0 for success, or negative error code for failure. ++ */ ++int qbman_swp_CDAN_set_context(struct qbman_swp *s, uint16_t channelid, ++ uint64_t ctx); ++ ++/** ++ * qbman_swp_CDAN_enable() - Enable CDAN for the channel. ++ * @s: the software portal object. ++ * @channelid: the index of the channel to generate CDAN. ++ * ++ * Return 0 for success, or negative error code for failure. ++ */ ++int qbman_swp_CDAN_enable(struct qbman_swp *s, uint16_t channelid); ++ ++/** ++ * qbman_swp_CDAN_disable() - disable CDAN for the channel. ++ * @s: the software portal object. ++ * @channelid: the index of the channel to generate CDAN. ++ * ++ * Return 0 for success, or negative error code for failure. ++ */ ++int qbman_swp_CDAN_disable(struct qbman_swp *s, uint16_t channelid); ++ ++/** ++ * qbman_swp_CDAN_set_context_enable() - Set CDAN contest and enable CDAN ++ * @s: the software portal object. ++ * @channelid: the index of the channel to generate CDAN. ++ * @ctx: the context set in CDAN. ++ * ++ * Return 0 for success, or negative error code for failure. ++ */ ++int qbman_swp_CDAN_set_context_enable(struct qbman_swp *s, uint16_t channelid, ++ uint64_t ctx); ++int qbman_swp_fill_ring(struct qbman_swp *s, ++ const struct qbman_eq_desc *d, ++ const struct qbman_fd *fd, ++ uint8_t burst_index); ++int qbman_swp_flush_ring(struct qbman_swp *s); ++void qbman_sync(void); ++int qbman_swp_send_multiple(struct qbman_swp *s, ++ const struct qbman_eq_desc *d, ++ const struct qbman_fd *fd, ++ int frames_to_send); ++ ++int qbman_check_command_complete(struct qbman_swp *s, ++ const struct qbman_result *dq); ++#endif /* !_FSL_QBMAN_PORTAL_H */ +diff --git a/drivers/net/dpaa2/rte_eth_dpaa2_pvt.h b/drivers/net/dpaa2/rte_eth_dpaa2_pvt.h +new file mode 100644 +index 0000000..b35c3ee +--- /dev/null ++++ b/drivers/net/dpaa2/rte_eth_dpaa2_pvt.h +@@ -0,0 +1,313 @@ ++/*- ++ * BSD LICENSE ++ * ++ * Copyright(c) 2014 Freescale Semiconductor. All rights reserved. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * * Neither the name of Freescale Semiconductor nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#ifndef _RTE_ETH_DPAA2_PVT_H_ ++#define _RTE_ETH_DPAA2_PVT_H_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++typedef uint64_t dma_addr_t; ++ ++#define FALSE 0 ++#define TRUE 1 ++#ifndef false ++#define false FALSE ++#endif ++#ifndef true ++#define true TRUE ++#endif ++#define lower_32_bits(x) ((uint32_t)(x)) ++#define upper_32_bits(x) ((uint32_t)(((x) >> 16) >> 16)) ++ ++#ifndef ETH_ADDR_LEN ++#define ETH_ADDR_LEN 6 ++#endif ++#ifndef ETH_VLAN_HLEN ++#define ETH_VLAN_HLEN 4 /** < Vlan Header Length */ ++#endif ++ ++#define NUM_MAX_RECV_FRAMES 16 ++ ++#define MC_PORTAL_INDEX 0 ++#define NUM_DPIO_REGIONS 2 ++#define NUM_DQS_PER_QUEUE 2 ++#define MC_PORTALS_BASE_PADDR 0x00080C000000ULL ++#define MC_PORTAL_STRIDE 0x10000 ++#define MC_PORTAL_SIZE 64 ++#define MC_PORTAL_ID_TO_PADDR(portal_id) \ ++(MC_PORTALS_BASE_PADDR + (portal_id) * MC_PORTAL_STRIDE) ++ ++struct dpaa2_dpio_dev { ++ TAILQ_ENTRY(dpaa2_dpio_dev) next; /**< Pointer to Next device instance */ ++ uint16_t index; /**< Index of a instance in the list */ ++ rte_atomic16_t ref_count; /**< How many thread contexts are sharing this.*/ ++ struct fsl_mc_io *dpio; /** handle to DPIO portal object */ ++ uint16_t token; ++ struct qbman_swp *sw_portal; /** SW portal object */ ++ const struct qbman_result *dqrr[4]; /**< DQRR Entry for this SW portal */ ++ pthread_mutex_t lock; /** Required when Portal is shared */ ++ void *mc_portal; /**< MC Portal for configuring this device */ ++ uintptr_t qbman_portal_ce_paddr; /**< Physical address of Cache Enabled Area */ ++ uintptr_t ce_size; /**< Size of the CE region */ ++ uintptr_t qbman_portal_ci_paddr; /**< Physical address of Cache Inhibit Area */ ++ uintptr_t ci_size; /**< Size of the CI region */ ++ void *intr_handle; ++ int32_t vfio_fd; /**< File descriptor received via VFIO */ ++ int32_t hw_id; /**< An unique ID of this DPIO device instance */ ++}; ++ ++struct queue_storage_info_t { ++ struct qbman_result *dq_storage[NUM_DQS_PER_QUEUE]; ++ struct qbman_result *active_dqs; ++ int toggle; ++}; ++ ++struct thread_io_info_t { ++ struct dpaa2_dpio_dev *dpio_dev; ++ struct dpaa2_dpio_dev *sec_dpio_dev; ++ struct qbman_result *global_active_dqs; ++}; ++ ++/*! Global per thread DPIO portal */ ++extern __thread struct thread_io_info_t thread_io_info; ++/*! Global MCP list */ ++extern void *(*mcp_ptr_list); ++ ++/* Refer to Table 7-3 in SEC BG */ ++struct qbman_fle { ++ uint32_t addr_lo; ++ uint32_t addr_hi; ++ uint32_t length; ++ /* FMT must be 00, MSB is final bit */ ++ uint32_t fin_bpid_offset; ++ uint32_t frc; ++ uint32_t reserved[3]; /* Not used currently */ ++}; ++ ++/* Maximum release/acquire from QBMAN */ ++#define DPAA2_MBUF_MAX_ACQ_REL 7 ++ ++#define MAX_BPID 256 ++ ++/*Macros to define operations on FD*/ ++#define DPAA2_SET_FD_ADDR(fd, addr) \ ++ fd->simple.addr_lo = lower_32_bits((uint64_t)addr); \ ++ fd->simple.addr_hi = upper_32_bits((uint64_t)addr); ++#define DPAA2_SET_FD_LEN(fd, length) fd->simple.len = length ++#define DPAA2_SET_FD_BPID(fd, bpid) fd->simple.bpid_offset |= bpid; ++#define DPAA2_SET_FD_IVP(fd) ((fd->simple.bpid_offset |= 0x00004000)) ++#define DPAA2_SET_FD_OFFSET(fd, offset) (fd->simple.bpid_offset |= (uint32_t)(offset) << 16); ++#define DPAA2_SET_FD_FRC(fd, frc) fd->simple.frc = frc; ++#define DPAA2_RESET_FD_CTRL(fd) fd->simple.ctrl = 0; ++ ++#define DPAA2_SET_FD_ASAL(fd, asal) (fd->simple.ctrl |= (asal << 16)) ++#define DPAA2_SET_FD_FLC(fd, addr) \ ++ fd->simple.flc_lo = lower_32_bits((uint64_t)addr); \ ++ fd->simple.flc_hi = upper_32_bits((uint64_t)addr); ++#define DPAA2_GET_FLE_ADDR(fle) \ ++ (uint64_t)((((uint64_t)(fle->addr_hi)) << 32) + fle->addr_lo) ++#define DPAA2_SET_FLE_ADDR(fle, addr) \ ++ fle->addr_lo = lower_32_bits((uint64_t)addr); \ ++ fle->addr_hi = upper_32_bits((uint64_t)addr); ++#define DPAA2_SET_FLE_OFFSET(fle, offset) (fle)->fin_bpid_offset |= (uint32_t)(offset) << 16; ++#define DPAA2_SET_FLE_BPID(fle, bpid) (fle)->fin_bpid_offset |= (uint64_t)bpid; ++#define DPAA2_GET_FLE_BPID(fle, bpid) (fle->fin_bpid_offset & 0x000000ff) ++#define DPAA2_SET_FLE_FIN(fle) fle->fin_bpid_offset |= (uint64_t)1 << 31; ++#define DPAA2_SET_FLE_IVP(fle) (((fle)->fin_bpid_offset |= 0x00004000)) ++#define DPAA2_SET_FD_COMPOUND_FMT(fd) \ ++ fd->simple.bpid_offset |= (uint32_t)1 << 28; ++#define DPAA2_GET_FD_ADDR(fd) \ ++ (uint64_t)((((uint64_t)(fd->simple.addr_hi)) << 32) + fd->simple.addr_lo) ++#define DPAA2_GET_FD_LEN(fd) (fd->simple.len) ++#define DPAA2_GET_FD_BPID(fd) ((fd->simple.bpid_offset & 0x00003FFF)) ++#define DPAA2_GET_FD_IVP(fd) ((fd->simple.bpid_offset & 0x00004000) >> 14) ++#define DPAA2_GET_FD_OFFSET(fd) ((fd->simple.bpid_offset & 0x0FFF0000) >> 16) ++#define DPAA2_GET_FD_FRC(fd) (fd->simple.frc) ++#define DPAA2_GET_FD_FLC(fd) \ ++ (uint64_t)((((uint64_t)(fd->simple.flc_hi)) << 32) + fd->simple.flc_lo) ++ ++#define DPAA2_SET_FLE_SG_EXT(fle) fle->fin_bpid_offset |= (uint64_t)1<<29; ++#define DPAA2_IS_SET_FLE_SG_EXT(fle) \ ++ (fle->fin_bpid_offset & ((uint64_t)1<<29))? 1 : 0 ++ ++#define DPAA2_INLINE_MBUF_FROM_BUF(buf) \ ++ ((struct rte_mbuf *)((uint64_t)buf + DPAA2_FD_PTA_SIZE + DPAA2_MBUF_HW_ANNOTATION + DPAA2_RES)) ++#define DPAA2_BUF_FROM_INLINE_MBUF(mbuf) \ ++ ((uint8_t *)((uint64_t)mbuf - (DPAA2_FD_PTA_SIZE + DPAA2_MBUF_HW_ANNOTATION + DPAA2_RES))) ++ ++#define DPAA2_ASAL_VAL (DPAA2_MBUF_HW_ANNOTATION / 64) ++ ++/*Macros to define QBMAN enqueue options */ ++#define DPAA2_ETH_EQ_DISABLE 0 /*!< Dont Enqueue the Frame */ ++#define DPAA2_ETH_EQ_RESP_ON_SUCC 1 /*!< Enqueue the Frame with ++ response after success*/ ++#define DPAA2_ETH_EQ_RESP_ON_FAIL 2 /*!< Enqueue the Frame with ++ response after failure*/ ++#define DPAA2_ETH_EQ_NO_RESP 3 /*!< Enqueue the Frame without ++ response*/ ++/* Only Enqueue Error responses will be ++ * pushed on FQID_ERR of Enqueue FQ */ ++#define DPAA2_EQ_RESP_ERR_FQ 0 ++/* All Enqueue responses will be pushed on address ++ * set with qbman_eq_desc_set_response */ ++#define DPAA2_EQ_RESP_ALWAYS 1 ++ ++#define DPAA2_MAX_BUF_POOLS 8 ++ ++struct dpbp_node { ++ struct dpbp_node *next; ++ struct fsl_mc_io dpbp; ++ uint16_t token; ++ int dpbp_id; ++}; ++ ++struct buf_pool_cfg { ++ void *addr; /*!< The address from where DPAA2 will carve out the ++ * buffers. 'addr' should be 'NULL' if user wants ++ * to create buffers from the memory which user ++ * asked DPAA2 to reserve during 'nadk init' */ ++ phys_addr_t phys_addr; /*!< corresponding physical address ++ * of the memory provided in addr */ ++ uint32_t num; /*!< number of buffers */ ++ uint32_t size; /*!< size of each buffer. 'size' should include ++ * any headroom to be reserved and alignment */ ++ uint16_t align; /*!< Buffer alignment (in bytes) */ ++ uint16_t bpid; /*!< The buffer pool id. This will be filled ++ *in by DPAA2 for each buffer pool */ ++}; ++ ++struct buf_pool { ++ uint32_t size; ++ uint32_t num_bufs; ++ uint16_t bpid; ++ uint8_t *h_bpool_mem; ++ struct rte_mempool *mp; ++ struct dpbp_node *dpbp_node; ++}; ++ ++/*! ++ * Buffer pool list configuration structure. User need to give DPAA2 the ++ * valid number of 'num_buf_pools'. ++ */ ++struct dpaa2_bp_list_cfg { ++ struct buf_pool_cfg buf_pool; /* Configuration ++ * of each buffer pool */ ++}; ++ ++struct dpaa2_bp_list { ++ struct dpaa2_bp_list *next; ++ struct rte_mempool *mp; ++ struct buf_pool buf_pool; ++}; ++ ++struct bp_info { ++ uint32_t size; ++ uint32_t meta_data_size; ++ struct dpaa2_bp_list *bp_list; ++}; ++ ++extern struct dpaa2_bp_list *h_bp_list; ++ ++//todo - this is costly, need to write a fast coversion routine ++static void *dpaa2_mem_ptov(phys_addr_t paddr) ++{ ++ const struct rte_memseg *memseg = rte_eal_get_physmem_layout(); ++ int i; ++ ++ for (i = 0; i < RTE_MAX_MEMSEG && memseg[i].addr_64 != 0; i++) { ++ if (paddr >= memseg[i].phys_addr && ++ (char *)paddr < (char *)memseg[i].phys_addr + memseg[i].len) ++ return (void *)(memseg[i].addr_64 + (paddr - memseg[i].phys_addr)); ++ } ++ return NULL; ++} ++ ++static phys_addr_t dpaa2_mem_vtop(uint64_t vaddr) ++{ ++ const struct rte_memseg *memseg = rte_eal_get_physmem_layout(); ++ int i; ++ ++ for (i = 0; i < RTE_MAX_MEMSEG && memseg[i].addr_64 != 0; i++) { ++ if (vaddr >= memseg[i].addr_64 && ++ vaddr < memseg[i].addr_64 + memseg[i].len) ++ return memseg[i].phys_addr + (vaddr - memseg[i].addr_64); ++ } ++ return (phys_addr_t)(NULL); ++} ++ ++#ifdef RTE_LIBRTE_DPAA2_USE_PHYS_IOVA ++/* ++ * When we are using Physical addresses as IO Virtual Addresses, ++ * we call conversion routines nadk_mem_vtop & nadk_mem_ptov wherever required. ++ * These routines are called with help of below MACRO's ++ */ ++ ++#define DPAA2_MBUF_VADDR_TO_IOVA(mbuf) (mbuf->buf_physaddr) ++ ++/** ++ * macro to convert Virtual address to IOVA ++ */ ++#define DPAA2_VADDR_TO_IOVA(_vaddr) dpaa2_mem_vtop((uint64_t)(_vaddr)) ++ ++/** ++ * macro to convert IOVA to Virtual address ++ */ ++#define DPAA2_IOVA_TO_VADDR(_iova) dpaa2_mem_ptov((phys_addr_t)(_iova)) ++ ++/** ++ * macro to convert modify the memory containing Virtual address to IOVA ++ */ ++#define DPAA2_MODIFY_VADDR_TO_IOVA(_mem, _type) \ ++ {_mem = (_type)(dpaa2_mem_vtop((uint64_t)(_mem))); } ++ ++/** ++ * macro to convert modify the memory containing IOVA to Virtual address ++ */ ++#define DPAA2_MODIFY_IOVA_TO_VADDR(_mem, _type) \ ++ {_mem = (_type)(dpaa2_mem_ptov((phys_addr_t)(_mem))); } ++ ++#else ++#define DPAA2_MBUF_VADDR_TO_IOVA(mbuf) (mbuf->buf_addr) ++ ++#define DPAA2_VADDR_TO_IOVA(_vaddr) (_vaddr) ++#define DPAA2_IOVA_TO_VADDR(_iova) (_iova) ++#define DPAA2_MODIFY_VADDR_TO_IOVA(_mem, _type) ++#define DPAA2_MODIFY_IOVA_TO_VADDR(_mem, _type) ++#endif ++ ++#endif +diff --git a/drivers/net/dpaa2/rte_eth_dpbp.c b/drivers/net/dpaa2/rte_eth_dpbp.c +new file mode 100644 +index 0000000..6a7617d +--- /dev/null ++++ b/drivers/net/dpaa2/rte_eth_dpbp.c +@@ -0,0 +1,430 @@ ++/*- ++ * BSD LICENSE ++ * ++ * Copyright(c) 2014 Freescale Semiconductor. All rights reserved. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * * Neither the name of Freescale Semiconductor nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "rte_pci.h" ++#include "rte_memzone.h" ++ ++#include "rte_eth_dpaa2_pvt.h" ++#include "fsl_qbman_portal.h" ++#include ++ ++#include ++#include "dpaa2_logs.h" ++ ++static struct dpbp_node *g_dpbp_list; ++static struct dpbp_node *avail_dpbp; ++ ++struct bp_info bpid_info[MAX_BPID]; ++ ++struct dpaa2_bp_list *h_bp_list; ++ ++int ++dpaa2_create_dpbp_device( ++ int dpbp_id) ++{ ++ struct dpbp_node *dpbp_node; ++ int ret; ++ ++ /* Allocate DPAA2 dpbp handle */ ++ dpbp_node = (struct dpbp_node *)malloc(sizeof(struct dpbp_node)); ++ if (!dpbp_node) { ++ PMD_DRV_LOG(ERR, "Memory allocation failed for DPBP Device\n"); ++ return -1; ++ } ++ ++ /* Open the dpbp object */ ++ dpbp_node->dpbp.regs = mcp_ptr_list[MC_PORTAL_INDEX]; ++ ret = dpbp_open(&dpbp_node->dpbp, CMD_PRI_LOW, dpbp_id, &dpbp_node->token); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Resource allocation failure with err code: %d", ++ ret); ++ free(dpbp_node); ++ return -1; ++ } ++ ++ /* Clean the device first */ ++ ret = dpbp_reset(&dpbp_node->dpbp, CMD_PRI_LOW, dpbp_node->token); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Failure cleaning dpbp device with" ++ "error code %d\n", ret); ++ return -1; ++ } ++ ++ dpbp_node->dpbp_id = dpbp_id; ++ /* Add the dpbp handle into the global list */ ++ dpbp_node->next = g_dpbp_list; ++ g_dpbp_list = dpbp_node; ++ avail_dpbp = g_dpbp_list; ++ ++ PMD_DRV_LOG(INFO, "Buffer resource initialized\n"); ++ ++ return 0; ++} ++ ++int hw_mbuf_create_pool(struct rte_mempool *mp) ++{ ++ struct dpaa2_bp_list *bp_list; ++ struct dpbp_attr dpbp_attr; ++ int ret; ++ ++ if (!avail_dpbp) { ++ PMD_DRV_LOG(ERR, "DPAA2 resources not available\n"); ++ return -1; ++ } ++ ++ ret = dpbp_enable(&avail_dpbp->dpbp, CMD_PRI_LOW, avail_dpbp->token); ++ if (ret != 0) { ++ PMD_DRV_LOG(ERR, "Resource enable failure with" ++ "err code: %d\n", ret); ++ return -1; ++ } ++ ++ ret = dpbp_get_attributes(&avail_dpbp->dpbp, CMD_PRI_LOW, ++ avail_dpbp->token, &dpbp_attr); ++ if (ret != 0) { ++ PMD_DRV_LOG(ERR, "Resource read failure with" ++ "err code: %d\n", ret); ++ ret = dpbp_disable(&avail_dpbp->dpbp, CMD_PRI_LOW, ++ avail_dpbp->token); ++ return -1; ++ } ++ ++ /* Allocate the bp_list which will be added into global_bp_list */ ++ bp_list = (struct dpaa2_bp_list *)malloc(sizeof(struct dpaa2_bp_list)); ++ if (!bp_list) { ++ PMD_DRV_LOG(ERR, "No heap memory available\n"); ++ return -1; ++ } ++ ++ /* Set parameters of buffer pool list */ ++ bp_list->buf_pool.num_bufs = mp->size; ++ bp_list->buf_pool.size = mp->elt_size ++ - sizeof(struct rte_mbuf) - rte_pktmbuf_priv_size(mp); ++ bp_list->buf_pool.bpid = dpbp_attr.bpid; ++ bp_list->buf_pool.h_bpool_mem = NULL; ++ bp_list->buf_pool.mp = mp; ++ bp_list->buf_pool.dpbp_node = avail_dpbp; ++ bp_list->next = h_bp_list; ++ ++ mp->offload_ptr = dpbp_attr.bpid; ++ ++ /* Increment the available DPBP */ ++ avail_dpbp = avail_dpbp->next; ++ ++ bpid_info[dpbp_attr.bpid].size = bp_list->buf_pool.size; ++ bpid_info[dpbp_attr.bpid].meta_data_size = sizeof(struct rte_mbuf) ++ + rte_pktmbuf_priv_size(mp); ++ bpid_info[dpbp_attr.bpid].bp_list = bp_list; ++ ++ PMD_DRV_LOG(INFO, "BP List created for bpid =%d\n", dpbp_attr.bpid); ++ ++ h_bp_list = bp_list; ++ return 0; ++} ++ ++static inline void dpaa2_mbuf_release(uint64_t buf, uint32_t bpid) ++{ ++ struct qbman_release_desc releasedesc; ++ struct qbman_swp *swp; ++ int ret; ++ ++ if (!thread_io_info.dpio_dev) { ++ ret = dpaa2_affine_qbman_swp(); ++ if (ret != 0) { ++ PMD_DRV_LOG(ERR, "Failed to allocate IO portal"); ++ return; ++ } ++ } ++ swp = thread_io_info.dpio_dev->sw_portal; ++ ++ /* Create a release descriptor required for releasing ++ * buffers into BMAN */ ++ qbman_release_desc_clear(&releasedesc); ++ qbman_release_desc_set_bpid(&releasedesc, bpid); ++ ++ DPAA2_MODIFY_VADDR_TO_IOVA(buf, uint64_t); ++ do { ++ /* Release buffer into the BMAN */ ++ ret = qbman_swp_release(swp, &releasedesc, &buf, 1); ++ } while (ret == -EBUSY); ++ PMD_TX_FREE_LOG(DEBUG, "Released %p address to BMAN\n", buf); ++} ++ ++int hw_mbuf_alloc(struct rte_mempool *mp, void **mb) ++{ ++ struct qbman_swp *swp; ++ uint16_t bpid; ++ uint64_t buf; ++ int ret; ++ struct rte_mbuf *m; ++ ++ if ((mp->offload_ptr > MAX_BPID) || ++ !(bpid_info[mp->offload_ptr].bp_list)) { ++ ++ PMD_DRV_LOG(INFO, "DPAA2 buffer pool not configured\n"); ++ return -2; ++ } ++ ++ bpid = mp->offload_ptr; ++ ++ if (!thread_io_info.dpio_dev) { ++ ret = dpaa2_affine_qbman_swp(); ++ if (ret != 0) { ++ PMD_DRV_LOG(ERR, "Failed to allocate IO portal"); ++ return -1; ++ } ++ } ++ swp = thread_io_info.dpio_dev->sw_portal; ++ ++ do { ++ ret = qbman_swp_acquire(swp, bpid, &buf, 1); ++ } while (ret == -EBUSY); ++ if (ret <= 0) { ++ PMD_DRV_LOG(INFO, "Buffer alloc(bpid %d)fail: err: %x", ++ bpid, ret); ++ return -1; ++ } ++ DPAA2_MODIFY_IOVA_TO_VADDR(buf, uint64_t); ++ ++ PMD_DRV_LOG(INFO, "Acquired %p address from BMAN\n", buf); ++ m = (struct rte_mbuf *)DPAA2_INLINE_MBUF_FROM_BUF(buf); ++ RTE_MBUF_ASSERT(rte_mbuf_refcnt_read(m) == 0); ++ rte_mbuf_refcnt_set(m, 1); ++ *mb = m; ++ return 0; ++} ++ ++int hw_mbuf_free(void __rte_unused *m) ++{ ++ struct rte_mbuf *mb = (struct rte_mbuf *)m; ++ if ((mb->pool->offload_ptr > MAX_BPID) || ++ !(bpid_info[mb->pool->offload_ptr].bp_list)) { ++ ++ PMD_DRV_LOG(INFO, "DPAA2 buffer pool not configured\n"); ++ return -1; ++ } ++ ++ dpaa2_mbuf_release((uint64_t)DPAA2_BUF_FROM_INLINE_MBUF(m), ++ mb->pool->offload_ptr); ++ return 0; ++} ++ ++int hw_mbuf_alloc_bulk(struct rte_mempool *pool, ++ void **obj_table, unsigned count) ++{ ++ static int alloc; ++ struct qbman_swp *swp; ++ uint32_t mbuf_size; ++ uint16_t bpid; ++ uint64_t bufs[64]; ++ int ret; ++ unsigned i, n = 0; ++ struct rte_mbuf **mt = (struct rte_mbuf **)obj_table; ++ ++ //PMD_DRV_LOG(DEBUG, MBUF, "%s/n", __func__); ++ if ((pool->offload_ptr > MAX_BPID) || ++ !(bpid_info[pool->offload_ptr].bp_list)) { ++ ++ printf("\nDPAA2 buffer pool not configured\n"); ++ return -2; ++ } ++ ++ bpid = pool->offload_ptr; ++ ++ if (!thread_io_info.dpio_dev) { ++ ret = dpaa2_affine_qbman_swp(); ++ if (ret != 0) { ++ PMD_DRV_LOG(ERR, "Failed to allocate IO portal"); ++ return -1; ++ } ++ } ++ swp = thread_io_info.dpio_dev->sw_portal; ++ ++ /* if number of buffers requested is less than 7 */ ++ if (count < DPAA2_MBUF_MAX_ACQ_REL) { ++ ret = qbman_swp_acquire(swp, bpid, &bufs[n], count); ++ if (ret <= 0){ ++ PMD_DRV_LOG(ERR, "Failed to allocate buffers %d", ret); ++ return -1; ++ } ++ n = ret; ++ goto set_buf; ++ } ++ ++ while (n < count) { ++ ret = 0; ++ /* Acquire is all-or-nothing, so we drain in 7s, ++ * then in 1s for the remainder. */ ++ if ((count - n) > DPAA2_MBUF_MAX_ACQ_REL) { ++ ret = qbman_swp_acquire(swp, bpid, &bufs[n], ++ DPAA2_MBUF_MAX_ACQ_REL); ++ if (ret == DPAA2_MBUF_MAX_ACQ_REL) { ++ n += ret; ++ } ++ } ++ if (ret < DPAA2_MBUF_MAX_ACQ_REL) { ++ ret = qbman_swp_acquire(swp, bpid, &bufs[n], 1); ++ if (ret > 0) { ++ PMD_DRV_LOG(DEBUG, "Drained buffer: %x", ++ bufs[n]); ++ n += ret; ++ } ++ } ++ if (ret < 0) { ++ PMD_DRV_LOG(WARNING, "Buffer aquire failed with" ++ "err code: %d", ret); ++ break; ++ } ++ } ++ if (ret < 0 || n == 0){ ++ PMD_DRV_LOG(ERR, "Failed to allocate buffers %d", ret); ++ return -1; ++ } ++set_buf: ++ ++ mbuf_size = sizeof(struct rte_mbuf) + rte_pktmbuf_priv_size(pool); ++ ++ for (i = 0; i < n; i++ ) { ++ ++ DPAA2_MODIFY_IOVA_TO_VADDR(buf[i], uint64_t); ++ ++ mt[i] = (struct rte_mbuf *)(bufs[i] - mbuf_size); ++ PMD_DRV_LOG(DEBUG,"Acquired %p address %p from BMAN\n", (void *)bufs[i], (void *)mt[i]); ++ if (!bufs[i] || !mt[i]) { ++ printf("\n ??????? how come we have a null buffer %p, %p", ++ (void *)bufs[i], (void *)mt[i]); ++ } ++ } ++ ++ alloc +=n; ++ PMD_DRV_LOG(DEBUG, "Total = %d , req = %d done = %d", ++ alloc, count, n); ++ return 0; ++} ++ ++int hw_mbuf_free_bulk(struct rte_mempool *pool, void * const *obj_table, ++ unsigned n) ++{ ++ unsigned i; ++ struct rte_mbuf *m; ++ //PMD_DRV_LOG(INFO, "%s/n", __func__); ++ if ((pool->offload_ptr > MAX_BPID) || ++ !(bpid_info[pool->offload_ptr].bp_list)) { ++ ++ PMD_DRV_LOG(INFO, "DPAA2 buffer pool not configured\n"); ++ return -1; ++ } ++ for (i = 0; i < n; i++) { ++ m = (struct rte_mbuf *)(obj_table[i]); ++ dpaa2_mbuf_release((uint64_t)m->buf_addr, pool->offload_ptr); ++ } ++ ++ return 0; ++} ++ ++int hw_mbuf_init( ++ struct rte_mempool *mp, ++ void *_m) ++{ ++ struct rte_mbuf *m = (struct rte_mbuf *)((unsigned char *)_m + DPAA2_FD_PTA_SIZE + ++ DPAA2_MBUF_HW_ANNOTATION + DPAA2_RES); ++ uint32_t mbuf_size, buf_len, priv_size, head_size; ++ uint32_t bpid; ++ ++ if ((mp->offload_ptr > MAX_BPID) || ++ !(bpid_info[mp->offload_ptr].bp_list)) { ++ ++ PMD_DRV_LOG(WARNING, "DPAA2 buffer pool not configured\n"); ++ return -1; ++ } ++ /*todo - assuming that h_bp_list will be at top node*/ ++ bpid = mp->offload_ptr; ++ ++ priv_size = rte_pktmbuf_priv_size(mp); ++ mbuf_size = sizeof(struct rte_mbuf) + priv_size; ++ ++ RTE_MBUF_ASSERT(RTE_ALIGN(priv_size, RTE_MBUF_PRIV_ALIGN) == priv_size); ++ RTE_MBUF_ASSERT(mp->elt_size >= mbuf_size); ++ ++ memset(_m, 0, mp->elt_size); ++ ++ /*update it in global list as well */ ++ bpid_info[bpid].meta_data_size = DPAA2_RES; ++ ++/* head_size = DPAA2_FD_PTA_SIZE + DPAA2_MBUF_HW_ANNOTATION ++ + RTE_PKTMBUF_HEADROOM; ++ head_size = DPAA2_ALIGN_ROUNDUP(head_size, ++ DPAA2_PACKET_LAYOUT_ALIGN); ++ head_size -= DPAA2_FD_PTA_SIZE + DPAA2_MBUF_HW_ANNOTATION; ++*/ ++ head_size = RTE_PKTMBUF_HEADROOM; ++ ++ buf_len = rte_pktmbuf_data_room_size(mp) ++ - (DPAA2_FD_PTA_SIZE + DPAA2_MBUF_HW_ANNOTATION + DPAA2_RES /* dummy */); ++ ++ RTE_MBUF_ASSERT(buf_len <= UINT16_MAX); ++ ++ /* start of buffer is after mbuf structure and priv data */ ++ m->priv_size = priv_size; ++ m->buf_addr = (char *)m + mbuf_size ; ++ m->buf_physaddr = rte_mempool_virt2phy(mp, _m) + DPAA2_FD_PTA_SIZE + ++ DPAA2_MBUF_HW_ANNOTATION + DPAA2_RES + mbuf_size; ++ m->buf_len = (uint16_t)buf_len; ++ ++ /* keep some headroom between start of buffer and data */ ++ m->data_off = RTE_MIN(head_size, (uint16_t)m->buf_len); ++ /* init some constant fields */ ++ m->pool = mp; ++ m->nb_segs = 1; ++ m->port = 0xff; ++ ++ /* Release the mempool buffer to BMAN */ ++ dpaa2_mbuf_release((uint64_t)_m, bpid); ++ return 0; ++} ++ +diff --git a/drivers/net/dpaa2/rte_eth_dpio.c b/drivers/net/dpaa2/rte_eth_dpio.c +new file mode 100644 +index 0000000..23f0b08 +--- /dev/null ++++ b/drivers/net/dpaa2/rte_eth_dpio.c +@@ -0,0 +1,339 @@ ++/*- ++ * BSD LICENSE ++ * ++ * Copyright(c) 2014 Freescale Semiconductor. All rights reserved. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * * Neither the name of Freescale Semiconductor nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "rte_pci.h" ++#include "rte_memzone.h" ++#include ++ ++#include "rte_eth_dpaa2_pvt.h" ++#include "fsl_qbman_portal.h" ++#include ++ ++#include ++#include "dpaa2_logs.h" ++ ++#define NUM_HOST_CPUS RTE_MAX_LCORE ++ ++__thread struct thread_io_info_t thread_io_info; ++ ++TAILQ_HEAD(dpio_device_list, dpaa2_dpio_dev); ++static struct dpio_device_list *dpio_dev_list; /*!< DPIO device list */ ++static uint32_t io_space_count; ++ ++/*Stashing Macros*/ ++#define DPAA2_CORE_CLUSTER_BASE 0x04 ++#define DPAA2_CORE_CLUSTER_FIRST (DPAA2_CORE_CLUSTER_BASE + 0) ++#define DPAA2_CORE_CLUSTER_SECOND (DPAA2_CORE_CLUSTER_BASE + 1) ++#define DPAA2_CORE_CLUSTER_THIRD (DPAA2_CORE_CLUSTER_BASE + 2) ++#define DPAA2_CORE_CLUSTER_FOURTH (DPAA2_CORE_CLUSTER_BASE + 3) ++ ++#define DPAA2_CORE_CLUSTER_GET(sdest, cpu_id) \ ++do { \ ++ if (cpu_id == 0 || cpu_id == 1) \ ++ sdest = DPAA2_CORE_CLUSTER_FIRST; \ ++ else if (cpu_id == 2 || cpu_id == 3) \ ++ sdest = DPAA2_CORE_CLUSTER_SECOND; \ ++ else if (cpu_id == 4 || cpu_id == 5) \ ++ sdest = DPAA2_CORE_CLUSTER_THIRD; \ ++ else \ ++ sdest = DPAA2_CORE_CLUSTER_FOURTH; \ ++} while (0) ++ ++static int ++configure_dpio_qbman_swp(struct dpaa2_dpio_dev *dpio_dev) ++{ ++ struct qbman_swp_desc p_des; ++ struct dpio_attr attr; ++ ++ dpio_dev->dpio = malloc(sizeof(struct fsl_mc_io)); ++ if (!dpio_dev->dpio) { ++ PMD_DRV_LOG(ERR, "Memory allocation failure\n"); ++ return -1; ++ } ++ ++ PMD_DRV_LOG(INFO, "\t Alocated DPIO[%p]\n", dpio_dev->dpio); ++ dpio_dev->dpio->regs = dpio_dev->mc_portal; ++ if (dpio_open(dpio_dev->dpio, CMD_PRI_LOW, dpio_dev->hw_id, ++ &dpio_dev->token)) { ++ PMD_DRV_LOG(ERR, "Failed to allocate IO space\n"); ++ free(dpio_dev->dpio); ++ return -1; ++ } ++ ++ if (dpio_enable(dpio_dev->dpio, CMD_PRI_LOW, dpio_dev->token)) { ++ PMD_DRV_LOG(ERR, "Failed to Enable dpio\n"); ++ dpio_close(dpio_dev->dpio, CMD_PRI_LOW, dpio_dev->token); ++ free(dpio_dev->dpio); ++ return -1; ++ } ++ ++ if (dpio_get_attributes(dpio_dev->dpio, CMD_PRI_LOW, ++ dpio_dev->token, &attr)) { ++ PMD_DRV_LOG(ERR, "DPIO Get attribute failed\n"); ++ dpio_disable(dpio_dev->dpio, CMD_PRI_LOW, dpio_dev->token); ++ dpio_close(dpio_dev->dpio, CMD_PRI_LOW, dpio_dev->token); ++ free(dpio_dev->dpio); ++ return -1; ++ } ++ ++ PMD_DRV_LOG(INFO, "Qbman Portal ID %d\n", attr.qbman_portal_id); ++ PMD_DRV_LOG(INFO, "Portal CE addr 0x%lX\n", attr.qbman_portal_ce_offset); ++ PMD_DRV_LOG(INFO, "Portal CI addr 0x%lX\n", attr.qbman_portal_ci_offset); ++ ++ /* Configure & setup SW portal */ ++ p_des.block = NULL; ++ p_des.idx = attr.qbman_portal_id; ++ p_des.cena_bar = (void *)(dpio_dev->qbman_portal_ce_paddr); ++ p_des.cinh_bar = (void *)(dpio_dev->qbman_portal_ci_paddr); ++ p_des.irq = -1; ++ p_des.qman_version = attr.qbman_version; ++ ++ PMD_DRV_LOG(INFO, "Portal CE addr 0x%p\n", p_des.cena_bar); ++ PMD_DRV_LOG(INFO, "Portal CI addr 0x%p\n", p_des.cinh_bar); ++ ++ dpio_dev->sw_portal = qbman_swp_init(&p_des); ++ if (dpio_dev->sw_portal == NULL) { ++ PMD_DRV_LOG(ERR, " QBMan SW Portal Init failed\n"); ++ dpio_close(dpio_dev->dpio, CMD_PRI_LOW, dpio_dev->token); ++ free(dpio_dev->dpio); ++ return -1; ++ } ++ ++ PMD_DRV_LOG(INFO, "QBMan SW Portal 0x%p\n", dpio_dev->sw_portal); ++ ++ return 0; ++} ++ ++int dpaa2_configure_stashing(struct dpaa2_dpio_dev *dpio_dev) ++{ ++ int sdest; ++ int cpu_id, ret; ++ ++ /* Set the Stashing Destination */ ++ cpu_id = rte_lcore_id(); ++ if (cpu_id < 0) { ++ cpu_id = rte_get_master_lcore(); ++ if (cpu_id < 0) { ++ PMD_DRV_LOG(ERR, "\tGetting CPU Index failed\n"); ++ return -1; ++ } ++ } ++ ++ /* ++ * In case of running DPDK on the Virtual Machine the Stashing ++ * Destination gets set in the H/W w.r.t. the Virtual CPU ID's. ++ * As a W.A. environment variable HOST_START_CPU tells which ++ * the offset of the host start core of the Virtual Machine threads. ++ */ ++ if (getenv("HOST_START_CPU")) { ++ cpu_id += ++ atoi(getenv("HOST_START_CPU")); ++ cpu_id = cpu_id % NUM_HOST_CPUS; ++ } ++ ++ /* Set the STASH Destination depending on Current CPU ID. ++ Valid values of SDEST are 4,5,6,7. Where, ++ CPU 0-1 will have SDEST 4 ++ CPU 2-3 will have SDEST 5.....and so on. ++ */ ++ DPAA2_CORE_CLUSTER_GET(sdest, cpu_id); ++ PMD_DRV_LOG(INFO, "Portal= %d CPU= %u SDEST= %d\n", ++ dpio_dev->index, cpu_id, sdest); ++ ++ ret = dpio_set_stashing_destination(dpio_dev->dpio, CMD_PRI_LOW, ++ dpio_dev->token, sdest); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "%d ERROR in SDEST\n", ret); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int ++dpaa2_affine_qbman_swp(void) ++{ ++ struct dpaa2_dpio_dev *dpio_dev = NULL; ++ int ret; ++ ++ if (thread_io_info.dpio_dev) ++ return 0; ++ ++ /* Get DPIO dev handle from list using index */ ++ TAILQ_FOREACH(dpio_dev, dpio_dev_list, next) { ++ if (dpio_dev && rte_atomic16_test_and_set(&dpio_dev->ref_count)) ++ break; ++ } ++ if (!dpio_dev) ++ return -1; ++ ++ /* Populate the thread_io_info structure */ ++ thread_io_info.dpio_dev = dpio_dev; ++ ++ ret = dpaa2_configure_stashing(dpio_dev); ++ if (ret) { ++ RTE_LOG(ERR, EAL, "dpaa2_configure_stashing failed"); ++ } ++ return ret; ++} ++ ++int ++dpaa2_affine_qbman_swp_sec(void) ++{ ++ struct dpaa2_dpio_dev *dpio_dev = NULL; ++ int ret; ++ ++ if (thread_io_info.sec_dpio_dev) ++ return 0; ++ ++ /* Get DPIO dev handle from list using index */ ++ TAILQ_FOREACH(dpio_dev, dpio_dev_list, next) { ++ if (dpio_dev && rte_atomic16_read(&dpio_dev->ref_count) == 0) { ++ rte_atomic16_inc(&dpio_dev->ref_count); ++ break; ++ } ++ } ++ if (!dpio_dev) ++ return -1; ++ ++ /* Populate the thread_io_info structure */ ++ thread_io_info.sec_dpio_dev = dpio_dev; ++ ++ ret = dpaa2_configure_stashing(dpio_dev); ++ if (ret) { ++ RTE_LOG(ERR, EAL, "dpaa2_configure_stashing failed"); ++ } ++ return ret; ++} ++ ++int ++dpaa2_create_dpio_device(struct vfio_device *vdev, ++ struct vfio_device_info *obj_info, ++ int object_id) ++{ ++ struct dpaa2_dpio_dev *dpio_dev; ++ struct vfio_region_info reg_info = { .argsz = sizeof(reg_info)}; ++ ++ if (obj_info->num_regions < NUM_DPIO_REGIONS) { ++ PMD_DRV_LOG(ERR, "ERROR, Not sufficient number " ++ "of DPIO regions.\n"); ++ return -1; ++ } ++ ++ if (!dpio_dev_list) { ++ dpio_dev_list = malloc(sizeof(struct dpio_device_list)); ++ if (NULL == dpio_dev_list) { ++ PMD_DRV_LOG(ERR, "Memory allocation failed for DPIO list\n"); ++ return -1; ++ } ++ ++ /* Initialize the DPIO List */ ++ TAILQ_INIT(dpio_dev_list); ++ } ++ ++ dpio_dev = malloc(sizeof(struct dpaa2_dpio_dev)); ++ if (!dpio_dev) { ++ PMD_DRV_LOG(ERR, "Memory allocation failed for DPIO Device\n"); ++ return -1; ++ } ++ ++ PMD_DRV_LOG(INFO, "\t Aloocated DPIO [%p]\n", dpio_dev); ++ dpio_dev->dpio = NULL; ++ dpio_dev->hw_id = object_id; ++ dpio_dev->vfio_fd = vdev->fd; ++ rte_atomic16_init(&dpio_dev->ref_count); ++ /* Using single portal for all devices */ ++ dpio_dev->mc_portal = mcp_ptr_list[MC_PORTAL_INDEX]; ++ ++ reg_info.index = 0; ++ if (ioctl(dpio_dev->vfio_fd, VFIO_DEVICE_GET_REGION_INFO, ®_info)) { ++ printf("vfio: error getting region info\n"); ++ return -1; ++ } ++ ++ PMD_DRV_LOG(INFO, "\t Region Offset = %llx\n", reg_info.offset); ++ PMD_DRV_LOG(INFO, "\t Region Size = %llx\n", reg_info.size); ++ dpio_dev->ce_size = reg_info.size; ++ dpio_dev->qbman_portal_ce_paddr = (uint64_t)mmap(NULL, reg_info.size, ++ PROT_WRITE | PROT_READ, MAP_SHARED, ++ dpio_dev->vfio_fd, reg_info.offset); ++ ++ /* Create Mapping for QBMan Cache Enabled area. This is a fix for ++ SMMU fault for DQRR statshing transaction. */ ++ if (vfio_dmamap_mem_region(dpio_dev->qbman_portal_ce_paddr, ++ reg_info.offset, reg_info.size)) { ++ PMD_DRV_LOG(ERR, "DMAMAP for Portal CE area failed.\n"); ++ return -1; ++ } ++ ++ reg_info.index = 1; ++ if (ioctl(dpio_dev->vfio_fd, VFIO_DEVICE_GET_REGION_INFO, ®_info)) { ++ printf("vfio: error getting region info\n"); ++ return -1; ++ } ++ ++ PMD_DRV_LOG(INFO, "\t Region Offset = %llx\n", reg_info.offset); ++ PMD_DRV_LOG(INFO, "\t Region Size = %llx\n", reg_info.size); ++ dpio_dev->ci_size = reg_info.size; ++ dpio_dev->qbman_portal_ci_paddr = (uint64_t)mmap(NULL, reg_info.size, ++ PROT_WRITE | PROT_READ, MAP_SHARED, ++ dpio_dev->vfio_fd, reg_info.offset); ++ ++ if (configure_dpio_qbman_swp(dpio_dev)) { ++ PMD_DRV_LOG(ERR, ++ "Failed in configuring the qbman portal for dpio %d\n", ++ dpio_dev->hw_id); ++ return -1; ++ } ++ ++ io_space_count++; ++ dpio_dev->index = io_space_count; ++ TAILQ_INSERT_HEAD(dpio_dev_list, dpio_dev, next); ++ ++ return 0; ++} ++ +diff --git a/drivers/net/dpaa2/rte_eth_dpni.c b/drivers/net/dpaa2/rte_eth_dpni.c +new file mode 100644 +index 0000000..62baf03 +--- /dev/null ++++ b/drivers/net/dpaa2/rte_eth_dpni.c +@@ -0,0 +1,2230 @@ ++/*- ++ * BSD LICENSE ++ * ++ * Copyright (c) 2014 Freescale Semiconductor, Inc. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * * Neither the name of Freescale Semiconductor, Inc nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++/* MC header files */ ++#include ++#include ++#include "rte_eth_dpaa2_pvt.h" ++#include "rte_eth_dpni_annot.h" ++#include "dpaa2_logs.h" ++ ++#include ++#include ++ ++#define DPAA2_STASHING ++ ++/* tx fd send batching */ ++#define QBMAN_MULTI_TX ++ ++#define RTE_ETH_DPAA2_SNAPSHOT_LEN 65535 ++#define RTE_ETH_DPAA2_SNAPLEN 4096 ++#define RTE_ETH_DPAA2_PROMISC 1 ++#define RTE_ETH_DPAA2_TIMEOUT -1 ++#define ETH_DPAA2_RX_IFACE_ARG "rx_iface" ++#define ETH_DPAA2_TX_IFACE_ARG "tx_iface" ++#define ETH_DPAA2_IFACE_ARG "iface" ++ ++static const char *drivername = "DPNI PMD"; ++ ++#define MAX_TCS DPNI_MAX_TC ++#define MAX_RX_QUEUES 64 ++#define MAX_TX_QUEUES 64 ++ ++/*Maximum number of slots available in TX ring*/ ++#define MAX_SLOTS 8 ++ ++/*Threshold for a queue to *Enter* Congestion state. ++ It is set to 128 frames of size 64 bytes.*/ ++#define CONG_ENTER_THRESHOLD 128*64 ++ ++/*Threshold for a queue to *Exit* Congestion state. ++ It is set to 98 frames of size 64 bytes*/ ++#define CONG_EXIT_THRESHOLD 98*64 ++ ++/*! Maximum number of flow distributions per traffic class */ ++#define MAX_DIST_PER_TC 16 ++ ++/* Size of the input SMMU mapped memory required by MC */ ++#define DIST_PARAM_IOVA_SIZE 256 ++ ++struct dpaa2_queue { ++ void *dev; ++ int32_t eventfd; /*!< Event Fd of this queue */ ++ uint32_t fqid; /*!< Unique ID of this queue */ ++ uint8_t tc_index; /*!< traffic class identifier */ ++ uint16_t flow_id; /*!< To be used by DPAA2 frmework */ ++ uint64_t rx_pkts; ++ uint64_t tx_pkts; ++ uint64_t err_pkts; ++ union { ++ struct queue_storage_info_t *q_storage; ++ struct qbman_result *cscn; ++ }; ++}; ++ ++struct dpaa2_dev_priv { ++ void *hw; ++ int32_t hw_id; ++ int32_t qdid; ++ uint16_t token; ++ uint8_t nb_tx_queues; ++ uint8_t nb_rx_queues; ++ void *rx_vq[MAX_RX_QUEUES]; ++ void *tx_vq[MAX_TX_QUEUES]; ++ ++ struct dpaa2_bp_list *bp_list; /**data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ uint64_t value; ++ ++ dpni_get_counter(dpni, CMD_PRI_LOW, priv->token, DPNI_CNT_ING_FRAME, &value); ++ printf("Rx packets: %ld\n", value); ++ dpni_get_counter(dpni, CMD_PRI_LOW, priv->token, DPNI_CNT_ING_BYTE, &value); ++ printf("Rx bytes: %ld\n", value); ++ dpni_get_counter(dpni, CMD_PRI_LOW, priv->token, DPNI_CNT_ING_MCAST_FRAME, &value); ++ printf("Rx Multicast: %ld\n", value); ++ dpni_get_counter(dpni, CMD_PRI_LOW, priv->token, DPNI_CNT_ING_FRAME_DROP, &value); ++ printf("Rx dropped: %ld\n", value); ++ dpni_get_counter(dpni, CMD_PRI_LOW, priv->token, DPNI_CNT_ING_FRAME_DISCARD, &value); ++ printf("Rx discarded: %ld\n", value); ++ dpni_get_counter(dpni, CMD_PRI_LOW, priv->token, DPNI_CNT_EGR_FRAME, &value); ++ printf("Tx packets: %ld\n", value); ++ dpni_get_counter(dpni, CMD_PRI_LOW, priv->token, DPNI_CNT_EGR_BYTE, &value); ++ printf("Tx bytes: %ld\n", value); ++ dpni_get_counter(dpni, CMD_PRI_LOW, priv->token, DPNI_CNT_EGR_FRAME_DISCARD, &value); ++ printf("Tx dropped: %ld\n", value); ++} ++ ++/** ++ * Atomically reads the link status information from global ++ * structure rte_eth_dev. ++ * ++ * @param dev ++ * - Pointer to the structure rte_eth_dev to read from. ++ * - Pointer to the buffer to be saved with the link status. ++ * ++ * @return ++ * - On success, zero. ++ * - On failure, negative value. ++ */ ++static inline int ++rte_dpni_dev_atomic_read_link_status(struct rte_eth_dev *dev, ++ struct rte_eth_link *link) ++{ ++ struct rte_eth_link *dst = link; ++ struct rte_eth_link *src = &dev->data->dev_link; ++ ++ if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst, ++ *(uint64_t *)src) == 0) ++ return -1; ++ ++ return 0; ++} ++ ++/** ++ * Atomically writes the link status information into global ++ * structure rte_eth_dev. ++ * ++ * @param dev ++ * - Pointer to the structure rte_eth_dev to read from. ++ * - Pointer to the buffer to be saved with the link status. ++ * ++ * @return ++ * - On success, zero. ++ * - On failure, negative value. ++ */ ++static inline int ++rte_dpni_dev_atomic_write_link_status(struct rte_eth_dev *dev, ++ struct rte_eth_link *link) ++{ ++ struct rte_eth_link *dst = &dev->data->dev_link; ++ struct rte_eth_link *src = link; ++ ++ if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst, ++ *(uint64_t *)src) == 0) ++ return -1; ++ ++ return 0; ++} ++ ++static inline void ++dpaa2_eth_parse_packet(struct rte_mbuf *mbuf) ++{ ++ uint32_t pkt_type = 0; ++ struct pkt_annotation *annotation = (struct pkt_annotation *) ++ ((uint8_t *)mbuf - (DPAA2_MBUF_HW_ANNOTATION + DPAA2_RES)); ++ ++ PMD_DRV_LOG(DEBUG, "\n 1 annotation = 0x%x ", annotation->word4); ++ ++ if (BIT_ISSET_AT_POS(annotation->word3, L2_ETH_MAC_PRESENT)) ++ pkt_type/* mbuf->packet_type */ |= RTE_PTYPE_L2_ETHER; ++ ++ if (BIT_ISSET_AT_POS(annotation->word4, L3_IPV4_1_PRESENT)) ++ pkt_type/* mbuf->packet_type */ |= RTE_PTYPE_L3_IPV4; ++ ++ if (BIT_ISSET_AT_POS(annotation->word4, L3_IPV6_1_PRESENT)) ++ pkt_type /* mbuf->packet_type */ |= RTE_PTYPE_L3_IPV6; ++ ++ if (BIT_ISSET_AT_POS(annotation->word4, L3_IP_1_OPT_PRESENT)) ++ pkt_type/* mbuf->packet_type */ |= RTE_PTYPE_L3_IPV4_EXT; ++ ++ if (BIT_ISSET_AT_POS(annotation->word4, L3_PROTO_UDP_PRESENT)) ++ pkt_type/* mbuf->packet_type */ |= RTE_PTYPE_L4_UDP; ++ ++ if (BIT_ISSET_AT_POS(annotation->word4, L3_PROTO_TCP_PRESENT)) ++ pkt_type/* mbuf->packet_type */ |= RTE_PTYPE_L4_TCP; ++ ++ if (BIT_ISSET_AT_POS(annotation->word4, L3_PROTO_SCTP_PRESENT)) ++ pkt_type/* mbuf->packet_type */ |= RTE_PTYPE_L4_SCTP; ++ ++ if (BIT_ISSET_AT_POS(annotation->word4, L3_PROTO_ICMP_PRESENT)) ++ pkt_type/* mbuf->packet_type */ |= RTE_PTYPE_L4_ICMP; ++ ++ if (BIT_ISSET_AT_POS(annotation->word4, L3_IP_UNKNOWN_PROTOCOL)) ++ pkt_type/* mbuf->packet_type */ |= RTE_PTYPE_UNKNOWN; ++ ++ mbuf->packet_type = pkt_type; ++} ++ ++static inline ++struct rte_mbuf *eth_fd_to_mbuf(const struct qbman_fd *fd) ++{ ++ struct rte_mbuf *mbuf = DPAA2_INLINE_MBUF_FROM_BUF(DPAA2_GET_FD_ADDR(fd)); ++ ++ PMD_DRV_LOG(DEBUG, "\nmbuf %p BMAN buf addr %p", ++ (void *)mbuf, mbuf->buf_addr); ++ ++ PMD_DRV_LOG(DEBUG, "\nfdaddr =%lx bpid =%d meta =%d off =%d, len =%d\n", ++ DPAA2_GET_FD_ADDR(fd), ++ DPAA2_GET_FD_BPID(fd), ++ bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size, ++ DPAA2_GET_FD_OFFSET(fd), ++ DPAA2_GET_FD_LEN(fd)); ++ ++// mbuf->data_off = DPAA2_GET_FD_OFFSET(fd); ++ mbuf->data_len = DPAA2_GET_FD_LEN(fd); ++ mbuf->pkt_len = mbuf->data_len; ++ mbuf->next = NULL; ++ rte_mbuf_refcnt_set(mbuf, 1); ++ ++ /* Parse the packet */ ++ dpaa2_eth_parse_packet(mbuf); ++ ++ mbuf->nb_segs = 1; ++ mbuf->ol_flags = 0; ++ ++ return mbuf; ++} ++ ++static void __attribute__ ((noinline)) eth_mbuf_to_fd(struct rte_mbuf *mbuf, ++ struct qbman_fd *fd, uint16_t bpid) ++{ ++ /*Resetting the buffer pool id and offset field*/ ++ fd->simple.bpid_offset = 0; ++ ++ DPAA2_SET_FD_ADDR(fd, DPAA2_VADDR_TO_IOVA(DPAA2_BUF_FROM_INLINE_MBUF(mbuf))); ++ DPAA2_SET_FD_LEN(fd, mbuf->data_len); ++ DPAA2_SET_FD_BPID(fd, bpid); ++ DPAA2_SET_FD_OFFSET(fd, DPAA2_FD_PTA_SIZE + DPAA2_MBUF_HW_ANNOTATION + ++ DPAA2_RES /* dummy */+ 128 + mbuf->priv_size + mbuf->data_off); ++ DPAA2_SET_FD_ASAL(fd, DPAA2_ASAL_VAL); ++ ++ PMD_DRV_LOG(DEBUG, "\nmbuf %p BMAN buf addr %p", ++ (void *)mbuf, mbuf->buf_addr); ++ ++ PMD_DRV_LOG(DEBUG, "\nfdaddr =%lx bpid =%d meta =%d off =%d, len =%d\n", ++ DPAA2_GET_FD_ADDR(fd), ++ DPAA2_GET_FD_BPID(fd), ++ bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size, ++ DPAA2_GET_FD_OFFSET(fd), ++ DPAA2_GET_FD_LEN(fd)); ++ ++ return; ++} ++ ++static int eth_copy_mbuf_to_fd(struct rte_mbuf *mbuf, ++ struct qbman_fd *fd, uint16_t bpid) ++{ ++ struct rte_mbuf *m; ++ void *mb = NULL; ++ ++ if (hw_mbuf_alloc(bpid_info[bpid].bp_list->buf_pool.mp, &mb)) { ++ PMD_DRV_LOG(WARNING, "Unable to allocated DPAA2 buffer"); ++ rte_pktmbuf_free(mbuf); ++ return -1; ++ } ++ m = (struct rte_mbuf *)mb; ++ memcpy((char *)m->buf_addr + mbuf->data_off, ++ (void *)((char *)mbuf->buf_addr + mbuf->data_off), ++ mbuf->pkt_len); ++ ++ /*Resetting the buffer pool id and offset field*/ ++ fd->simple.bpid_offset = 0; ++ ++ DPAA2_SET_FD_ADDR(fd, m->buf_addr); ++ DPAA2_SET_FD_LEN(fd, mbuf->data_len); ++ DPAA2_SET_FD_BPID(fd, bpid); ++ DPAA2_SET_FD_OFFSET(fd, mbuf->data_off); ++ DPAA2_SET_FD_ASAL(fd, DPAA2_ASAL_VAL); ++ ++ PMD_DRV_LOG(DEBUG, "\nmbuf %p BMAN buf addr %p", ++ (void *)mbuf, mbuf->buf_addr); ++ ++ PMD_DRV_LOG(DEBUG, "\nfdaddr =%lx bpid =%d meta =%d off =%d, len =%d\n", ++ DPAA2_GET_FD_ADDR(fd), ++ DPAA2_GET_FD_BPID(fd), ++ bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size, ++ DPAA2_GET_FD_OFFSET(fd), ++ DPAA2_GET_FD_LEN(fd)); ++ /*free the original packet */ ++ rte_pktmbuf_free(mbuf); ++ ++ return 0; ++} ++ ++static uint16_t ++eth_dpaa2_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) ++{ ++ /* Function is responsible to receive frames for a given device and VQ*/ ++ struct dpaa2_queue *dpaa2_q = (struct dpaa2_queue *)queue; ++ struct qbman_result *dq_storage; ++ uint32_t fqid = dpaa2_q->fqid; ++ int ret, num_rx = 0; ++ uint8_t is_last = 0, status; ++ struct qbman_swp *swp; ++ const struct qbman_fd *fd; ++ struct qbman_pull_desc pulldesc; ++ struct rte_eth_dev *dev = dpaa2_q->dev; ++ ++ if (!thread_io_info.dpio_dev) { ++ ret = dpaa2_affine_qbman_swp(); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Failure in affining portal\n"); ++ return 0; ++ } ++ } ++ swp = thread_io_info.dpio_dev->sw_portal; ++ dq_storage = dpaa2_q->q_storage->dq_storage[0]; ++ ++ qbman_pull_desc_clear(&pulldesc); ++ qbman_pull_desc_set_numframes(&pulldesc, nb_pkts); ++ qbman_pull_desc_set_fq(&pulldesc, fqid); ++ /* todo optimization - we can have dq_storage_phys available*/ ++ qbman_pull_desc_set_storage(&pulldesc, dq_storage, ++ (dma_addr_t)(DPAA2_VADDR_TO_IOVA(dq_storage)), 1); ++ ++ /*Issue a volatile dequeue command. */ ++ while (1) { ++ if (qbman_swp_pull(swp, &pulldesc)) { ++ PMD_DRV_LOG(ERR, "VDQ command is not issued." ++ "QBMAN is busy\n"); ++ /* Portal was busy, try again */ ++ continue; ++ } ++ break; ++ }; ++ ++ /* Receive the packets till Last Dequeue entry is found with ++ respect to the above issues PULL command. ++ */ ++ while (!is_last) { ++ /*Check if the previous issued command is completed. ++ *Also seems like the SWP is shared between the Ethernet Driver ++ *and the SEC driver.*/ ++ while(!qbman_check_command_complete(swp, dq_storage)) ++ ; ++ /* Loop until the dq_storage is updated with ++ * new token by QBMAN */ ++ while (!qbman_result_has_new_result(swp, dq_storage)) ++ ; ++ /* Check whether Last Pull command is Expired and ++ setting Condition for Loop termination */ ++ if (qbman_result_DQ_is_pull_complete(dq_storage)) { ++ is_last = 1; ++ /* Check for valid frame. */ ++ status = (uint8_t)qbman_result_DQ_flags(dq_storage); ++ if (unlikely((status & QBMAN_DQ_STAT_VALIDFRAME) == 0)) { ++ PMD_DRV_LOG(DEBUG, "No frame is delivered\n"); ++ continue; ++ } ++ } ++ ++ fd = qbman_result_DQ_fd(dq_storage); ++ bufs[num_rx] = eth_fd_to_mbuf(fd); ++ bufs[num_rx]->port = dev->data->port_id; ++ ++ num_rx++; ++ dq_storage++; ++ } /* End of Packet Rx loop */ ++ ++ dpaa2_q->rx_pkts += num_rx; ++ ++ PMD_DRV_LOG(INFO, "Ethernet Received %d Packets\n", num_rx); ++ /*Return the total number of packets received to DPAA2 app*/ ++ return num_rx; ++} ++ ++static uint16_t ++eth_dpaa2_prefetch_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) ++{ ++ /* Function is responsible to receive frames for a given device and VQ*/ ++ struct dpaa2_queue *dpaa2_q = (struct dpaa2_queue *)queue; ++ struct qbman_result *dq_storage; ++ uint32_t fqid = dpaa2_q->fqid; ++ int ret, i, num_rx = 0; ++ uint8_t is_last = 0, status; ++ struct qbman_swp *swp; ++ const struct qbman_fd *fd[16]; ++ struct qbman_pull_desc pulldesc; ++ struct queue_storage_info_t *q_storage = dpaa2_q->q_storage; ++ struct rte_eth_dev *dev = dpaa2_q->dev; ++ ++ if(!thread_io_info.dpio_dev) { ++ ret = dpaa2_affine_qbman_swp(); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Failure in affining portal\n"); ++ return 0; ++ } ++ } ++ swp = thread_io_info.dpio_dev->sw_portal; ++ ++ if(!q_storage->active_dqs) { ++ q_storage->toggle = 0; ++ dq_storage = q_storage->dq_storage[q_storage->toggle]; ++ qbman_pull_desc_clear(&pulldesc); ++ qbman_pull_desc_set_numframes(&pulldesc, nb_pkts); ++ qbman_pull_desc_set_fq(&pulldesc, fqid); ++ qbman_pull_desc_set_storage(&pulldesc, dq_storage, ++ (dma_addr_t)(DPAA2_VADDR_TO_IOVA(dq_storage)), 1); ++ if(thread_io_info.global_active_dqs) { ++ while(!qbman_check_command_complete(swp, thread_io_info.global_active_dqs)) ++ ; ++ } ++ while (1) { ++ if (qbman_swp_pull(swp, &pulldesc)) { ++ PMD_DRV_LOG(WARNING, "VDQ command is not issued." ++ "QBMAN is busy\n"); ++ /* Portal was busy, try again */ ++ continue; ++ } ++ break; ++ } ++ q_storage->active_dqs = dq_storage; ++ thread_io_info.global_active_dqs = dq_storage; ++ } ++ while(!qbman_check_command_complete(swp, thread_io_info.global_active_dqs)) ++ ; ++ dq_storage = q_storage->active_dqs; ++ while (!is_last) { ++ /* Loop until the dq_storage is updated with ++ * new token by QBMAN */ ++ struct rte_mbuf *mbuf; ++ ++ while (!qbman_result_has_new_result(swp, dq_storage)) ++ ; ++ rte_prefetch0((void *)((uint64_t)(dq_storage + 1))); ++ /* Check whether Last Pull command is Expired and ++ setting Condition for Loop termination */ ++ if (qbman_result_DQ_is_pull_complete(dq_storage)) { ++ is_last = 1; ++ /* Check for valid frame. */ ++ status = (uint8_t)qbman_result_DQ_flags(dq_storage); ++ if (unlikely((status & QBMAN_DQ_STAT_VALIDFRAME) == 0)) { ++ PMD_DRV_LOG(DEBUG, "No frame is delivered\n"); ++ continue; ++ } ++ } ++ fd[num_rx] = qbman_result_DQ_fd(dq_storage); ++ mbuf = DPAA2_INLINE_MBUF_FROM_BUF(DPAA2_GET_FD_ADDR(fd[num_rx])); ++ /* Prefeth mbuf */ ++ rte_prefetch0(mbuf); ++ /* Prefetch Annotation address from where we get parse results */ ++ rte_prefetch0((void *)((uint64_t)DPAA2_GET_FD_ADDR(fd[num_rx]) + DPAA2_FD_PTA_SIZE + 16)); ++ /*Prefetch Data buffer*/ ++ /* rte_prefetch0((void *)((uint64_t)DPAA2_GET_FD_ADDR(fd[num_rx]) + DPAA2_GET_FD_OFFSET(fd[num_rx]))); */ ++ dq_storage++; ++ num_rx++; ++ ++ } /* End of Packet Rx loop */ ++ ++ for (i = 0; i < num_rx; i++) { ++ bufs[i] = eth_fd_to_mbuf(fd[i]); ++ bufs[i]->port = dev->data->port_id; ++ } ++ ++ q_storage->toggle ^= 1; ++ dq_storage = q_storage->dq_storage[q_storage->toggle]; ++ qbman_pull_desc_clear(&pulldesc); ++ qbman_pull_desc_set_numframes(&pulldesc, nb_pkts); ++ qbman_pull_desc_set_fq(&pulldesc, fqid); ++ qbman_pull_desc_set_storage(&pulldesc, dq_storage, ++ (dma_addr_t)(DPAA2_VADDR_TO_IOVA(dq_storage)), 1); ++ /*Issue a volatile dequeue command. */ ++ ++ while (1) { ++ if (qbman_swp_pull(swp, &pulldesc)) { ++ PMD_DRV_LOG(WARNING, "VDQ command is not issued." ++ "QBMAN is busy\n"); ++ continue; ++ } ++ break; ++ } ++ q_storage->active_dqs = dq_storage; ++ thread_io_info.global_active_dqs = dq_storage; ++ ++ dpaa2_q->rx_pkts += num_rx; ++ ++ PMD_DRV_LOG(INFO, "Ethernet Received %d Packets\n", num_rx); ++ /*Return the total number of packets received to DPAA2 app*/ ++ return num_rx; ++} ++ ++/* ++ * Callback to handle sending packets through a real NIC. ++ */ ++static uint16_t ++eth_dpaa2_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) ++{ ++ /* Function to transmit the frames to given device and VQ*/ ++ uint32_t loop; ++ int32_t ret; ++#ifdef QBMAN_MULTI_TX ++ struct qbman_fd fd_arr[8]; ++ uint32_t frames_to_send; ++#else ++ struct qbman_fd fd; ++#endif ++ struct rte_mempool *mp; ++ struct qbman_eq_desc eqdesc; ++ struct dpaa2_queue *dpaa2_q = (struct dpaa2_queue *)queue; ++ struct qbman_swp *swp; ++ uint16_t num_tx = 0; ++ /*todo - need to support multiple buffer pools */ ++ uint16_t bpid; ++ struct rte_eth_dev *dev = dpaa2_q->dev; ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ ++ if (!thread_io_info.dpio_dev) { ++ ret = dpaa2_affine_qbman_swp(); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Failure in affining portal\n"); ++ return 0; ++ } ++ } ++ swp = thread_io_info.dpio_dev->sw_portal; ++ ++ /*Prepare enqueue descriptor*/ ++ qbman_eq_desc_clear(&eqdesc); ++ qbman_eq_desc_set_no_orp(&eqdesc, DPAA2_EQ_RESP_ERR_FQ); ++ qbman_eq_desc_set_response(&eqdesc, 0, 0); ++ qbman_eq_desc_set_qd(&eqdesc, priv->qdid, ++ dpaa2_q->flow_id, dpaa2_q->tc_index); ++ ++ /*Clear the unused FD fields before sending*/ ++#ifdef QBMAN_MULTI_TX ++ while(nb_pkts) { ++ /*Check if the queue is congested*/ ++ if(qbman_result_is_CSCN(dpaa2_q->cscn)) ++ goto skip_tx; ++ ++ frames_to_send = (nb_pkts >> 3) ? MAX_SLOTS : nb_pkts; ++ ++ for(loop = 0; loop < frames_to_send; loop++) { ++ fd_arr[loop].simple.frc = 0; ++ DPAA2_RESET_FD_CTRL((&fd_arr[loop])); ++ DPAA2_SET_FD_FLC((&fd_arr[loop]), NULL); ++ mp = (*bufs)->pool; ++ /* Not a hw_pkt pool allocated frame */ ++ if (mp && !(mp->flags & MEMPOOL_F_HW_PKT_POOL)) { ++ printf ("\n non hw offload bufffer "); ++ /* alloc should be from the default buffer pool ++ attached to this interface */ ++ bpid = priv->bp_list->buf_pool.bpid; ++ if (eth_copy_mbuf_to_fd(*bufs, &fd_arr[loop], bpid)) { ++ bufs++; ++ continue; ++ } ++ } else { ++ bpid = mp->offload_ptr; ++ eth_mbuf_to_fd(*bufs, &fd_arr[loop], bpid); ++ } ++ bufs++; ++ } ++ loop = 0; ++ while(loop < frames_to_send) { ++ loop += qbman_swp_send_multiple(swp, &eqdesc, ++ &fd_arr[loop], frames_to_send - loop); ++ } ++ ++ num_tx += frames_to_send; ++ dpaa2_q->tx_pkts += frames_to_send; ++ nb_pkts -= frames_to_send; ++ } ++#else ++ /*Check if the queue is congested*/ ++// if(qbman_result_is_CSCN(dpaa2_q->cscn)) ++// goto skip_tx; ++ ++ fd.simple.frc = 0; ++ DPAA2_RESET_FD_CTRL((&fd)); ++ DPAA2_SET_FD_FLC((&fd), NULL); ++ loop = 0; ++ ++ while (loop < nb_pkts) { ++ /*Prepare each packet which is to be sent*/ ++ mp = bufs[loop]->pool; ++ /* Not a hw_pkt pool allocated frame */ ++ if (mp && !(mp->flags & MEMPOOL_F_HW_PKT_POOL)) { ++ printf ("\n non hw offload bufffer "); ++ /* alloc should be from the default buffer pool ++ attached to this interface */ ++ if (priv->bp_list) ++ bpid = priv->bp_list->buf_pool.bpid; ++ else ++ printf("\n ??? why no bpool attached"); ++ ++ if (eth_copy_mbuf_to_fd(bufs[loop], &fd, bpid)) { ++ loop++; ++ continue; ++ } ++ } else { ++ bpid = mp->offload_ptr; ++ eth_mbuf_to_fd(bufs[loop], &fd, bpid); ++ } ++ /*Enqueue a single packet to the QBMAN*/ ++ do { ++ ret = qbman_swp_enqueue(swp, &eqdesc, &fd); ++ if (ret != 0) { ++ PMD_DRV_LOG(DEBUG, "Error in transmiting the frame\n"); ++ } ++ } while (ret != 0); ++ ++ /* Free the buffer shell */ ++ /* rte_pktmbuf_free(bufs[loop]); */ ++ num_tx++; loop++; ++ } ++ dpaa2_q->tx_pkts += num_tx; ++ dpaa2_q->err_pkts += nb_pkts - num_tx; ++#endif ++ skip_tx: ++ return num_tx; ++} ++ ++static int ++dpaa2_vlan_stripping_set(struct rte_eth_dev *dev, int on) ++{ ++ int ret; ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ ++ PMD_INIT_FUNC_TRACE(); ++ ++ if (dpni == NULL) { ++ PMD_DRV_LOG(ERR, "dpni is NULL"); ++ return -1; ++ } ++ ++ ret = dpni_set_vlan_removal(dpni, CMD_PRI_LOW, priv->token, on); ++ if (ret < 0) ++ PMD_DRV_LOG(ERR, "Unable to dpni_set_vlan_removal hwid =%d", ++ priv->hw_id); ++ return ret; ++} ++ ++static int ++dpaa2_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) ++{ ++ int ret; ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ ++ if (dpni == NULL) { ++ PMD_DRV_LOG(ERR, "dpni is NULL"); ++ return -1; ++ } ++ ++ if (on) ++ ret = dpni_add_vlan_id(dpni, CMD_PRI_LOW, priv->token, vlan_id); ++ else ++ ret = dpni_remove_vlan_id(dpni, CMD_PRI_LOW, priv->token, vlan_id); ++ ++ if (ret < 0) ++ PMD_DRV_LOG(ERR, "ret = %d Unable to add/rem vlan %d hwid =%d", ++ ret, vlan_id, priv->hw_id); ++ ++ /*todo this should on global basis */ ++/* ret = dpni_set_vlan_filters(dpni, CMD_PRI_LOW, priv->token, on); ++ if (ret < 0) ++ PMD_DRV_LOG(ERR, "Unable to set vlan filter"); ++*/ return ret; ++} ++ ++static void ++dpaa2_vlan_offload_set(struct rte_eth_dev *dev, int mask) ++{ ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ int ret; ++ if (mask & ETH_VLAN_FILTER_MASK) { ++ if (dev->data->dev_conf.rxmode.hw_vlan_filter) ++ ret = dpni_set_vlan_filters(dpni, CMD_PRI_LOW, priv->token, TRUE); ++ else ++ ret = dpni_set_vlan_filters(dpni, CMD_PRI_LOW, priv->token, FALSE); ++ if (ret < 0) ++ PMD_DRV_LOG(ERR, "ret = %d Unable to set vlan filter", ret); ++ } ++ ++ if (mask & ETH_VLAN_STRIP_MASK) { ++ /* Enable or disable VLAN stripping */ ++ if (dev->data->dev_conf.rxmode.hw_vlan_strip) ++ dpaa2_vlan_stripping_set(dev, TRUE); ++ else ++ dpaa2_vlan_stripping_set(dev, FALSE); ++ } ++ ++ if (mask & ETH_VLAN_EXTEND_MASK) { ++ PMD_INIT_FUNC_TRACE(); ++/* if (dev->data->dev_conf.rxmode.hw_vlan_extend) ++ i40e_vsi_config_double_vlan(vsi, TRUE); ++ else ++ i40e_vsi_config_double_vlan(vsi, FALSE); ++*/ } ++} ++ ++static void ++dpaa2_eth_dev_info(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) ++{ ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ ++ dev_info->driver_name = drivername; ++ dev_info->if_index = priv->hw_id; ++ dev_info->max_mac_addrs = priv->max_unicast_filters; ++ dev_info->max_rx_pktlen = (uint32_t)-1; ++ dev_info->max_rx_queues = (uint16_t)priv->nb_rx_queues; ++ dev_info->max_tx_queues = (uint16_t)priv->nb_tx_queues; ++ dev_info->min_rx_bufsize = 0; ++ dev_info->pci_dev = dev->pci_dev; ++/* dev_info->rx_offload_capa = ++ DEV_RX_OFFLOAD_IPV4_CKSUM | ++ DEV_RX_OFFLOAD_UDP_CKSUM | ++ DEV_RX_OFFLOAD_TCP_CKSUM; ++ dev_info->tx_offload_capa = ++ DEV_TX_OFFLOAD_IPV4_CKSUM | ++ DEV_TX_OFFLOAD_UDP_CKSUM | ++ DEV_TX_OFFLOAD_TCP_CKSUM | ++ DEV_TX_OFFLOAD_SCTP_CKSUM; ++*/ ++} ++ ++static int ++dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) ++{ ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ uint8_t tc_idx; ++ uint16_t dist_idx; ++ uint32_t vq_id; ++ struct dpaa2_queue *mc_q, *mcq; ++ uint32_t tot_queues; ++ int i; ++ struct dpaa2_queue *dpaa2_q; ++ tot_queues = priv->nb_rx_queues + priv->nb_tx_queues; ++ mc_q = rte_malloc(NULL, sizeof(struct dpaa2_queue) * tot_queues, ++ RTE_CACHE_LINE_SIZE); ++ if (!mc_q) { ++ PMD_DRV_LOG(ERR, "malloc failed for rx/tx queues\n"); ++ return -1; ++ } ++ ++ for (i = 0; i < priv->nb_rx_queues; i++) { ++ mc_q->dev = dev; ++ priv->rx_vq[i] = mc_q++; ++ dpaa2_q = (struct dpaa2_queue *)priv->rx_vq[i]; ++ dpaa2_q->q_storage = rte_malloc("dq_storage", ++ sizeof(struct queue_storage_info_t), ++ RTE_CACHE_LINE_SIZE); ++ if(!dpaa2_q->q_storage) ++ goto fail; ++ ++ memset(dpaa2_q->q_storage, 0, sizeof(struct queue_storage_info_t)); ++ } ++ ++ for (i = 0; i < priv->nb_tx_queues; i++) { ++ mc_q->dev = dev; ++ priv->tx_vq[i] = mc_q++; ++ } ++ ++ vq_id = 0; ++ for (tc_idx = 0; tc_idx < priv->num_tc; tc_idx++) { ++ for (dist_idx = 0; dist_idx < priv->num_dist_per_tc[tc_idx]; dist_idx++) { ++ mcq = (struct dpaa2_queue *)priv->rx_vq[vq_id]; ++ mcq->tc_index = tc_idx; ++ mcq->flow_id = dist_idx; ++ vq_id++; ++ } ++ } ++ ++ return 0; ++fail: ++ i -= 1; ++ while(i >= 0) ++ { ++ dpaa2_q = (struct dpaa2_queue *)priv->rx_vq[i]; ++ rte_free(dpaa2_q->q_storage); ++ } ++ return -1; ++} ++ ++static void dpaa2_distset_to_dpkg_profile_cfg( ++ uint32_t req_dist_set, ++ struct dpkg_profile_cfg *kg_cfg) ++{ ++ uint32_t loop = 0, i = 0, dist_field = 0; ++ int l2_configured = 0, l3_configured = 0; ++ int l4_configured = 0, sctp_configured = 0; ++ ++ memset(kg_cfg, 0, sizeof(struct dpkg_profile_cfg)); ++ while (req_dist_set) { ++ if (req_dist_set % 2 != 0) { ++ dist_field = 1U << loop; ++ switch (dist_field) { ++ case ETH_RSS_L2_PAYLOAD: ++ ++ if (l2_configured) ++ break; ++ l2_configured = 1; ++ ++ kg_cfg->extracts[i].extract.from_hdr.prot = ++ NET_PROT_ETH; ++ kg_cfg->extracts[i].extract.from_hdr.field = ++ NH_FLD_ETH_TYPE; ++ kg_cfg->extracts[i].type = DPKG_EXTRACT_FROM_HDR; ++ kg_cfg->extracts[i].extract.from_hdr.type = ++ DPKG_FULL_FIELD; ++ i++; ++ break; ++ ++ case ETH_RSS_IPV4: ++ case ETH_RSS_FRAG_IPV4: ++ case ETH_RSS_NONFRAG_IPV4_OTHER: ++ case ETH_RSS_IPV6: ++ case ETH_RSS_FRAG_IPV6: ++ case ETH_RSS_NONFRAG_IPV6_OTHER: ++ case ETH_RSS_IPV6_EX: ++ ++ if (l3_configured) ++ break; ++ l3_configured = 1; ++ ++ kg_cfg->extracts[i].extract.from_hdr.prot = ++ NET_PROT_IP; ++ kg_cfg->extracts[i].extract.from_hdr.field = ++ NH_FLD_IP_SRC; ++ kg_cfg->extracts[i].type = DPKG_EXTRACT_FROM_HDR; ++ kg_cfg->extracts[i].extract.from_hdr.type = ++ DPKG_FULL_FIELD; ++ i++; ++ ++ kg_cfg->extracts[i].extract.from_hdr.prot = ++ NET_PROT_IP; ++ kg_cfg->extracts[i].extract.from_hdr.field = ++ NH_FLD_IP_DST; ++ kg_cfg->extracts[i].type = DPKG_EXTRACT_FROM_HDR; ++ kg_cfg->extracts[i].extract.from_hdr.type = ++ DPKG_FULL_FIELD; ++ i++; ++ ++ kg_cfg->extracts[i].extract.from_hdr.prot = ++ NET_PROT_IP; ++ kg_cfg->extracts[i].extract.from_hdr.field = ++ NH_FLD_IP_PROTO; ++ kg_cfg->extracts[i].type = DPKG_EXTRACT_FROM_HDR; ++ kg_cfg->extracts[i].extract.from_hdr.type = ++ DPKG_FULL_FIELD; ++ kg_cfg->num_extracts++; ++ i++; ++ break; ++ ++ case ETH_RSS_NONFRAG_IPV4_TCP: ++ case ETH_RSS_NONFRAG_IPV6_TCP: ++ case ETH_RSS_NONFRAG_IPV4_UDP: ++ case ETH_RSS_NONFRAG_IPV6_UDP: ++ ++ if (l4_configured) ++ break; ++ l4_configured = 1; ++ ++ kg_cfg->extracts[i].extract.from_hdr.prot = ++ NET_PROT_TCP; ++ kg_cfg->extracts[i].extract.from_hdr.field = ++ NH_FLD_TCP_PORT_SRC; ++ kg_cfg->extracts[i].type = DPKG_EXTRACT_FROM_HDR; ++ kg_cfg->extracts[i].extract.from_hdr.type = ++ DPKG_FULL_FIELD; ++ i++; ++ ++ kg_cfg->extracts[i].extract.from_hdr.prot = ++ NET_PROT_TCP; ++ kg_cfg->extracts[i].extract.from_hdr.field = ++ NH_FLD_TCP_PORT_SRC; ++ kg_cfg->extracts[i].type = DPKG_EXTRACT_FROM_HDR; ++ kg_cfg->extracts[i].extract.from_hdr.type = ++ DPKG_FULL_FIELD; ++ i++; ++ break; ++ ++ case ETH_RSS_NONFRAG_IPV4_SCTP: ++ case ETH_RSS_NONFRAG_IPV6_SCTP: ++ ++ if (sctp_configured) ++ break; ++ sctp_configured = 1; ++ ++ kg_cfg->extracts[i].extract.from_hdr.prot = ++ NET_PROT_SCTP; ++ kg_cfg->extracts[i].extract.from_hdr.field = ++ NH_FLD_SCTP_PORT_SRC; ++ kg_cfg->extracts[i].type = DPKG_EXTRACT_FROM_HDR; ++ kg_cfg->extracts[i].extract.from_hdr.type = ++ DPKG_FULL_FIELD; ++ i++; ++ ++ kg_cfg->extracts[i].extract.from_hdr.prot = ++ NET_PROT_SCTP; ++ kg_cfg->extracts[i].extract.from_hdr.field = ++ NH_FLD_SCTP_PORT_DST; ++ kg_cfg->extracts[i].type = DPKG_EXTRACT_FROM_HDR; ++ kg_cfg->extracts[i].extract.from_hdr.type = ++ DPKG_FULL_FIELD; ++ i++; ++ break; ++ ++ default: ++ PMD_DRV_LOG(WARNING, "Bad flow distribution option %x\n", dist_field); ++ } ++ } ++ req_dist_set = req_dist_set >> 1; ++ loop++; ++ } ++ kg_cfg->num_extracts = i; ++} ++ ++static int dpaa2_setup_flow_distribution(struct rte_eth_dev *eth_dev, ++ uint32_t req_dist_set) ++{ ++ struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; ++ struct fsl_mc_io *dpni = priv->hw; ++ struct dpni_rx_tc_dist_cfg tc_cfg; ++ struct dpkg_profile_cfg kg_cfg; ++ void *p_params; ++ int ret, tc_index = 0; ++ ++ p_params = rte_malloc( ++ NULL, DIST_PARAM_IOVA_SIZE, RTE_CACHE_LINE_SIZE); ++ if (!p_params) { ++ PMD_DRV_LOG(ERR, "Memory unavaialble\n"); ++ return -ENOMEM; ++ } ++ memset(p_params, 0, DIST_PARAM_IOVA_SIZE); ++ memset(&tc_cfg, 0, sizeof(struct dpni_rx_tc_dist_cfg)); ++ ++ dpaa2_distset_to_dpkg_profile_cfg(req_dist_set, &kg_cfg); ++ tc_cfg.key_cfg_iova = (uint64_t)(DPAA2_VADDR_TO_IOVA(p_params)); ++ tc_cfg.dist_size = eth_dev->data->nb_rx_queues; ++ tc_cfg.dist_mode = DPNI_DIST_MODE_HASH; ++ ++ ret = dpni_prepare_key_cfg(&kg_cfg, p_params); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Unable to prepare extract parameters\n"); ++ rte_free(p_params); ++ return ret; ++ } ++ ++ ret = dpni_set_rx_tc_dist(dpni, CMD_PRI_LOW, priv->token, tc_index, ++ &tc_cfg); ++ rte_free(p_params); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Setting distribution for Rx failed with" ++ "err code: %d\n", ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int ++dpaa2_remove_flow_distribution(struct rte_eth_dev *eth_dev, uint8_t tc_index) ++{ ++ struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; ++ struct fsl_mc_io *dpni = priv->hw; ++ struct dpni_rx_tc_dist_cfg tc_cfg; ++ struct dpkg_profile_cfg kg_cfg; ++ void *p_params; ++ int ret; ++ ++ p_params = rte_malloc( ++ NULL, DIST_PARAM_IOVA_SIZE, RTE_CACHE_LINE_SIZE); ++ if (!p_params) { ++ PMD_DRV_LOG(ERR, "Memory unavaialble\n"); ++ return -ENOMEM; ++ } ++ memset(p_params, 0, DIST_PARAM_IOVA_SIZE); ++ memset(&tc_cfg, 0, sizeof(struct dpni_rx_tc_dist_cfg)); ++ ++ tc_cfg.key_cfg_iova = (uint64_t)(DPAA2_VADDR_TO_IOVA(p_params)); ++ tc_cfg.dist_size = 0; ++ tc_cfg.dist_mode = DPNI_DIST_MODE_NONE; ++ ++ ret = dpni_prepare_key_cfg(&kg_cfg, p_params); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Unable to prepare extract parameters\n"); ++ rte_free(p_params); ++ return ret; ++ } ++ ++ ret = dpni_set_rx_tc_dist(dpni, CMD_PRI_LOW, priv->token, tc_index, ++ &tc_cfg); ++ rte_free(p_params); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Setting distribution for Rx failed with" ++ "err code: %d\n", ret); ++ return ret; ++ } ++ return ret; ++} ++ ++static int ++dpaa2_alloc_dq_storage(struct queue_storage_info_t *q_storage) ++{ ++ int i=0; ++ ++ for(i = 0;i < NUM_DQS_PER_QUEUE; i++) { ++ q_storage->dq_storage[i] = rte_malloc(NULL, ++ NUM_MAX_RECV_FRAMES * sizeof(struct qbman_result), ++ RTE_CACHE_LINE_SIZE); ++ if(!q_storage->dq_storage[i]) ++ goto fail; ++ /*setting toggle for initial condition*/ ++ q_storage->toggle = -1; ++ } ++ return 0; ++fail: ++ i -= 1; ++ while(i >= 0) ++ { ++ rte_free(q_storage->dq_storage[i]); ++ } ++ return -1; ++} ++ ++static int ++dpaa2_eth_dev_configure(struct rte_eth_dev *dev) ++{ ++ struct rte_eth_dev_data *data = dev->data; ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct rte_eth_conf *eth_conf = &data->dev_conf; ++ struct dpaa2_queue *dpaa2_q; ++ int i, ret; ++ ++ for (i = 0; i < data->nb_rx_queues; i++) { ++ data->rx_queues[i] = priv->rx_vq[i]; ++ dpaa2_q = (struct dpaa2_queue *)data->rx_queues[i]; ++ if(dpaa2_alloc_dq_storage(dpaa2_q->q_storage)) ++ return -1; ++ } ++ ++ for (i = 0; i < data->nb_tx_queues; i++) { ++ data->tx_queues[i] = priv->tx_vq[i]; ++ dpaa2_q = (struct dpaa2_queue *)data->tx_queues[i]; ++ dpaa2_q->cscn = rte_malloc(NULL, sizeof(struct qbman_result), 16); ++ if(!dpaa2_q->cscn) ++ goto fail_tx_queue; ++ } ++ ++ /* Check for correct configuration */ ++ if (eth_conf->rxmode.mq_mode != ETH_MQ_RX_RSS && ++ data->nb_rx_queues > 1) { ++ PMD_DRV_LOG(ERR, "Distribution is not enabled, " ++ "but Rx queues more than 1\n"); ++ return -1; ++ } ++ ++ if (eth_conf->rxmode.mq_mode == ETH_MQ_RX_RSS) { ++ /* Return in case number of Rx queues is 1 */ ++ if (data->nb_rx_queues == 1) ++ return 0; ++ ret = dpaa2_setup_flow_distribution(dev, ++ eth_conf->rx_adv_conf.rss_conf.rss_hf); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "dpaa2_setup_flow_distribution failed\n"); ++ return ret; ++ } ++ } ++ ++ return 0; ++ fail_tx_queue: ++ i -= 1; ++ while(i >= 0) { ++ dpaa2_q = (struct dpaa2_queue *)data->tx_queues[i]; ++ rte_free(dpaa2_q->cscn); ++ } ++ return -1; ++} ++ ++static int dpaa2_attach_bp_list(struct dpaa2_dev_priv *priv, ++ void *blist) ++{ ++ /* Function to attach a DPNI with a buffer pool list. Buffer pool list ++ * handle is passed in blist. ++ */ ++ int32_t retcode; ++ struct fsl_mc_io *dpni = priv->hw; ++ struct dpni_pools_cfg bpool_cfg; ++ struct dpaa2_bp_list *bp_list = (struct dpaa2_bp_list *)blist; ++ ++ /*Attach buffer pool to the network interface as described by the user*/ ++ bpool_cfg.num_dpbp = 1; ++ bpool_cfg.pools[0].dpbp_id = bp_list->buf_pool.dpbp_node->dpbp_id; ++ bpool_cfg.pools[0].backup_pool = 0; ++ bpool_cfg.pools[0].buffer_size = ++ DPAA2_ALIGN_ROUNDUP(bp_list->buf_pool.size, ++ DPAA2_PACKET_LAYOUT_ALIGN);; ++ ++ retcode = dpni_set_pools(dpni, CMD_PRI_LOW, priv->token, &bpool_cfg); ++ if (retcode != 0) { ++ PMD_DRV_LOG(ERR, "Error in attaching the buffer pool list" ++ "bpid = %d Error code = %d\n", ++ bpool_cfg.pools[0].dpbp_id, retcode); ++ return retcode; ++ } ++ ++ priv->bp_list = bp_list; ++ return 0; ++} ++ ++/* Function to setup RX flow information. It contains traffic class ID, ++ * flow ID, destination configuration etc. ++ */ ++static int ++dpaa2_rx_queue_setup(struct rte_eth_dev *dev, ++ uint16_t rx_queue_id, ++ uint16_t nb_rx_desc __rte_unused, ++ unsigned int socket_id __rte_unused, ++ const struct rte_eth_rxconf *rx_conf __rte_unused, ++ struct rte_mempool *mb_pool) ++{ ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ struct dpaa2_queue *dpaa2_q; ++ struct dpni_queue_cfg cfg; ++ uint8_t tc_id, flow_id; ++ int ret; ++ ++ PMD_DRV_LOG(INFO, "\n dev =%p, queue =%d, pool = %p, conf =%p", ++ dev, rx_queue_id, mb_pool, rx_conf); ++ ++ if (!priv->bp_list) { ++ if (mb_pool->offload_ptr > MAX_BPID) { ++ printf ("\n ??? ERR - %s not a offloaded buffer pool", ++ __func__); ++ return -1; ++ } ++ ret = dpaa2_attach_bp_list(priv, ++ bpid_info[mb_pool->offload_ptr].bp_list); ++ if (ret) ++ return ret; ++ } ++ dpaa2_q = (struct dpaa2_queue *)dev->data->rx_queues[rx_queue_id]; ++ ++ /*Get the tc id and flow id from given VQ id*/ ++ tc_id = rx_queue_id / MAX_DIST_PER_TC; ++ flow_id = rx_queue_id % MAX_DIST_PER_TC; ++ memset(&cfg, 0, sizeof(struct dpni_queue_cfg)); ++ ++ cfg.options = cfg.options | DPNI_QUEUE_OPT_USER_CTX; ++ ++#ifdef DPAA2_STASHING ++ cfg.options = cfg.options | DPNI_QUEUE_OPT_FLC; ++#endif ++ ++ cfg.user_ctx = (uint64_t)(dpaa2_q); ++#ifdef DPAA2_STASHING ++ cfg.flc_cfg.flc_type = DPNI_FLC_STASH; ++ cfg.flc_cfg.frame_data_size = DPNI_STASH_SIZE_64B; ++ /* Enabling Annotation stashing */ ++ cfg.options |= DPNI_FLC_STASH_FRAME_ANNOTATION; ++ cfg.flc_cfg.options = DPNI_FLC_STASH_FRAME_ANNOTATION; ++#endif ++ ++ cfg.options = cfg.options | DPNI_QUEUE_OPT_TAILDROP_THRESHOLD; ++ cfg.tail_drop_threshold = 2048;// 16 packet ++ ++ ret = dpni_set_rx_flow(dpni, CMD_PRI_LOW, priv->token, ++ tc_id, flow_id, &cfg); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Error in setting the rx flow: = %d\n", ret); ++ return -1; ++ } ++ return 0; ++} ++ ++static int ++dpaa2_tx_queue_setup(struct rte_eth_dev *dev, ++ uint16_t tx_queue_id, ++ uint16_t nb_tx_desc __rte_unused, ++ unsigned int socket_id __rte_unused, ++ const struct rte_eth_txconf *tx_conf __rte_unused) ++{ ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct dpaa2_queue *dpaa2_q; ++ struct fsl_mc_io *dpni = priv->hw; ++ struct dpni_tx_flow_cfg cfg; ++ struct dpni_tx_conf_cfg tx_conf_cfg; ++#ifdef QBMAN_MULTI_TX ++ struct dpni_congestion_notification_cfg cong_notif_cfg; ++#endif ++ uint32_t tc_idx; ++ uint16_t flow_id = DPNI_NEW_FLOW_ID; ++ int ret; ++ ++ PMD_INIT_FUNC_TRACE(); ++ ++ memset(&cfg, 0, sizeof(struct dpni_tx_flow_cfg)); ++ cfg.l3_chksum_gen = 1; ++ cfg.options |= DPNI_TX_FLOW_OPT_L3_CHKSUM_GEN; ++ cfg.l4_chksum_gen = 1; ++ cfg.options = DPNI_TX_FLOW_OPT_L4_CHKSUM_GEN; ++ memset(&tx_conf_cfg, 0, sizeof(struct dpni_tx_conf_cfg)); ++ tx_conf_cfg.errors_only = TRUE; ++ ++ /* ++ if (action & DPAA2BUF_TX_CONF_REQUIRED) { ++ cfg.options = DPNI_TX_FLOW_OPT_TX_CONF_ERROR; ++ cfg.use_common_tx_conf_queue = ++ ((action & DPAA2BUF_TX_CONF_ERR_ON_COMMON_Q) ? ++ TRUE : FALSE); ++ tx_conf_cfg.errors_only = FALSE; ++ }*/ ++ ++ if (priv->num_tc == 1) ++ tc_idx = 0; ++ else ++ tc_idx = tx_queue_id; ++ ++ ret = dpni_set_tx_flow(dpni, CMD_PRI_LOW, priv->token, &flow_id, &cfg); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Error in setting the tx flow:" ++ "ErrorCode = %x\n", ret); ++ return -1; ++ } ++ /*Set tx-conf and error configuration*/ ++ ret = dpni_set_tx_conf(dpni, CMD_PRI_LOW, priv->token, ++ flow_id, &tx_conf_cfg); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Error in setting tx conf settings: " ++ "ErrorCode = %x", ret); ++ return -1; ++ } ++ ++ if (tx_queue_id == 0) { ++ /*Set tx-conf and error configuration*/ ++ ret = dpni_set_tx_conf(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_COMMON_TX_CONF, &tx_conf_cfg); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Error in setting tx conf settings: " ++ "ErrorCode = %x", ret); ++ return -1; ++ } ++ } ++ /*todo - add the queue id support instead of hard queue id as "0" */ ++ dpaa2_q = (struct dpaa2_queue *)dev->data->tx_queues[tx_queue_id]; ++ dpaa2_q->tc_index = tc_idx; ++ if (flow_id == DPNI_NEW_FLOW_ID) ++ dpaa2_q->flow_id = 0; ++ else ++ dpaa2_q->flow_id = flow_id; ++ ++#ifdef QBMAN_MULTI_TX ++ cong_notif_cfg.units = DPNI_CONGESTION_UNIT_BYTES; ++ /*Notify about congestion when the queue size is 128 frames with each \ ++ frame 64 bytes size*/ ++ cong_notif_cfg.threshold_entry = CONG_ENTER_THRESHOLD; ++ /*Notify that the queue is not congested when the number of frames in \ ++ the queue is below this thershold. ++ TODO: Check if this value is the optimum value for better performance*/ ++ cong_notif_cfg.threshold_exit = CONG_EXIT_THRESHOLD; ++ cong_notif_cfg.message_ctx = 0; ++ cong_notif_cfg.message_iova = (uint64_t)dpaa2_q->cscn; ++ cong_notif_cfg.dest_cfg.dest_type = DPNI_DEST_NONE; ++ cong_notif_cfg.options = DPNI_CONG_OPT_WRITE_MEM_ON_ENTER | ++ DPNI_CONG_OPT_WRITE_MEM_ON_EXIT | DPNI_CONG_OPT_COHERENT_WRITE; ++ ++ ret = dpni_set_tx_tc_congestion_notification(dpni, CMD_PRI_LOW, ++ priv->token, ++ tc_idx, &cong_notif_cfg); ++ if(ret) { ++ PMD_DRV_LOG(ERR, "Error in setting tx congestion notification " ++ "settings: ErrorCode = %x", ret); ++ return -1; ++ } ++#endif ++ return 0; ++} ++ ++static const uint32_t * ++dpaa2_supported_ptypes_get(struct rte_eth_dev *dev) ++{ ++ static const uint32_t ptypes[] = { ++ /*todo -= add more types */ ++ RTE_PTYPE_L2_ETHER, ++ RTE_PTYPE_L3_IPV4, ++ RTE_PTYPE_L3_IPV4_EXT, ++ RTE_PTYPE_L3_IPV6, ++ RTE_PTYPE_L3_IPV6_EXT, ++ RTE_PTYPE_L4_TCP, ++ RTE_PTYPE_L4_UDP, ++ RTE_PTYPE_L4_SCTP, ++ RTE_PTYPE_L4_ICMP, ++ RTE_PTYPE_UNKNOWN ++ }; ++ ++ if (dev->rx_pkt_burst == eth_dpaa2_prefetch_rx || ++ dev->rx_pkt_burst == eth_dpaa2_rx) ++ return ptypes; ++ return NULL; ++} ++ ++static int ++dpaa2_dev_start(struct rte_eth_dev *dev) ++{ ++ struct rte_eth_dev_data *data = dev->data; ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ struct dpni_queue_attr cfg; ++ uint16_t qdid; ++ struct dpaa2_queue *dpaa2_q; ++ int ret, i, mask = 0; ++ ++ PMD_INIT_FUNC_TRACE(); ++ ++ dev->data->dev_link.link_status = 1; ++ ++ ret = dpni_enable(dpni, CMD_PRI_LOW, priv->token); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Failure %d in enabling dpni %d device\n", ++ ret, priv->hw_id); ++ return ret; ++ } ++ ++ ret = dpni_get_qdid(dpni, CMD_PRI_LOW, priv->token, &qdid); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Error to get qdid:ErrorCode = %d\n", ret); ++ return ret; ++ } ++ priv->qdid = qdid; ++ ++ for (i = 0; i < data->nb_rx_queues; i++) { ++ dpaa2_q = (struct dpaa2_queue *)data->rx_queues[i]; ++ ret = dpni_get_rx_flow(dpni, CMD_PRI_LOW, priv->token, ++ dpaa2_q->tc_index, dpaa2_q->flow_id, &cfg); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Error to get flow " ++ "information Error code = %d\n", ret); ++ return ret; ++ } ++ dpaa2_q->fqid = cfg.fqid; ++ } ++ /* ++ * VLAN Offload Settings ++ */ ++ if (priv->options & DPNI_OPT_VLAN_FILTER) ++ mask = ETH_VLAN_FILTER_MASK; ++ ++ if (priv->options & DPNI_OPT_VLAN_MANIPULATION) ++ mask = ETH_VLAN_STRIP_MASK; ++ ++ if (mask) ++ dpaa2_vlan_offload_set(dev, mask); ++ ++ return 0; ++} ++ ++/********************************************************************* ++ * ++ * This routine disables all traffic on the adapter by issuing a ++ * global reset on the MAC. ++ * ++ **********************************************************************/ ++static void ++dpaa2_dev_stop(struct rte_eth_dev *dev) ++{ ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ int ret; ++ struct rte_eth_link link; ++ ++ dev->data->dev_link.link_status = 0; ++ ++ ret = dpni_disable(dpni, CMD_PRI_LOW, priv->token); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Failure in disabling dpni %d device\n", priv->hw_id); ++ return; ++ } ++ ++ /* clear the recorded link status */ ++ memset(&link, 0, sizeof(link)); ++ rte_dpni_dev_atomic_write_link_status(dev, &link); ++} ++ ++static void ++dpaa2_dev_close(struct rte_eth_dev *dev) ++{ ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ int ret; ++ struct rte_eth_link link; ++ ++ /*Function is reverse of dpaa2_dev_init. ++ * It does the following: ++ * 1. Detach a DPNI from attached resources i.e. buffer pools, dpbp_id. ++ * 2. Close the DPNI device ++ * 3. Free the allocated reqources. ++ */ ++ ++ /* Clean the device first */ ++ ret = dpni_reset(dpni, CMD_PRI_LOW, priv->token); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Failure cleaning dpni device with" ++ "error code %d\n", ret); ++ return; ++ } ++ ++ /*Close the device at underlying layer*/ ++ ret = dpni_close(dpni, CMD_PRI_LOW, priv->token); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Failure closing dpni device with" ++ "error code %d\n", ret); ++ return; ++ } ++ ++ /*Free the allocated memory for ethernet private data and dpni*/ ++ priv->hw = NULL; ++ free(dpni); ++ ++ memset(&link, 0, sizeof(link)); ++ rte_dpni_dev_atomic_write_link_status(dev, &link); ++} ++ ++static void ++dpaa2_dev_promiscuous_enable( ++ struct rte_eth_dev *dev) ++{ ++ int ret; ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ ++ if (dpni == NULL) { ++ PMD_DRV_LOG(ERR, "dpni is NULL"); ++ return; ++ } ++ ++ ret = dpni_set_unicast_promisc(dpni, CMD_PRI_LOW, priv->token, TRUE); ++ if (ret < 0) ++ PMD_DRV_LOG(ERR, "Unable to enable promiscuous mode"); ++ return; ++} ++ ++static void ++dpaa2_dev_promiscuous_disable( ++ struct rte_eth_dev *dev) ++{ ++ int ret; ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ ++ if (dpni == NULL) { ++ PMD_DRV_LOG(ERR, "dpni is NULL"); ++ return; ++ } ++ ++ ret = dpni_set_unicast_promisc(dpni, CMD_PRI_LOW, priv->token, FALSE); ++ if (ret < 0) ++ PMD_DRV_LOG(ERR, "Unable to disable promiscuous mode"); ++ return; ++} ++ ++static void ++dpaa2_dev_allmulticast_enable( ++ struct rte_eth_dev *dev) ++{ ++ int ret; ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ ++ if (dpni == NULL) { ++ PMD_DRV_LOG(ERR, "dpni is NULL"); ++ return; ++ } ++ ++ ret = dpni_set_multicast_promisc(dpni, CMD_PRI_LOW, priv->token, true); ++ if (ret < 0) ++ PMD_DRV_LOG(ERR, "Unable to enable promiscuous mode"); ++ return; ++} ++ ++static void ++dpaa2_dev_allmulticast_disable(struct rte_eth_dev *dev) ++{ ++ int ret; ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ ++ if (dpni == NULL) { ++ PMD_DRV_LOG(ERR, "dpni is NULL"); ++ return; ++ } ++ ++ ret = dpni_set_multicast_promisc(dpni, CMD_PRI_LOW, priv->token, false); ++ if (ret < 0) ++ PMD_DRV_LOG(ERR, "Unable to enable promiscuous mode"); ++ return; ++} ++ ++static int dpaa2_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) ++{ ++ int ret; ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ uint32_t frame_size = mtu + ETHER_HDR_LEN + ETHER_CRC_LEN; ++ ++ if (dpni == NULL) { ++ PMD_DRV_LOG(ERR, "dpni is NULL"); ++ return -EINVAL; ++ } ++ ++ /* check that mtu is within the allowed range */ ++ ++ if ((mtu < ETHER_MIN_MTU) || (frame_size > ETHER_MAX_JUMBO_FRAME_LEN)) ++ return -EINVAL; ++ ++ /* Set the Max Rx frame length as 'mtu' + ++ * Maximum Ethernet header length */ ++ ret = dpni_set_max_frame_length(dpni, CMD_PRI_LOW, priv->token, ++ mtu + ETH_VLAN_HLEN); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "setting the max frame length failed"); ++ return -1; ++ } ++ if (priv->options & DPNI_OPT_IPF) { ++ ret = dpni_set_mtu(dpni, CMD_PRI_LOW, priv->token, mtu); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Setting the MTU failed"); ++ return -1; ++ } ++ } ++ ++ PMD_DRV_LOG(INFO, "MTU is configured %d for the device\n", mtu); ++ return 0; ++} ++ ++static void ++dpaa2_dev_add_mac_addr(struct rte_eth_dev *dev, ++ struct ether_addr *addr, ++ __rte_unused uint32_t index, ++ __rte_unused uint32_t pool) ++{ ++ int ret; ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ ++ if (dpni == NULL) { ++ PMD_DRV_LOG(ERR, "dpni is NULL"); ++ return; ++ } ++ ++ ret = dpni_add_mac_addr(dpni, CMD_PRI_LOW, ++ priv->token, addr->addr_bytes); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Adding the MAC ADDR failed"); ++ } ++ ++ return; ++} ++ ++static void ++dpaa2_dev_remove_mac_addr(struct rte_eth_dev *dev, ++ uint32_t index) ++{ ++ int ret; ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ struct rte_eth_dev_data *data = dev->data; ++ struct ether_addr *macaddr; ++ ++ macaddr = &data->mac_addrs[index]; ++ ++ if (dpni == NULL) { ++ PMD_DRV_LOG(ERR, "dpni is NULL"); ++ return; ++ } ++ ++ ret = dpni_remove_mac_addr(dpni, CMD_PRI_LOW, ++ priv->token, macaddr->addr_bytes); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Removing the MAC ADDR failed"); ++ } ++ ++ return; ++} ++ ++static void ++dpaa2_dev_set_mac_addr(struct rte_eth_dev *dev, ++ struct ether_addr *addr) ++{ ++ int ret; ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ ++ if (dpni == NULL) { ++ PMD_DRV_LOG(ERR, "dpni is NULL"); ++ return; ++ } ++ ++ ret = dpni_set_primary_mac_addr(dpni, CMD_PRI_LOW, ++ priv->token, addr->addr_bytes); ++ ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Setting the MAC ADDR failed"); ++ } ++ ++ return; ++} ++ ++int dpaa2_dev_get_mac_addr(struct rte_eth_dev *dev, ++ struct ether_addr *addr) ++{ ++ int ret; ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ ++ if (dpni == NULL) { ++ PMD_DRV_LOG(ERR, "dpni is NULL"); ++ return -EINVAL; ++ } ++ ++ ret = dpni_get_primary_mac_addr(dpni, CMD_PRI_LOW, ++ priv->token, addr->addr_bytes); ++ ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Getting the MAC ADDR failed"); ++ } ++ ++ return ret; ++} ++ ++/*int dpni_clear_mac_filters(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int unicast, ++ int multicast) ++ ++ ++int dpni_set_vlan_insertion(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en) ++ ++dpni_set_errors_behavior ++ ++int dpni_get_l3_chksum_validation(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en) ++ ++int dpni_set_l3_chksum_validation(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en) ++ ++int dpni_get_l4_chksum_validation(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en) ++ ++int dpni_set_l4_chksum_validation(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en) ++ ++*/ ++ ++static int dpaa2_timestamp_enable(struct rte_eth_dev *dev) ++{ ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ ++ struct dpni_buffer_layout layout; ++ int ret; ++ ++ layout.options = DPNI_BUF_LAYOUT_OPT_TIMESTAMP; ++ layout.pass_timestamp = TRUE; ++ ++ ret = dpni_set_rx_buffer_layout(dpni, CMD_PRI_LOW, priv->token, &layout); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Enabling timestamp for Rx failed with" ++ "err code: %d", ret); ++ return ret; ++ } ++ ++ ret = dpni_set_tx_buffer_layout(dpni, CMD_PRI_LOW, priv->token, &layout); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Enabling timestamp failed for Tx with" ++ "err code: %d", ret); ++ return ret; ++ } ++ ++ ret = dpni_set_tx_conf_buffer_layout(dpni, CMD_PRI_LOW, ++ priv->token, &layout); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Enabling timestamp failed for Tx-conf with" ++ "err code: %d", ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int dpaa2_timestamp_disable(struct rte_eth_dev *dev) ++{ ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ struct dpni_buffer_layout layout; ++ int ret; ++ ++ layout.options = DPNI_BUF_LAYOUT_OPT_TIMESTAMP; ++ layout.pass_timestamp = FALSE; ++ ++ ret = dpni_set_rx_buffer_layout(dpni, CMD_PRI_LOW, priv->token, &layout); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Disabling timestamp failed for Rx with" ++ "err code: %d", ret); ++ return ret; ++ } ++ ++ ret = dpni_set_tx_buffer_layout(dpni, CMD_PRI_LOW, priv->token, &layout); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Disabling timestamp failed for Tx with" ++ "err code: %d", ret); ++ return ret; ++ } ++ ++ ret = dpni_set_tx_conf_buffer_layout(dpni, CMD_PRI_LOW, ++ priv->token, &layout); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Disabling timestamp failed for Tx-conf with" ++ "err code: %d", ret); ++ return ret; ++ } ++ ++ return ret; ++} ++ ++/* return 0 means link status changed, -1 means not changed */ ++static int ++dpaa2_dev_get_link_info(struct rte_eth_dev *dev, ++ int wait_to_complete __rte_unused) ++{ ++ int ret; ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ struct rte_eth_link link, old; ++ struct dpni_link_state state = {0}; ++ ++ if (dpni == NULL) { ++ PMD_DRV_LOG(ERR, "dpni is NULL"); ++ return 0; ++ } ++ memset(&old, 0, sizeof(old)); ++ rte_dpni_dev_atomic_read_link_status(dev, &old); ++ ++ ret = dpni_get_link_state(dpni, CMD_PRI_LOW, priv->token, &state); ++ if (ret < 0) { ++ PMD_DRV_LOG(ERR, "dpni_get_link_state"); ++ return 0; ++ } ++ ++ if (state.up == 0) { ++ rte_dpni_dev_atomic_write_link_status(dev, &link); ++ if (state.up == old.link_status) ++ return -1; ++ return 0; ++ } ++ link.link_status = state.up; ++ link.link_speed = state.rate; ++ ++ if (state.options & DPNI_LINK_OPT_HALF_DUPLEX) ++ link.link_duplex = ETH_LINK_HALF_DUPLEX; ++ else ++ link.link_duplex = ETH_LINK_FULL_DUPLEX; ++ ++ rte_dpni_dev_atomic_write_link_status(dev, &link); ++ ++ if (link.link_status == old.link_status) ++ return -1; ++ ++ return 0; ++} ++ ++static ++void dpaa2_dev_stats_get(struct rte_eth_dev *dev, ++ struct rte_eth_stats *stats) ++{ ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ ++ int32_t retcode; ++ uint64_t value; ++ ++ if (dpni == NULL) { ++ PMD_DRV_LOG(ERR, "dpni is NULL"); ++ return; ++ } ++ ++ if (!stats) { ++ PMD_DRV_LOG(ERR, "stats is NULL"); ++ return; ++ } ++ ++ retcode = dpni_get_counter(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_CNT_ING_FRAME, &value); ++ if (retcode) ++ goto error; ++ stats->ipackets = value; ++ retcode = dpni_get_counter(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_CNT_ING_BYTE, &value); ++ if (retcode) ++ goto error; ++ stats->ibytes = value; ++ retcode = dpni_get_counter(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_CNT_ING_FRAME_DROP, &value); ++ if (retcode) ++ goto error; ++ stats->ierrors = value; ++ retcode = dpni_get_counter(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_CNT_ING_FRAME_DISCARD, &value); ++ if (retcode) ++ goto error; ++ stats->ierrors = stats->ierrors + value; ++ retcode = dpni_get_counter(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_CNT_EGR_FRAME, &value); ++ if (retcode) ++ goto error; ++ stats->opackets = value; ++ dpni_get_counter(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_CNT_EGR_BYTE, &value); ++ if (retcode) ++ goto error; ++ stats->obytes = value; ++ retcode = dpni_get_counter(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_CNT_EGR_FRAME_DISCARD, &value); ++ if (retcode) ++ goto error; ++ stats->oerrors = value; ++ ++ return; ++ ++error: ++ PMD_DRV_LOG(ERR, "Operation not completed:Error Code = %d\n", retcode); ++ return; ++}; ++ ++static ++void dpaa2_dev_stats_reset(struct rte_eth_dev *dev) ++{ ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ ++ int32_t retcode; ++ ++ if (dpni == NULL) { ++ PMD_DRV_LOG(ERR, "dpni is NULL"); ++ return; ++ } ++ ++ retcode = dpni_set_counter(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_CNT_ING_FRAME, 0); ++ if (retcode) ++ goto error; ++ retcode = dpni_set_counter(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_CNT_ING_BYTE, 0); ++ if (retcode) ++ goto error; ++ retcode = dpni_set_counter(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_CNT_ING_BCAST_FRAME, 0); ++ if (retcode) ++ goto error; ++ retcode = dpni_set_counter(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_CNT_ING_BCAST_BYTES, 0); ++ if (retcode) ++ goto error; ++ retcode = dpni_set_counter(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_CNT_ING_MCAST_FRAME, 0); ++ if (retcode) ++ goto error; ++ retcode = dpni_set_counter(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_CNT_ING_MCAST_BYTE, 0); ++ if (retcode) ++ goto error; ++ retcode = dpni_set_counter(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_CNT_ING_FRAME_DROP, 0); ++ if (retcode) ++ goto error; ++ retcode = dpni_set_counter(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_CNT_ING_FRAME_DISCARD, 0); ++ if (retcode) ++ goto error; ++ retcode = dpni_set_counter(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_CNT_EGR_FRAME, 0); ++ if (retcode) ++ goto error; ++ retcode = dpni_set_counter(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_CNT_EGR_BYTE, 0); ++ if (retcode) ++ goto error; ++ retcode = dpni_set_counter(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_CNT_EGR_FRAME_DISCARD, 0); ++ if (retcode) ++ goto error; ++ ++ return; ++ ++error: ++ PMD_DRV_LOG(ERR, "Operation not completed:Error Code = %d\n", retcode); ++ return; ++}; ++ ++static struct eth_dev_ops ops = { ++ .dev_configure = dpaa2_eth_dev_configure, ++ .dev_start = dpaa2_dev_start, ++ .dev_stop = dpaa2_dev_stop, ++ .dev_close = dpaa2_dev_close, ++ .promiscuous_enable = dpaa2_dev_promiscuous_enable, ++ .promiscuous_disable = dpaa2_dev_promiscuous_disable, ++ .allmulticast_enable = dpaa2_dev_allmulticast_enable, ++ .allmulticast_disable = dpaa2_dev_allmulticast_disable, ++ /* .dev_set_link_up = ixgbe_dev_set_link_up, */ ++ /* .dev_set_link_down = ixgbe_dev_set_link_down, */ ++ .link_update = dpaa2_dev_get_link_info, ++ .stats_get = dpaa2_dev_stats_get, ++ /* .xstats_get = ixgbe_dev_xstats_get, */ ++ .stats_reset = dpaa2_dev_stats_reset, ++ /* .xstats_reset = ixgbe_dev_xstats_reset, */ ++ /* .queue_stats_mapping_set = i40e_dev_queue_stats_mapping_set, */ ++ .dev_infos_get = dpaa2_eth_dev_info, ++ .dev_supported_ptypes_get = dpaa2_supported_ptypes_get, ++ .mtu_set = dpaa2_dev_mtu_set, ++ .vlan_filter_set = dpaa2_vlan_filter_set, ++/* .vlan_tpid_set = i40e_vlan_tpid_set, */ ++ .vlan_offload_set = dpaa2_vlan_offload_set, ++/* .vlan_strip_queue_set = i40e_vlan_strip_queue_set, */ ++/* .vlan_pvid_set = i40e_vlan_pvid_set, */ ++/* .rx_queue_start = i40e_dev_rx_queue_start, */ ++/* .rx_queue_stop = i40e_dev_rx_queue_stop, */ ++/* .tx_queue_start = i40e_dev_tx_queue_start, */ ++/* .tx_queue_stop = i40e_dev_tx_queue_stop, */ ++ .rx_queue_setup = dpaa2_rx_queue_setup, ++/* .rx_queue_intr_enable = i40e_dev_rx_queue_intr_enable, */ ++/* .rx_queue_intr_disable = i40e_dev_rx_queue_intr_disable, */ ++/* .rx_queue_release = i40e_dev_rx_queue_release, */ ++/* .rx_queue_count = i40e_dev_rx_queue_count, */ ++ .tx_queue_setup = dpaa2_tx_queue_setup, ++/* .tx_queue_release = i40e_dev_tx_queue_release, */ ++/* .dev_led_on = i40e_dev_led_on, */ ++/* .dev_led_off = i40e_dev_led_off, */ ++/* .flow_ctrl_get = i40e_flow_ctrl_get, */ ++/* .flow_ctrl_set = i40e_flow_ctrl_set, */ ++/* .priority_flow_ctrl_set = i40e_priority_flow_ctrl_set, */ ++ .mac_addr_add = dpaa2_dev_add_mac_addr, ++ .mac_addr_remove = dpaa2_dev_remove_mac_addr, ++/* .reta_update = i40e_dev_rss_reta_update, */ ++/* .reta_query = i40e_dev_rss_reta_query, */ ++/* .rss_hash_update = i40e_dev_rss_hash_update, */ ++/* .rss_hash_conf_get = i40e_dev_rss_hash_conf_get, */ ++/* .filter_ctrl = i40e_dev_filter_ctrl, */ ++/* .rxq_info_get = i40e_rxq_info_get, */ ++/* .txq_info_get = i40e_txq_info_get, */ ++/* .mirror_rule_set = i40e_mirror_rule_set, */ ++/* .mirror_rule_reset = i40e_mirror_rule_reset, */ ++ .timesync_enable = dpaa2_timestamp_enable, ++ .timesync_disable = dpaa2_timestamp_disable, ++/* .timesync_read_rx_timestamp = i40e_timesync_read_rx_timestamp, */ ++/* .timesync_read_tx_timestamp = i40e_timesync_read_tx_timestamp, */ ++/* .get_dcb_info = i40e_dev_get_dcb_info, */ ++/* .timesync_adjust_time = i40e_timesync_adjust_time, */ ++/* .timesync_read_time = i40e_timesync_read_time, */ ++/* .timesync_write_time = i40e_timesync_write_time, */ ++/* .get_reg_length = i40e_get_reg_length, */ ++/* .get_reg = i40e_get_regs, */ ++/* .get_eeprom_length = i40e_get_eeprom_length, */ ++/* .get_eeprom = i40e_get_eeprom, */ ++ .mac_addr_set = dpaa2_dev_set_mac_addr, ++}; ++ ++static int ++dpaa2_dev_init(struct rte_eth_dev *eth_dev) ++{ ++ struct rte_eth_dev_data *data = eth_dev->data; ++ struct fsl_mc_io *dpni_dev; ++ struct dpni_attr attr; ++ struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; ++ struct dpni_buffer_layout layout; ++ int i, ret, hw_id = eth_dev->pci_dev->addr.devid; ++ struct dpni_extended_cfg *ext_cfg = NULL; ++ int tot_size; ++ ++ PMD_INIT_FUNC_TRACE(); ++ ++ dpni_dev = (struct fsl_mc_io *)malloc(sizeof(struct fsl_mc_io)); ++ if (!dpni_dev) { ++ PMD_DRV_LOG(ERR, "malloc failed for dpni device\n"); ++ return -1; ++ } ++ ++ dpni_dev->regs = mcp_ptr_list[0]; ++ ret = dpni_open(dpni_dev, CMD_PRI_LOW, hw_id, &priv->token); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Failure in opening dpni@%d device with" ++ "error code %d\n", hw_id, ret); ++ return -1; ++ } ++ ++ /* Clean the device first */ ++ ret = dpni_reset(dpni_dev, CMD_PRI_LOW, priv->token); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Failure cleaning dpni@%d device with" ++ "error code %d\n", hw_id, ret); ++ return -1; ++ } ++ ++ ext_cfg = (struct dpni_extended_cfg *)rte_malloc(NULL, 256, ++ RTE_CACHE_LINE_SIZE); ++ if (!ext_cfg) { ++ PMD_DRV_LOG(ERR, "No data memory\n"); ++ return -1; ++ } ++ attr.ext_cfg_iova = (uint64_t)(DPAA2_VADDR_TO_IOVA(ext_cfg)); ++ ++ ret = dpni_get_attributes(dpni_dev, CMD_PRI_LOW, priv->token, &attr); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Failure in getting dpni@%d attribute, " ++ "error code %d\n", hw_id, ret); ++ return -1; ++ } ++ ++ priv->num_tc = attr.max_tcs; ++ for (i = 0; i < attr.max_tcs; i++) { ++ priv->num_dist_per_tc[i] = ext_cfg->tc_cfg[i].max_dist; ++ priv->nb_rx_queues += priv->num_dist_per_tc[i]; ++ /* todo - currently we only support one TC index in RX side */ ++ break; ++ } ++ if (attr.max_tcs == 1) ++ priv->nb_tx_queues = attr.max_senders; ++ else ++ priv->nb_tx_queues = attr.max_tcs; ++ PMD_DRV_LOG(INFO, "num_tc %d\n", priv->num_tc); ++ PMD_DRV_LOG(INFO, "nb_rx_queues %d\n", priv->nb_rx_queues); ++ ++ eth_dev->data->nb_rx_queues = priv->nb_rx_queues; ++ eth_dev->data->nb_tx_queues = priv->nb_tx_queues; ++ ++ priv->hw = dpni_dev; ++ priv->hw_id = hw_id; ++ priv->options = attr.options; ++ ++ priv->max_unicast_filters = attr.max_unicast_filters; ++ priv->max_multicast_filters = attr.max_multicast_filters; ++ ++ if (attr.options & DPNI_OPT_VLAN_FILTER) ++ priv->max_vlan_filters = attr.max_vlan_filters; ++ else ++ priv->max_vlan_filters = 0; ++ ++ ret = dpaa2_alloc_rx_tx_queues(eth_dev); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "dpaa2_alloc_rx_tx_queuesFailed\n"); ++ return -1; ++ } ++ ++ data->mac_addrs = (struct ether_addr *)malloc(sizeof(struct ether_addr)); ++ ++ /* Allocate memory for storing MAC addresses */ ++ eth_dev->data->mac_addrs = rte_zmalloc("dpni", ++ ETHER_ADDR_LEN * attr.max_unicast_filters, 0); ++ if (eth_dev->data->mac_addrs == NULL) { ++ PMD_DRV_LOG(ERR, "Failed to allocate %d bytes needed to " ++ "store MAC addresses", ++ ETHER_ADDR_LEN * attr.max_unicast_filters); ++ return -ENOMEM; ++ } ++ ++ ret = dpni_get_primary_mac_addr(dpni_dev, CMD_PRI_LOW, ++ priv->token, ++ (uint8_t *)(data->mac_addrs[0].addr_bytes)); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "DPNI get mac address failed:" ++ " Error Code = %d\n", ret); ++ return -1; ++ } ++ ++ PMD_DRV_LOG(INFO, "Adding Broadcast Address...\n"); ++ memset(data->mac_addrs[1].addr_bytes, 0xff, ETH_ADDR_LEN); ++ ret = dpni_add_mac_addr(dpni_dev, CMD_PRI_LOW, ++ priv->token, ++ (uint8_t *)(data->mac_addrs[1].addr_bytes)); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "DPNI set broadcast mac address failed:" ++ " Error Code = %0x\n", ret); ++ return -1; ++ } ++ ++ /* ... rx buffer layout ... */ ++ /*Check alignment for buffer layouts first*/ ++ tot_size = DPAA2_FD_PTA_SIZE + DPAA2_MBUF_HW_ANNOTATION + DPAA2_RES/* dummy */ + ++ 128 /*RTE_MUF */ + (128+DPAA2_RES)/*VLIB*/ + RTE_PKTMBUF_HEADROOM; ++ tot_size = DPAA2_ALIGN_ROUNDUP(tot_size, ++ DPAA2_PACKET_LAYOUT_ALIGN); ++ ++ memset(&layout, 0, sizeof(struct dpni_buffer_layout)); ++ layout.options = DPNI_BUF_LAYOUT_OPT_FRAME_STATUS | ++ DPNI_BUF_LAYOUT_OPT_PARSER_RESULT | ++ DPNI_BUF_LAYOUT_OPT_DATA_HEAD_ROOM | ++ DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE; ++ ++ layout.pass_frame_status = 1; ++ layout.data_head_room = ++ (tot_size - (DPAA2_FD_PTA_SIZE + DPAA2_MBUF_HW_ANNOTATION)); ++ layout.private_data_size = DPAA2_FD_PTA_SIZE; ++ layout.pass_parser_result = 1; ++ ++ ret = dpni_set_rx_buffer_layout(dpni_dev, CMD_PRI_LOW, priv->token, ++ &layout); ++ if (ret) { ++ printf("Err(%d) in setting rx buffer layout\n", ret); ++ return -1; ++ } ++ ++ /* ... tx buffer layout ... */ ++ memset(&layout, 0, sizeof(struct dpni_buffer_layout)); ++ layout.options = DPNI_BUF_LAYOUT_OPT_FRAME_STATUS; ++ layout.pass_frame_status = 1; ++ ret = dpni_set_tx_buffer_layout(dpni_dev, CMD_PRI_LOW, priv->token, &layout); ++ if (ret) { ++ printf("Error (%d) in setting tx buffer layout\n", ret); ++ return -1; ++ } ++ ++ /* ... tx-conf and error buffer layout ... */ ++ memset(&layout, 0, sizeof(struct dpni_buffer_layout)); ++ layout.options = DPNI_BUF_LAYOUT_OPT_FRAME_STATUS; ++ layout.pass_frame_status = 1; ++ ret = dpni_set_tx_conf_buffer_layout(dpni_dev, CMD_PRI_LOW, priv->token, &layout); ++ if (ret) { ++ printf("Error (%d) in setting tx-conf buffer layout\n", ret); ++ return -1; ++ } ++ ++ /* TODO - Set the MTU if required */ ++ ++ eth_dev->dev_ops = &ops; ++ eth_dev->rx_pkt_burst = eth_dpaa2_prefetch_rx;/*eth_dpaa2_rx;*/ ++ eth_dev->tx_pkt_burst = eth_dpaa2_tx; ++ ++ rte_free(ext_cfg); ++ ++ return 0; ++} ++ ++static struct eth_driver rte_dpaa2_dpni = { ++ { ++ .name = "rte_dpaa2_dpni", ++ .id_table = pci_id_dpaa2_map, ++ }, ++ .eth_dev_init = dpaa2_dev_init, ++ .dev_private_size = sizeof(struct dpaa2_dev_priv), ++}; ++ ++static int ++rte_pmd_dpaa2_devinit( ++ const char *name __rte_unused, ++ const char *params __rte_unused) ++{ ++ printf("Initializing dpaa2_pmd for %s\n", name); ++ rte_eth_driver_register(&rte_dpaa2_dpni); ++ ++ return 0; ++} ++ ++static struct rte_driver pmd_dpaa2_drv = { ++ .name = "dpaa2_pmd", ++ .type = PMD_PDEV, ++ .init = rte_pmd_dpaa2_devinit, ++}; ++ ++PMD_REGISTER_DRIVER(pmd_dpaa2_drv); +diff --git a/drivers/net/dpaa2/rte_eth_dpni_annot.h b/drivers/net/dpaa2/rte_eth_dpni_annot.h +new file mode 100644 +index 0000000..00fac9b +--- /dev/null ++++ b/drivers/net/dpaa2/rte_eth_dpni_annot.h +@@ -0,0 +1,311 @@ ++/*- ++ * BSD LICENSE ++ * ++ * Copyright (c) 2014 Freescale Semiconductor, Inc. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * * Neither the name of Freescale Semiconductor, Inc nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++/** ++ * @file ++ * ++ * DPNI packet parse results - implementation internal ++ */ ++ ++#ifndef RTE_ETH_DPNI_ANNOT_H_ ++#define RTE_ETH_DPNI_ANNOT_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* Annotation valid bits in FD FRC */ ++#define DPAA2_FD_FRC_FASV 0x8000 ++#define DPAA2_FD_FRC_FAEADV 0x4000 ++#define DPAA2_FD_FRC_FAPRV 0x2000 ++#define DPAA2_FD_FRC_FAIADV 0x1000 ++#define DPAA2_FD_FRC_FASWOV 0x0800 ++#define DPAA2_FD_FRC_FAICFDV 0x0400 ++ ++/* Annotation bits in FD CTRL */ ++#define DPAA2_FD_CTRL_ASAL 0x00020000 /* ASAL = 128 */ ++#define DPAA2_FD_CTRL_PTA 0x00800000 ++#define DPAA2_FD_CTRL_PTV1 0x00400000 ++ ++/* Frame annotation status */ ++struct dpaa2_fas { ++ uint8_t reserved; ++ uint8_t ppid; ++ __le16 ifpid; ++ __le32 status; ++} __packed; ++ ++/** ++ * Internal Packet annotation header ++ */ ++struct pkt_annotation { ++ /**< word1: Frame Annotation Status (8 bytes)*/ ++ uint64_t word1; ++ /**< word2: Time Stamp (8 bytes)*/ ++ uint64_t word2; ++ /**< word3: Next Hdr + FAF Extension + FAF (2 + 2 + 4 bytes)*/ ++ uint64_t word3; ++ /**< word4: Frame Annotation Flags-FAF (8 bytes) */ ++ uint64_t word4; ++ /**< word5: ++ ShimOffset_1 + ShimOffset_2 + IPPIDOffset + EthOffset + ++ LLC+SNAPOffset + VLANTCIOffset_1 + VLANTCIOffset_n + ++ LastETypeOffset (1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 bytes) ++ */ ++ uint64_t word5; ++ /**< word6: ++ PPPoEOffset + MPLSOffset_1 + MPLSOffset_n + ARPorIPOffset_1 ++ + IPOffset_norMInEncapO + GREOffset + L4Offset + ++ GTPorESPorIPSecOffset(1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 bytes) ++ */ ++ uint64_t word6; ++ /**< word7: ++ RoutingHdrOfset1 + RoutingHdrOfset2 + NxtHdrOffset + IPv6FragOffset + ++ GrossRunningSum + RunningSum(1 + 1 + 1 + 1 + 2 + 2 bytes) ++ */ ++ uint64_t word7; ++ /**< word8: ++ ParseErrorcode + Soft Parsing Context (1 + 7 bytes) ++ */ ++ uint64_t word8; /**< Layer 4 length */ ++}; ++ ++/** ++ * Internal Macros to get/set Packet annotation header ++ */ ++ ++/** General Macro to define a particular bit position*/ ++#define BIT_POS(x) ((uint64_t)1 << ((x))) ++/** Set a bit in the variable */ ++#define BIT_SET_AT_POS(var, pos) (var |= pos) ++/** Reset the bit in the variable */ ++#define BIT_RESET_AT_POS(var, pos) (var &= ~(pos)) ++/** Check the bit is set in the variable */ ++#define BIT_ISSET_AT_POS(var, pos) ((var & pos) ? 1 : 0) ++/** ++ * Macrso to define bit position in word3 ++ */ ++#define NEXT_HDR(var) ((uint64_t)var & 0xFFFF000000000000) ++#define FAF_EXTN_IPV6_ROUTE_HDR_PRESENT(var) BIT_POS(16) ++#define FAF_EXTN_RESERVED(var) ((uint64_t)var & 0x00007FFF00000000) ++#define FAF_USER_DEFINED_RESERVED(var) ((uint64_t)var & 0x00000000FF000000) ++#define SHIM_SHELL_SOFT_PARSING_ERRROR BIT_POS(23) ++#define PARSING_ERROR BIT_POS(22) ++#define L2_ETH_MAC_PRESENT BIT_POS(21) ++#define L2_ETH_MAC_UNICAST BIT_POS(20) ++#define L2_ETH_MAC_MULTICAST BIT_POS(19) ++#define L2_ETH_MAC_BROADCAST BIT_POS(18) ++#define L2_ETH_FRAME_IS_BPDU BIT_POS(17) ++#define L2_ETH_FCOE_PRESENT BIT_POS(16) ++#define L2_ETH_FIP_PRESENT BIT_POS(15) ++#define L2_ETH_PARSING_ERROR BIT_POS(14) ++#define L2_LLC_SNAP_PRESENT BIT_POS(13) ++#define L2_UNKNOWN_LLC_OUI BIT_POS(12) ++#define L2_LLC_SNAP_ERROR BIT_POS(11) ++#define L2_VLAN_1_PRESENT BIT_POS(10) ++#define L2_VLAN_N_PRESENT BIT_POS(9) ++#define L2_VLAN_CFI_BIT_PRESENT BIT_POS(8) ++#define L2_VLAN_PARSING_ERROR BIT_POS(7) ++#define L2_PPPOE_PPP_PRESENT BIT_POS(6) ++#define L2_PPPOE_PPP_PARSING_ERROR BIT_POS(5) ++#define L2_MPLS_1_PRESENT BIT_POS(4) ++#define L2_MPLS_N_PRESENT BIT_POS(3) ++#define L2_MPLS_PARSING_ERROR BIT_POS(2) ++#define L2_ARP_PRESENT BIT_POS(1) ++#define L2_ARP_PARSING_ERROR BIT_POS(0) ++/** ++ * Macrso to define bit position in word4 ++ */ ++#define L2_UNKNOWN_PROTOCOL BIT_POS(63) ++#define L2_SOFT_PARSING_ERROR BIT_POS(62) ++#define L3_IPV4_1_PRESENT BIT_POS(61) ++#define L3_IPV4_1_UNICAST BIT_POS(60) ++#define L3_IPV4_1_MULTICAST BIT_POS(59) ++#define L3_IPV4_1_BROADCAST BIT_POS(58) ++#define L3_IPV4_N_PRESENT BIT_POS(57) ++#define L3_IPV4_N_UNICAST BIT_POS(56) ++#define L3_IPV4_N_MULTICAST BIT_POS(55) ++#define L3_IPV4_N_BROADCAST BIT_POS(54) ++#define L3_IPV6_1_PRESENT BIT_POS(53) ++#define L3_IPV6_1_UNICAST BIT_POS(52) ++#define L3_IPV6_1_MULTICAST BIT_POS(51) ++#define L3_IPV6_N_PRESENT BIT_POS(50) ++#define L3_IPV6_N_UNICAST BIT_POS(49) ++#define L3_IPV6_N_MULTICAST BIT_POS(48) ++#define L3_IP_1_OPT_PRESENT BIT_POS(47) ++#define L3_IP_1_UNKNOWN_PROTOCOL BIT_POS(46) ++#define L3_IP_1_MORE_FRAGMENT BIT_POS(45) ++#define L3_IP_1_FIRST_FRAGMENT BIT_POS(44) ++#define L3_IP_1_PARSING_ERROR BIT_POS(43) ++#define L3_IP_N_OPT_PRESENT BIT_POS(42) ++#define L3_IP_N_UNKNOWN_PROTOCOL BIT_POS(41) ++#define L3_IP_N_MORE_FRAGMENT BIT_POS(40) ++#define L3_IP_N_FIRST_FRAGMENT BIT_POS(39) ++#define L3_PROTO_ICMP_PRESENT BIT_POS(38) ++#define L3_PROTO_IGMP_PRESENT BIT_POS(37) ++#define L3_PROTO_ICMPV6_PRESENT BIT_POS(36) ++#define L3_PROTO_UDP_LIGHT_PRESENT BIT_POS(35) ++#define L3_IP_N_PARSING_ERROR BIT_POS(34) ++#define L3_MIN_ENCAP_PRESENT BIT_POS(33) ++#define L3_MIN_ENCAP_SBIT_PRESENT BIT_POS(32) ++#define L3_MIN_ENCAP_PARSING_ERROR BIT_POS(31) ++#define L3_PROTO_GRE_PRESENT BIT_POS(30) ++#define L3_PROTO_GRE_RBIT_PRESENT BIT_POS(29) ++#define L3_PROTO_GRE_PARSING_ERROR BIT_POS(28) ++#define L3_IP_UNKNOWN_PROTOCOL BIT_POS(27) ++#define L3_SOFT_PARSING_ERROR BIT_POS(26) ++#define L3_PROTO_UDP_PRESENT BIT_POS(25) ++#define L3_PROTO_UDP_PARSING_ERROR BIT_POS(24) ++#define L3_PROTO_TCP_PRESENT BIT_POS(23) ++#define L3_PROTO_TCP_OPT_PRESENT BIT_POS(22) ++#define L3_PROTO_TCP_CTRL_BIT_6_TO_11_PRESENT BIT_POS(21) ++#define L3_PROTO_TCP_CTRL_BIT_3_TO_5_PRESENT BIT_POS(20) ++#define L3_PROTO_TCP_PARSING_ERROR BIT_POS(19) ++#define L3_PROTO_IPSEC_PRESENT BIT_POS(18) ++#define L3_PROTO_IPSEC_ESP_PRESENT BIT_POS(17) ++#define L3_PROTO_IPSEC_AH_PRESENT BIT_POS(16) ++#define L3_PROTO_IPSEC_PARSING_ERROR BIT_POS(15) ++#define L3_PROTO_SCTP_PRESENT BIT_POS(14) ++#define L3_PROTO_SCTP_PARSING_ERROR BIT_POS(13) ++#define L3_PROTO_DCCP_PRESENT BIT_POS(12) ++#define L3_PROTO_DCCP_PARSING_ERROR BIT_POS(11) ++#define L4_UNKNOWN_PROTOCOL BIT_POS(10) ++#define L4_SOFT_PARSING_ERROR BIT_POS(9) ++#define L3_PROTO_GTP_PRESENT BIT_POS(8) ++#define L3_PROTO_GTP_PARSING_ERROR BIT_POS(7) ++#define L3_PROTO_ESP_PRESENT BIT_POS(6) ++#define L3_PROTO_ESP_PARSING_ERROR BIT_POS(5) ++#define L3_PROTO_ISCSI_PRESENT BIT_POS(4) ++#define L3_PROTO_CAPWAN__CTRL_PRESENT BIT_POS(3) ++#define L3_PROTO_CAPWAN__DATA_PRESENT BIT_POS(2) ++#define L5_SOFT_PARSING_ERROR BIT_POS(1) ++#define L3_IPV6_ROUTE_HDR_PRESENT BIT_POS(0) ++ ++/** ++ * Macros to get values in word5 ++ */ ++#define SHIM_OFFSET_1(var) ((uint64_t)var & 0xFF00000000000000) ++#define SHIM_OFFSET_2(var) ((uint64_t)var & 0x00FF000000000000) ++#define IP_PID_OFFSET(var) ((uint64_t)var & 0x0000FF0000000000) ++#define ETH_OFFSET(var) ((uint64_t)var & 0x000000FF00000000) ++#define LLC_SNAP_OFFSET(var) ((uint64_t)var & 0x00000000FF000000) ++#define VLAN_TCI_OFFSET_1(var) ((uint64_t)var & 0x0000000000FF0000) ++#define VLAN_TCI_OFFSET_N(var) ((uint64_t)var & 0x000000000000FF00) ++#define LAST_ETYPE_OFFSET(var) ((uint64_t)var & 0x00000000000000FF) ++ ++/** ++ * Macros to get values in word6 ++ */ ++#define PPPOE_OFFSET(var) ((uint64_t)var & 0xFF00000000000000) ++#define MPLS_OFFSET_1(var) ((uint64_t)var & 0x00FF000000000000) ++#define MPLS_OFFSET_N(var) ((uint64_t)var & 0x0000FF0000000000) ++#define ARP_OR_IP_OFFSET_1(var) ((uint64_t)var & 0x000000FF00000000) ++#define IP_N_OR_MIN_ENCAP_OFFSET(var) ((uint64_t)var & 0x00000000FF000000) ++#define GRE_OFFSET(var) ((uint64_t)var & 0x0000000000FF0000) ++#define L4_OFFSET(var) ((uint64_t)var & 0x000000000000FF00) ++#define GTP_OR_ESP_OR_IPSEC_OFFSET(var) ((uint64_t)var & 0x00000000000000FF) ++ ++/** ++ * Macros to get values in word7 ++ */ ++#define IPV6_ROUTING_HDR_OFFSET_1(var) ((uint64_t)var & 0xFF00000000000000) ++#define IPV6_ROUTING_HDR_OFFSET_2(var) ((uint64_t)var & 0x00FF000000000000) ++#define NEXT_HDR_OFFSET(var) ((uint64_t)var & 0x0000FF0000000000) ++#define IPV6_FRAG_OFFSET(var) ((uint64_t)var & 0x000000FF00000000) ++#define GROSS_RUNNING_SUM(var) ((uint64_t)var & 0x00000000FFFF0000) ++#define RUNNING_SUM(var) ((uint64_t)var & 0x000000000000FFFF) ++ ++/** ++ * Macros to get values in word8 ++ */ ++#define PARSE_ERROR_CODE(var) ((uint64_t)var & 0xFF00000000000000) ++#define SOFT_PARSING_CONTEXT(var) ((uint64_t)var & 0x00FFFFFFFFFFFFFF) ++ ++/* Debug frame, otherwise supposed to be discarded */ ++#define DPAA2_ETH_FAS_DISC 0x80000000 ++/* MACSEC frame */ ++#define DPAA2_ETH_FAS_MS 0x40000000 ++#define DPAA2_ETH_FAS_PTP 0x08000000 ++/* Ethernet multicast frame */ ++#define DPAA2_ETH_FAS_MC 0x04000000 ++/* Ethernet broadcast frame */ ++#define DPAA2_ETH_FAS_BC 0x02000000 ++#define DPAA2_ETH_FAS_KSE 0x00040000 ++#define DPAA2_ETH_FAS_EOFHE 0x00020000 ++#define DPAA2_ETH_FAS_MNLE 0x00010000 ++#define DPAA2_ETH_FAS_TIDE 0x00008000 ++#define DPAA2_ETH_FAS_PIEE 0x00004000 ++/* Frame length error */ ++#define DPAA2_ETH_FAS_FLE 0x00002000 ++/* Frame physical error; our favourite pastime */ ++#define DPAA2_ETH_FAS_FPE 0x00001000 ++#define DPAA2_ETH_FAS_PTE 0x00000080 ++#define DPAA2_ETH_FAS_ISP 0x00000040 ++#define DPAA2_ETH_FAS_PHE 0x00000020 ++#define DPAA2_ETH_FAS_BLE 0x00000010 ++/* L3 csum validation performed */ ++#define DPAA2_ETH_FAS_L3CV 0x00000008 ++/* L3 csum error */ ++#define DPAA2_ETH_FAS_L3CE 0x00000004 ++/* L4 csum validation performed */ ++#define DPAA2_ETH_FAS_L4CV 0x00000002 ++/* L4 csum error */ ++#define DPAA2_ETH_FAS_L4CE 0x00000001 ++ ++/* These bits always signal errors */ ++#define DPAA2_ETH_RX_ERR_MASK (DPAA2_ETH_FAS_KSE | \ ++ DPAA2_ETH_FAS_EOFHE | \ ++ DPAA2_ETH_FAS_MNLE | \ ++ DPAA2_ETH_FAS_TIDE | \ ++ DPAA2_ETH_FAS_PIEE | \ ++ DPAA2_ETH_FAS_FLE | \ ++ DPAA2_ETH_FAS_FPE | \ ++ DPAA2_ETH_FAS_PTE | \ ++ DPAA2_ETH_FAS_ISP | \ ++ DPAA2_ETH_FAS_PHE | \ ++ DPAA2_ETH_FAS_BLE | \ ++ DPAA2_ETH_FAS_L3CE | \ ++ DPAA2_ETH_FAS_L4CE) ++/* Unsupported features in the ingress */ ++#define DPAA2_ETH_RX_UNSUPP_MASK DPAA2_ETH_FAS_MS ++/* Tx errors */ ++#define DPAA2_ETH_TXCONF_ERR_MASK (DPAA2_ETH_FAS_KSE | \ ++ DPAA2_ETH_FAS_EOFHE | \ ++ DPAA2_ETH_FAS_MNLE | \ ++ DPAA2_ETH_FAS_TIDE) ++ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/drivers/net/dpaa2/rte_pmd_dpaa2_version.map b/drivers/net/dpaa2/rte_pmd_dpaa2_version.map +new file mode 100644 +index 0000000..349c6e1 +--- /dev/null ++++ b/drivers/net/dpaa2/rte_pmd_dpaa2_version.map +@@ -0,0 +1,4 @@ ++DPDK_16.04 { ++ ++ local: *; ++}; +diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h +index 2342fa1..8f27836 100644 +--- a/lib/librte_eal/common/eal_private.h ++++ b/lib/librte_eal/common/eal_private.h +@@ -328,4 +328,16 @@ int rte_eal_hugepage_init(void); + */ + int rte_eal_hugepage_attach(void); + ++#ifdef RTE_LIBRTE_DPAA2_PMD ++/** ++ * Initialize any soc init related functions if any before thread creation ++ */ ++int rte_eal_soc_pre_init(void); ++ ++/** ++ * Initialize any soc init related functions if any after thread creation ++ */ ++int rte_eal_soc_post_init(void); ++#endif ++ + #endif /* _EAL_PRIVATE_H_ */ +diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile +index e109361..abcd02c 100644 +--- a/lib/librte_eal/linuxapp/eal/Makefile ++++ b/lib/librte_eal/linuxapp/eal/Makefile +@@ -47,6 +47,13 @@ CFLAGS += -I$(RTE_SDK)/lib/librte_eal/common/include + CFLAGS += -I$(RTE_SDK)/lib/librte_ring + CFLAGS += -I$(RTE_SDK)/lib/librte_mempool + CFLAGS += -I$(RTE_SDK)/lib/librte_ivshmem ++ifeq ($(CONFIG_RTE_LIBRTE_DPAA2_PMD),y) ++CFLAGS += -I$(RTE_SDK)/lib/librte_mbuf ++CFLAGS += -I$(RTE_SDK)/drivers/net/dpaa2/qbman/include ++CFLAGS += -I$(RTE_SDK)/drivers/net/dpaa2/qbman/include/drivers ++CFLAGS += -I$(RTE_SDK)/drivers/net/dpaa2/mc ++CFLAGS += -I$(RTE_SDK)/drivers/net/dpaa2/driver ++endif + CFLAGS += $(WERROR_FLAGS) -O3 + + LDLIBS += -ldl +@@ -72,6 +79,10 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_lcore.c + SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_timer.c + SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_interrupts.c + SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_alarm.c ++ifeq ($(CONFIG_RTE_LIBRTE_DPAA2_PMD),y) ++SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_soc.c ++SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_vfio_fsl_mc.c ++endif + ifeq ($(CONFIG_RTE_LIBRTE_IVSHMEM),y) + SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_ivshmem.c + endif +diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c +index 8aafd51..b2327c7 100644 +--- a/lib/librte_eal/linuxapp/eal/eal.c ++++ b/lib/librte_eal/linuxapp/eal/eal.c +@@ -805,6 +805,11 @@ rte_eal_init(int argc, char **argv) + if (rte_eal_tailqs_init() < 0) + rte_panic("Cannot init tail queues for objects\n"); + ++#ifdef RTE_LIBRTE_DPAA2_PMD ++ if (rte_eal_soc_pre_init() < 0) ++ rte_panic("Cannot pre init soc\n"); ++#endif ++ + #ifdef RTE_LIBRTE_IVSHMEM + if (rte_eal_ivshmem_obj_init() < 0) + rte_panic("Cannot init IVSHMEM objects\n"); +@@ -874,6 +879,11 @@ rte_eal_init(int argc, char **argv) + rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER); + rte_eal_mp_wait_lcore(); + ++#ifdef RTE_LIBRTE_DPAA2_PMD ++ if (rte_eal_soc_post_init() < 0) ++ rte_panic("Cannot post init soc\n"); ++#endif ++ + /* Probe & Initialize PCI devices */ + if (rte_eal_pci_probe()) + rte_panic("Cannot probe PCI\n"); +diff --git a/lib/librte_eal/linuxapp/eal/eal_soc.c b/lib/librte_eal/linuxapp/eal/eal_soc.c +new file mode 100644 +index 0000000..32ae172 +--- /dev/null ++++ b/lib/librte_eal/linuxapp/eal/eal_soc.c +@@ -0,0 +1,84 @@ ++/*- ++ * BSD LICENSE ++ * ++ * Copyright(c) 2016 Freescale Semiconductor, Inc. All rights reserved. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * * Neither the name of Freescale Semiconductor, Inc or the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "eal_private.h" ++ ++#ifdef RTE_LIBRTE_DPAA2_PMD ++#include "eal_vfio_fsl_mc.h" ++#endif ++ ++ ++#if (defined RTE_LIBRTE_DPAA_PMD) ++extern int usdpaa_pre_rte_eal_init(void); ++extern int usdpaa_post_rte_eal_init(void); ++#endif ++ ++ ++/* Initialize any soc init related functions if any before thread creation*/ ++int ++rte_eal_soc_pre_init(void) ++{ ++#ifdef RTE_LIBRTE_DPAA2_PMD ++ if (rte_eal_dpaa2_init() < 0) ++ RTE_LOG(WARNING, EAL, "Cannot init FSL_MC SCAN \n"); ++#endif ++#if (defined RTE_LIBRTE_DPAA_PMD) ++ if (usdpaa_pre_rte_eal_init()) ++ RTE_LOG(WARNING, EAL, "Cannot init FSL_DPAA \n"); ++#endif ++ return 0; ++} ++ ++/* Initialize any soc init related functions if any after thread creation*/ ++int ++rte_eal_soc_post_init(void) ++{ ++#if (defined RTE_LIBRTE_DPAA_PMD) ++ if (usdpaa_post_rte_eal_init()) { ++ RTE_LOG(WARNING, EAL, "dpaa1: usdpaa portal init failed\n"); ++ } ++#endif ++ return 0; ++} ++ +diff --git a/lib/librte_eal/linuxapp/eal/eal_vfio_fsl_mc.c b/lib/librte_eal/linuxapp/eal/eal_vfio_fsl_mc.c +new file mode 100644 +index 0000000..c71d8d6 +--- /dev/null ++++ b/lib/librte_eal/linuxapp/eal/eal_vfio_fsl_mc.c +@@ -0,0 +1,653 @@ ++/*- ++ * BSD LICENSE ++ * ++ * Copyright(c) 2014 Freescale Semiconductor. All rights reserved. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * * Neither the name of Freescale Semiconductor nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "rte_pci.h" ++#include "eal_vfio.h" ++ ++#include ++ ++#include "eal_vfio_fsl_mc.h" ++ ++#include "rte_pci_dev_ids.h" ++#include "eal_filesystem.h" ++#include "eal_private.h" ++ ++#ifndef VFIO_MAX_GROUPS ++#define VFIO_MAX_GROUPS 64 ++#endif ++ ++//#define DPAA2_STAGE2_STASHING ++ ++/** Pathname of FSL-MC devices directory. */ ++#define SYSFS_FSL_MC_DEVICES "/sys/bus/fsl-mc/devices" ++ ++/* Number of VFIO containers & groups with in */ ++static struct vfio_group vfio_groups[VFIO_MAX_GRP]; ++static struct vfio_container vfio_containers[VFIO_MAX_CONTAINERS]; ++static char *ls2bus_container; ++static int container_device_fd; ++static uint32_t *msi_intr_vaddr; ++void *(*mcp_ptr_list); ++static uint32_t mcp_id; ++ ++static int vfio_connect_container(struct vfio_group *vfio_group) ++{ ++ struct vfio_container *container; ++ int i, fd, ret; ++ ++ /* Try connecting to vfio container already created */ ++ for (i = 0; i < VFIO_MAX_CONTAINERS; i++) { ++ container = &vfio_containers[i]; ++ if (!ioctl(vfio_group->fd, VFIO_GROUP_SET_CONTAINER, &container->fd)) { ++ RTE_LOG(ERR, EAL, "Container pre-exists with FD[0x%x]" ++ " for this group\n", container->fd); ++ vfio_group->container = container; ++ return 0; ++ } ++ } ++ ++ /* Opens main vfio file descriptor which represents the "container" */ ++ fd = open("/dev/vfio/vfio", O_RDWR); ++ if (fd < 0) { ++ RTE_LOG(ERR, EAL, "vfio: failed to open /dev/vfio/vfio\n"); ++ return -errno; ++ } ++ ++ ret = ioctl(fd, VFIO_GET_API_VERSION); ++ if (ret != VFIO_API_VERSION) { ++ RTE_LOG(ERR, EAL, "vfio: supported vfio version: %d, " ++ "reported version: %d", VFIO_API_VERSION, ret); ++ close(fd); ++ return -EINVAL; ++ } ++#ifndef DPAA2_STAGE2_STASHING ++ /* Check whether support for SMMU type IOMMU prresent or not */ ++ if (ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1_IOMMU)) { ++ /* Connect group to container */ ++ ret = ioctl(vfio_group->fd, VFIO_GROUP_SET_CONTAINER, &fd); ++ if (ret) { ++ RTE_LOG(ERR, EAL, "vfio: failed to set group container:\n"); ++ close(fd); ++ return -errno; ++ } ++ ++ ret = ioctl(fd, VFIO_SET_IOMMU, VFIO_TYPE1_IOMMU); ++ if (ret) { ++ RTE_LOG(ERR, EAL, "vfio: failed to set iommu for container:\n"); ++ close(fd); ++ return -errno; ++ } ++ } else { ++ RTE_LOG(ERR, EAL, "vfio error: No supported IOMMU\n"); ++ close(fd); ++ return -EINVAL; ++ } ++#else ++ /* Check whether support for SMMU type IOMMU stage 2 present or not */ ++ if (ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1_NESTING_IOMMU)) { ++ /* Connect group to container */ ++ ret = ioctl(vfio_group->fd, VFIO_GROUP_SET_CONTAINER, &fd); ++ if (ret) { ++ RTE_LOG(ERR, EAL, "vfio: failed to set group container:\n"); ++ close(fd); ++ return -errno; ++ } ++ ++ ret = ioctl(fd, VFIO_SET_IOMMU, VFIO_TYPE1_NESTING_IOMMU); ++ if (ret) { ++ RTE_LOG(ERR, EAL, "vfio: failed to set iommu-2 for container:\n"); ++ close(fd); ++ return -errno; ++ } ++ } else { ++ RTE_LOG(ERR, EAL, "vfio error: No supported IOMMU-2\n"); ++ close(fd); ++ return -EINVAL; ++ } ++#endif ++ container = NULL; ++ for (i = 0; i < VFIO_MAX_CONTAINERS; i++) { ++ if (vfio_containers[i].used) ++ continue; ++ RTE_LOG(ERR, EAL, "DPAA2-Unused container at index %d\n", i); ++ container = &vfio_containers[i]; ++ } ++ if (!container) { ++ RTE_LOG(ERR, EAL, "vfio error: No Free Container Found\n"); ++ close(fd); ++ return -ENOMEM; ++ } ++ ++ container->used = 1; ++ container->fd = fd; ++ container->group_list[container->index] = vfio_group; ++ vfio_group->container = container; ++ container->index++; ++ return 0; ++} ++ ++static int vfio_map_irq_region(struct vfio_group *group) ++{ ++ int ret; ++ unsigned long *vaddr = NULL; ++ struct vfio_iommu_type1_dma_map map = { ++ .argsz = sizeof(map), ++ .flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE, ++ .vaddr = 0x6030000, ++ .iova = 0x6030000, ++ .size = 0x1000, ++ }; ++ ++ vaddr = (unsigned long *)mmap(NULL, 0x1000, PROT_WRITE | ++ PROT_READ, MAP_SHARED, container_device_fd, 0x6030000); ++ if (vaddr == MAP_FAILED) { ++ RTE_LOG(ERR, EAL, " mapping GITS region (errno = %d)", errno); ++ return -errno; ++ } ++ ++ msi_intr_vaddr = (uint32_t *)((char *)(vaddr) + 64); ++ map.vaddr = (unsigned long)vaddr; ++ ret = ioctl(group->container->fd, VFIO_IOMMU_MAP_DMA, &map); ++ if (ret == 0) ++ return 0; ++ ++ RTE_LOG(ERR, EAL, "vfio_map_irq_region fails (errno = %d)", errno); ++ return -errno; ++} ++ ++int vfio_dmamap_mem_region(uint64_t vaddr, ++ uint64_t iova, ++ uint64_t size) ++{ ++ struct vfio_group *group; ++ struct vfio_iommu_type1_dma_map dma_map = { ++ .argsz = sizeof(dma_map), ++ .flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE, ++ }; ++ ++ dma_map.vaddr = vaddr; ++ dma_map.size = size; ++ dma_map.iova = iova; ++ ++ /* SET DMA MAP for IOMMU */ ++ group = &vfio_groups[0]; ++ if (ioctl(group->container->fd, VFIO_IOMMU_MAP_DMA, &dma_map)) { ++ /* todo changes these to RTE_LOG */ ++ RTE_LOG(ERR, EAL, "SWP: VFIO_IOMMU_MAP_DMA API Error %d.\n", errno); ++ return -1; ++ } ++ return 0; ++} ++ ++static int32_t setup_dmamap(void) ++{ ++ int ret; ++ struct vfio_group *group; ++ struct vfio_iommu_type1_dma_map dma_map = { ++ .argsz = sizeof(struct vfio_iommu_type1_dma_map), ++ .flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE, ++ }; ++ ++ int i; ++ const struct rte_memseg *memseg; ++ ++ for (i = 0; i < RTE_MAX_MEMSEG; i++) { ++ memseg = rte_eal_get_physmem_layout(); ++ if (memseg == NULL) { ++ RTE_LOG(ERR, EAL, ++ "\nError Cannot get physical layout\n"); ++ return -ENODEV; ++ } ++ ++ if (memseg[i].addr == NULL && memseg[i].len == 0) { ++ break; ++ } ++ ++ dma_map.size = memseg[i].len; ++ dma_map.vaddr = memseg[i].addr_64; ++#ifdef RTE_LIBRTE_DPAA2_USE_PHYS_IOVA ++ dma_map.iova = memseg[i].phys_addr; ++#else ++ dma_map.iova = dma_map.vaddr; ++#endif ++ ++ /* SET DMA MAP for IOMMU */ ++ group = &vfio_groups[0]; ++ ++ printf("-->Initial SHM Virtual ADDR %llX\n", dma_map.vaddr); ++ printf("-----> DMA size 0x%llX\n", dma_map.size); ++ ret = ioctl(group->container->fd, VFIO_IOMMU_MAP_DMA, &dma_map); ++ if (ret) { ++ RTE_LOG(ERR, EAL, ++ "\nErr: VFIO_IOMMU_MAP_DMA API Error %d.\n", ++ errno); ++ return ret; ++ } ++ printf("-----> dma_map.vaddr = 0x%llX\n", dma_map.vaddr); ++ } ++ ++ /* TODO - This is a W.A. as VFIO currently does not add the mapping of ++ the interrupt region to SMMU. This should be removed once the ++ support is added in the Kernel. ++ */ ++ vfio_map_irq_region(group); ++ ++ return 0; ++} ++ ++static int vfio_set_group(struct vfio_group *group, int groupid) ++{ ++ char path[PATH_MAX]; ++ struct vfio_group_status status = { .argsz = sizeof(status) }; ++ ++ /* Open the VFIO file corresponding to the IOMMU group */ ++ snprintf(path, sizeof(path), "/dev/vfio/%d", groupid); ++ ++ group->fd = open(path, O_RDWR); ++ if (group->fd < 0) { ++ RTE_LOG(ERR, EAL, "vfio: error opening %s\n", path); ++ return -1; ++ } ++ ++ /* Test & Verify that group is VIABLE & AVAILABLE */ ++ if (ioctl(group->fd, VFIO_GROUP_GET_STATUS, &status)) { ++ RTE_LOG(ERR, EAL, "vfio: error getting group status\n"); ++ close(group->fd); ++ return -1; ++ } ++ if (!(status.flags & VFIO_GROUP_FLAGS_VIABLE)) { ++ RTE_LOG(ERR, EAL, "vfio: group not viable\n"); ++ close(group->fd); ++ return -1; ++ } ++ /* Since Group is VIABLE, Store the groupid */ ++ group->groupid = groupid; ++ ++ /* Now connect this IOMMU group to given container */ ++ if (vfio_connect_container(group)) { ++ RTE_LOG(ERR, EAL, ++ "vfio: error sonnecting container with group %d\n", ++ groupid); ++ close(group->fd); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int32_t setup_vfio_grp(char *vfio_container) ++{ ++ char path[PATH_MAX]; ++ char iommu_group_path[PATH_MAX], *group_name; ++ struct vfio_group *group = NULL; ++ struct stat st; ++ int groupid; ++ int ret, len, i; ++ ++ printf("\tProcessing Container = %s\n", vfio_container); ++ sprintf(path, "/sys/bus/fsl-mc/devices/%s", vfio_container); ++ /* Check whether ls-container exists or not */ ++ printf("\tcontainer device path = %s\n", path); ++ if (stat(path, &st) < 0) { ++ RTE_LOG(ERR, EAL, "vfio: Error (%d) getting FSL-MC device (%s)\n", ++ errno, path); ++ return -errno; ++ } ++ ++ /* DPRC container exists. NOw checkout the IOMMU Group */ ++ strncat(path, "/iommu_group", sizeof(path) - strlen(path) - 1); ++ ++ len = readlink(path, iommu_group_path, PATH_MAX); ++ if (len == -1) { ++ RTE_LOG(ERR, EAL, "\tvfio: error no iommu_group for device\n"); ++ RTE_LOG(ERR, EAL, "\t%s: len = %d, errno = %d\n", ++ path, len, errno); ++ return -errno; ++ } ++ ++ iommu_group_path[len] = 0; ++ group_name = basename(iommu_group_path); ++ if (sscanf(group_name, "%d", &groupid) != 1) { ++ RTE_LOG(ERR, EAL, "\tvfio: error reading %s: %m\n", path); ++ return -errno; ++ } ++ ++ RTE_LOG(INFO, EAL, "\tvfio: iommu group id = %d\n", groupid); ++ ++ /* Check if group already exists */ ++ for (i = 0; i < VFIO_MAX_GRP; i++) { ++ group = &vfio_groups[i]; ++ if (group->groupid == groupid) { ++ RTE_LOG(ERR, EAL, "groupid already exists %d\n", groupid); ++ return 0; ++ } ++ } ++ ++ if (vfio_set_group(group, groupid)) { ++ RTE_LOG(ERR, EAL, "group setup failure - %d\n", groupid); ++ return -ENODEV; ++ } ++ ++ /* Get Device information */ ++ ret = ioctl(group->fd, VFIO_GROUP_GET_DEVICE_FD, vfio_container); ++ if (ret < 0) { ++ RTE_LOG(ERR, EAL, "\tvfio: error getting device %s fd from group %d\n", ++ vfio_container, group->groupid); ++ return ret; ++ } ++ container_device_fd = ret; ++ RTE_LOG(INFO, EAL, "vfio: Container FD is [0x%X]\n", container_device_fd); ++ /* Set up SMMU */ ++ ret = setup_dmamap(); ++ if (ret) { ++ RTE_LOG(ERR, EAL, ": Setting dma map\n"); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++ ++static int64_t vfio_map_mcp_obj(struct vfio_group *group, char *mcp_obj) ++{ ++ int64_t v_addr = (int64_t)MAP_FAILED; ++ int32_t ret, mc_fd; ++ ++ struct vfio_device_info d_info = { .argsz = sizeof(d_info) }; ++ struct vfio_region_info reg_info = { .argsz = sizeof(reg_info) }; ++ ++ /* getting the mcp object's fd*/ ++ mc_fd = ioctl(group->fd, VFIO_GROUP_GET_DEVICE_FD, mcp_obj); ++ if (mc_fd < 0) { ++ RTE_LOG(ERR, EAL, "vfio: error getting device %s fd from group %d\n", ++ mcp_obj, group->fd); ++ return v_addr; ++ } ++ ++ /* getting device info*/ ++ ret = ioctl(mc_fd, VFIO_DEVICE_GET_INFO, &d_info); ++ if (ret < 0) { ++ RTE_LOG(ERR, EAL, "vfio: error getting DEVICE_INFO\n"); ++ goto MC_FAILURE; ++ } ++ ++ /* getting device region info*/ ++ ret = ioctl(mc_fd, VFIO_DEVICE_GET_REGION_INFO, ®_info); ++ if (ret < 0) { ++ RTE_LOG(ERR, EAL, "vfio: error getting REGION_INFO\n"); ++ goto MC_FAILURE; ++ } ++ ++ RTE_LOG(INFO, EAL, "region offset = %llx , region size = %llx\n", ++ reg_info.offset, reg_info.size); ++ ++ v_addr = (uint64_t)mmap(NULL, reg_info.size, ++ PROT_WRITE | PROT_READ, MAP_SHARED, ++ mc_fd, reg_info.offset); ++ ++MC_FAILURE: ++ close(mc_fd); ++ ++ return v_addr; ++} ++ ++/* Following function shall fetch total available list of MC devices ++ * from VFIO container & populate private list of devices and other ++ * data structures ++ */ ++static int vfio_process_group_devices(void) ++{ ++ struct vfio_device *vdev; ++ struct vfio_device_info device_info = { .argsz = sizeof(device_info) }; ++ char *temp_obj, *object_type, *mcp_obj, *dev_name; ++ int32_t object_id, i, dev_fd, ret; ++ DIR *d; ++ struct dirent *dir; ++ char path[PATH_MAX]; ++ int64_t v_addr; ++ int ndev_count; ++ struct vfio_group *group = &vfio_groups[0]; ++ ++ sprintf(path, "/sys/kernel/iommu_groups/%d/devices", group->groupid); ++ ++ d = opendir(path); ++ if (!d) { ++ RTE_LOG(ERR, EAL,"Unable to open directory %s\n", path); ++ return -1; ++ } ++ ++ /*Counting the number of devices in a group and getting the mcp ID*/ ++ ndev_count = 0; ++ mcp_obj = NULL; ++ while ((dir = readdir(d)) != NULL) { ++ if (dir->d_type == DT_LNK) { ++ ndev_count++; ++ if (!strncmp("dpmcp", dir->d_name, 5)) { ++ if (mcp_obj) ++ free(mcp_obj); ++ mcp_obj = malloc(sizeof(dir->d_name)); ++ if (!mcp_obj) { ++ RTE_LOG(ERR, EAL, ++ "Unable to allocate memory\n"); ++ return -ENOMEM; ++ } ++ strcpy(mcp_obj, dir->d_name); ++ temp_obj = strtok(dir->d_name, "."); ++ temp_obj = strtok(NULL, "."); ++ sscanf(temp_obj, "%d", &mcp_id); ++ } ++ } ++ } ++ closedir(d); ++ ++ if (!mcp_obj) { ++ RTE_LOG(ERR, EAL,"MCP Object not Found\n"); ++ return -ENODEV; ++ } ++ RTE_LOG(INFO, EAL,"Total devices in conatiner = %d, MCP ID = %d\n", ++ ndev_count, mcp_id); ++ ++ /* Allocate the memory depends upon number of objects in a group*/ ++ group->vfio_device = (struct vfio_device *)malloc(ndev_count * sizeof(struct vfio_device)); ++ if (!(group->vfio_device)) { ++ RTE_LOG(ERR, EAL,"Unable to allocate memory\n"); ++ free(mcp_obj); ++ return -ENOMEM; ++ } ++ ++ /* Allocate memory for MC Portal list */ ++ mcp_ptr_list = malloc(sizeof(void *) * 1); ++ if (!mcp_ptr_list) { ++ RTE_LOG(ERR, EAL, "NO Memory!\n"); ++ free(mcp_obj); ++ goto FAILURE; ++ } ++ ++ v_addr = vfio_map_mcp_obj(group, mcp_obj); ++ free(mcp_obj); ++ if (v_addr == (int64_t)MAP_FAILED) { ++ RTE_LOG(ERR, EAL, "mapping region (errno = %d)\n", errno); ++ goto FAILURE; ++ } ++ ++ RTE_LOG(INFO, EAL, "MC has VIR_ADD = 0x%ld\n", v_addr); ++ ++ mcp_ptr_list[0] = (void *)v_addr; ++ ++ d = opendir(path); ++ if (!d) { ++ RTE_LOG(ERR, EAL, "Directory %s not able to open\n", path); ++ goto FAILURE; ++ } ++ ++ i = 0; ++ printf("\nDPAA2 - Parsing MC Device Objects:\n"); ++ /* Parsing each object and initiating them*/ ++ while ((dir = readdir(d)) != NULL) { ++ if (dir->d_type != DT_LNK) ++ continue; ++ if (!strncmp("dprc", dir->d_name, 4) || !strncmp("dpmcp", dir->d_name, 5)) ++ continue; ++ dev_name = malloc(sizeof(dir->d_name)); ++ if (!dev_name) { ++ RTE_LOG(ERR, EAL, "Unable to allocate memory\n"); ++ goto FAILURE; ++ } ++ strcpy(dev_name, dir->d_name); ++ object_type = strtok(dir->d_name, "."); ++ temp_obj = strtok(NULL, "."); ++ sscanf(temp_obj, "%d", &object_id); ++ RTE_LOG(INFO, EAL, "%s ", dev_name); ++ ++ /* getting the device fd*/ ++ dev_fd = ioctl(group->fd, VFIO_GROUP_GET_DEVICE_FD, dev_name); ++ if (dev_fd < 0) { ++ RTE_LOG(ERR, EAL, "vfio getting device %s fd from group %d\n", ++ dev_name, group->fd); ++ free(dev_name); ++ goto FAILURE; ++ } ++ ++ free(dev_name); ++ vdev = &group->vfio_device[group->object_index++]; ++ vdev->fd = dev_fd; ++ vdev->index = i; ++ i++; ++ /* Get Device inofrmation */ ++ if (ioctl(vdev->fd, VFIO_DEVICE_GET_INFO, &device_info)) { ++ RTE_LOG(ERR, EAL, "VFIO_DEVICE_FSL_MC_GET_INFO failed\n"); ++ goto FAILURE; ++ } ++ ++ if (!strcmp(object_type, "dpni") || ++ !strcmp(object_type, "dpseci")) { ++ struct rte_pci_device *dev; ++ ++ dev = malloc(sizeof(struct rte_pci_device)); ++ if (dev == NULL) { ++ return -1; ++ } ++ memset(dev, 0, sizeof(*dev)); ++ /* store hw_id of dpni/dpseci device */ ++ dev->addr.devid = object_id; ++ dev->id.vendor_id = FSL_VENDOR_ID; ++ dev->id.device_id = (strcmp(object_type, "dpseci"))? ++ FSL_MC_DPNI_DEVID: FSL_MC_DPSECI_DEVID; ++ ++ TAILQ_INSERT_TAIL(&pci_device_list, dev, next); ++ } ++ ++ if (!strcmp(object_type, "dpio")) { ++ dpaa2_create_dpio_device(vdev, &device_info, object_id); ++ } ++ ++ if (!strcmp(object_type, "dpbp")) { ++ dpaa2_create_dpbp_device(object_id); ++ } ++ } ++ closedir(d); ++ ++ ret = dpaa2_affine_qbman_swp(); ++ if (ret) ++ RTE_LOG(ERR, EAL, "%s(): Err in affining qbman swp\n", __func__); ++ ++ return 0; ++ ++FAILURE: ++ free(group->vfio_device); ++ group->vfio_device = NULL; ++ return -1; ++} ++ ++/* ++ * Scan the content of the PCI bus, and the devices in the devices ++ * list ++ */ ++static int ++fsl_mc_scan(void) ++{ ++ char path[PATH_MAX]; ++ struct stat st; ++ ++ ls2bus_container = getenv("DPRC"); ++ ++ if (ls2bus_container == NULL) { ++ RTE_LOG(WARNING, EAL, "vfio container not set in env DPRC\n"); ++ return -1; ++ } ++ ++ snprintf(path, sizeof(path), "%s/%s", SYSFS_FSL_MC_DEVICES, ++ ls2bus_container); ++ /* Check whether LS-Container exists or not */ ++ RTE_LOG(INFO, EAL, "\tcontainer device path = %s\n", path); ++ if (stat(path, &st) < 0) { ++ RTE_LOG(ERR, EAL, "vfio:fsl-mc device does not exists\n"); ++ return -1; ++ } ++ return 0; ++} ++ ++/* Init the FSL-MC- LS2 EAL subsystem */ ++int ++rte_eal_dpaa2_init(void) ++{ ++ if (fsl_mc_scan() < 0) ++ return -1; ++ ++#ifdef VFIO_PRESENT ++ if (setup_vfio_grp(ls2bus_container)) { ++ RTE_LOG(ERR, EAL, "setup_vfio_grp\n"); ++ return -1; ++ } ++ if (vfio_process_group_devices()) { ++ RTE_LOG(ERR, EAL, "vfio_process_group_devices\n"); ++ return -1; ++ } ++#endif ++ return 0; ++} +diff --git a/lib/librte_eal/linuxapp/eal/eal_vfio_fsl_mc.h b/lib/librte_eal/linuxapp/eal/eal_vfio_fsl_mc.h +new file mode 100644 +index 0000000..7fc5ec6 +--- /dev/null ++++ b/lib/librte_eal/linuxapp/eal/eal_vfio_fsl_mc.h +@@ -0,0 +1,102 @@ ++/*- ++ * BSD LICENSE ++ * ++ * Copyright(c) 2014 Freescale Semiconductor. All rights reserved. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * * Neither the name of Freescale Semiconductor nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#ifndef _EAL_VFIO_FSL_MC_H_ ++#define _EAL_VFIO_FSL_MC_H_ ++ ++#include ++#include ++#include ++#include "eal_vfio.h" ++ ++#define FSL_VENDOR_ID 0x1957 ++#define FSL_MC_DPNI_DEVID 7 ++#define FSL_MC_DPSECI_DEVID 3 ++ ++#define VFIO_MAX_GRP 1 ++#define VFIO_MAX_CONTAINERS 1 ++ ++#define DPAA2_MBUF_HW_ANNOTATION 64 ++#define DPAA2_FD_PTA_SIZE 64 ++#define DPAA2_PACKET_LAYOUT_ALIGN 256 ++#if (RTE_CACHE_LINE_SIZE == 128) ++#define DPAA2_RES 128 ++#else ++#define DPAA2_RES 0 ++#endif ++ ++#define DPAA2_ALIGN_ROUNDUP(x, align) ((align) * (((x) + align - 1) / (align))) ++#define DPAA2_ALIGN_ROUNDUP_PTR(x, align)\ ++ ((void *)DPAA2_ALIGN_ROUNDUP((uintptr_t)(x), (uintptr_t)(align))) ++ ++typedef struct vfio_device { ++ int fd; /* fsl_mc root container device ?? */ ++ int index; /*index of child object */ ++ struct vfio_device *child; /* Child object */ ++} vfio_device; ++ ++typedef struct vfio_group { ++ int fd; /* /dev/vfio/"groupid" */ ++ int groupid; ++ struct vfio_container *container; ++ int object_index; ++ struct vfio_device *vfio_device; ++} vfio_group; ++ ++typedef struct vfio_container { ++ int fd; /* /dev/vfio/vfio */ ++ int used; ++ int index; /* index in group list */ ++ struct vfio_group *group_list[VFIO_MAX_GRP]; ++} vfio_container; ++ ++int vfio_dmamap_mem_region( ++ uint64_t vaddr, ++ uint64_t iova, ++ uint64_t size); ++ ++/* initialize the NXP/FSL dpaa2 accelerators */ ++int rte_eal_dpaa2_init(void); ++ ++int dpaa2_create_dpio_device(struct vfio_device *vdev, ++ struct vfio_device_info *obj_info, ++ int object_id); ++ ++int dpaa2_create_dpbp_device(int dpbp_id); ++ ++int dpaa2_affine_qbman_swp(void); ++ ++int dpaa2_affine_qbman_swp_sec(void); ++ ++#endif ++ +diff --git a/lib/librte_mbuf/Makefile b/lib/librte_mbuf/Makefile +index 8d62b0d..92446d1 100644 +--- a/lib/librte_mbuf/Makefile ++++ b/lib/librte_mbuf/Makefile +@@ -36,6 +36,10 @@ LIB = librte_mbuf.a + + CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 + ++ifeq ($(CONFIG_RTE_LIBRTE_DPAA2_PMD),y) ++CFLAGS += -I$(RTE_SDK)/lib/librte_eal/linuxapp/eal ++endif ++ + EXPORT_MAP := rte_mbuf_version.map + + LIBABIVER := 2 +diff --git a/lib/librte_mbuf/rte_mbuf.c b/lib/librte_mbuf/rte_mbuf.c +index dc0467c..c4009ee 100644 +--- a/lib/librte_mbuf/rte_mbuf.c ++++ b/lib/librte_mbuf/rte_mbuf.c +@@ -60,6 +60,59 @@ + #include + #include + ++#ifdef RTE_LIBRTE_DPAA2_PMD ++ ++int __attribute__((weak)) ++hw_mbuf_create_pool( ++struct rte_mempool __rte_unused *mp) ++{ ++ RTE_LOG(WARNING, MBUF, "%s/n", __func__); ++ return -1; ++} ++ ++int __attribute__((weak)) ++hw_mbuf_init( ++ struct rte_mempool __rte_unused*mp, ++ void __rte_unused *_m) ++{ ++ RTE_LOG(WARNING, MBUF, "%s/n", __func__); ++ return -1; ++} ++ ++int __attribute__((weak)) ++hw_mbuf_alloc( ++ struct rte_mempool __rte_unused *mp, ++ void __rte_unused **obj_p) ++{ ++ RTE_LOG(WARNING, MBUF, "%s/n", __func__); ++ return -1; ++} ++ ++int __attribute__((weak)) ++hw_mbuf_free(void __rte_unused *m) ++{ ++ RTE_LOG(WARNING, MBUF, "%s/n", __func__); ++ return -1; ++} ++ ++int __attribute__((weak)) ++hw_mbuf_alloc_bulk(struct rte_mempool __rte_unused *pool, ++ void __rte_unused **obj_table, ++ unsigned __rte_unused count) ++{ ++ RTE_LOG(WARNING, MBUF, "%s/n", __func__); ++ return -1; ++} ++ ++int __attribute__((weak)) ++hw_mbuf_free_bulk(struct rte_mempool __rte_unused *mp, ++ void __rte_unused * const *obj_table, ++ unsigned __rte_unused n) ++{ ++ RTE_LOG(WARNING, MBUF, "%s/n", __func__); ++ return -1; ++} ++#endif + /* + * ctrlmbuf constructor, given as a callback function to + * rte_mempool_create() +@@ -106,6 +159,10 @@ rte_pktmbuf_pool_init(struct rte_mempool *mp, void *opaque_arg) + + mbp_priv = rte_mempool_get_priv(mp); + memcpy(mbp_priv, user_mbp_priv, sizeof(*mbp_priv)); ++#ifdef RTE_LIBRTE_DPAA2_PMD ++ if (mp->flags & MEMPOOL_F_HW_PKT_POOL) ++ hw_mbuf_create_pool(mp); ++#endif + } + + /* +@@ -122,6 +179,12 @@ rte_pktmbuf_init(struct rte_mempool *mp, + struct rte_mbuf *m = _m; + uint32_t mbuf_size, buf_len, priv_size; + ++#ifdef RTE_LIBRTE_DPAA2_PMD ++ if (mp->flags & MEMPOOL_F_HW_PKT_POOL) { ++ if (hw_mbuf_init(mp, m) == 0) ++ return; ++ } ++#endif + priv_size = rte_pktmbuf_priv_size(mp); + mbuf_size = sizeof(struct rte_mbuf) + priv_size; + buf_len = rte_pktmbuf_data_room_size(mp); +@@ -170,7 +233,11 @@ rte_pktmbuf_pool_create(const char *name, unsigned n, + return rte_mempool_create(name, n, elt_size, + cache_size, sizeof(struct rte_pktmbuf_pool_private), + rte_pktmbuf_pool_init, &mbp_priv, rte_pktmbuf_init, NULL, ++#if defined(RTE_LIBRTE_DPAA2_PMD) ++ socket_id, MEMPOOL_F_HW_PKT_POOL); ++#else + socket_id, 0); ++#endif + } + + /* do some sanity checks on a mbuf: panic if it fails */ +diff --git a/lib/librte_mempool/Makefile b/lib/librte_mempool/Makefile +index a6898ef..6116d52 100644 +--- a/lib/librte_mempool/Makefile ++++ b/lib/librte_mempool/Makefile +@@ -36,6 +36,10 @@ LIB = librte_mempool.a + + CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 + ++ifeq ($(CONFIG_RTE_LIBRTE_DPAA2_PMD),y) ++CFLAGS += -I$(RTE_SDK)/lib/librte_mbuf ++CFLAGS += -I$(RTE_SDK)/lib/librte_eal/linuxapp/eal ++endif + EXPORT_MAP := rte_mempool_version.map + + LIBABIVER := 1 +diff --git a/lib/librte_mempool/rte_mempool.c b/lib/librte_mempool/rte_mempool.c +index f8781e1..ac9595d 100644 +--- a/lib/librte_mempool/rte_mempool.c ++++ b/lib/librte_mempool/rte_mempool.c +@@ -60,6 +60,10 @@ + + #include "rte_mempool.h" + ++#ifdef RTE_LIBRTE_DPAA2_PMD ++#include "eal_vfio_fsl_mc.h" ++#endif ++ + TAILQ_HEAD(rte_mempool_list, rte_tailq_entry); + + static struct rte_tailq_elem rte_mempool_tailq = { +@@ -316,6 +320,12 @@ rte_mempool_calc_obj_size(uint32_t elt_size, uint32_t flags, + + /* this is the size of an object, including header and trailer */ + sz->total_size = sz->header_size + sz->elt_size + sz->trailer_size; ++#ifdef RTE_LIBRTE_DPAA2_PMD ++ if (flags & MEMPOOL_F_HW_PKT_POOL) ++ sz->total_size += DPAA2_ALIGN_ROUNDUP( ++ DPAA2_MBUF_HW_ANNOTATION + DPAA2_FD_PTA_SIZE, ++ DPAA2_PACKET_LAYOUT_ALIGN); ++#endif + + return sz->total_size; + } +@@ -590,6 +600,9 @@ rte_mempool_xmem_create(const char *name, unsigned n, unsigned elt_size, + mp->cache_size = cache_size; + mp->cache_flushthresh = CALC_CACHE_FLUSHTHRESH(cache_size); + mp->private_data_size = private_data_size; ++#ifdef RTE_LIBRTE_DPAA2_PMD ++ mp->offload_ptr = UINTPTR_MAX; ++#endif + + /* calculate address of the first element for continuous mempool. */ + obj = (char *)mp + MEMPOOL_HEADER_SIZE(mp, pg_num) + +diff --git a/lib/librte_mempool/rte_mempool.h b/lib/librte_mempool/rte_mempool.h +index 9745bf0..304a434 100644 +--- a/lib/librte_mempool/rte_mempool.h ++++ b/lib/librte_mempool/rte_mempool.h +@@ -215,7 +215,10 @@ struct rte_mempool { + uintptr_t elt_va_end; + /**< Virtual address of the mempool object. */ + phys_addr_t elt_pa[MEMPOOL_PG_NUM_DEFAULT]; ++#ifdef RTE_LIBRTE_DPAA2_PMD + /**< Array of physical page addresses for the mempool objects buffer. */ ++ uintptr_t offload_ptr; ++#endif + + } __rte_cache_aligned; + +@@ -223,7 +226,18 @@ struct rte_mempool { + #define MEMPOOL_F_NO_CACHE_ALIGN 0x0002 /**< Do not align objs on cache lines.*/ + #define MEMPOOL_F_SP_PUT 0x0004 /**< Default put is "single-producer".*/ + #define MEMPOOL_F_SC_GET 0x0008 /**< Default get is "single-consumer".*/ +- ++#ifdef RTE_LIBRTE_DPAA2_PMD ++#define MEMPOOL_F_HW_PKT_POOL 0x0010 /**< HW offload for packet buffer mgmt*/ ++ ++int hw_mbuf_create_pool(struct rte_mempool *mp); ++int hw_mbuf_init(struct rte_mempool *mp, void *_m); ++int hw_mbuf_alloc(struct rte_mempool *mp, void **obj_p); ++int hw_mbuf_free(void *_m); ++int hw_mbuf_alloc_bulk(struct rte_mempool *pool, ++ void **obj_table, unsigned count); ++int hw_mbuf_free_bulk(struct rte_mempool *mp, void * const *obj_table, ++ unsigned n); ++#endif + /** + * @internal When debug is enabled, store some statistics. + * +@@ -877,6 +891,12 @@ static inline void __attribute__((always_inline)) + rte_mempool_put_bulk(struct rte_mempool *mp, void * const *obj_table, + unsigned n) + { ++#ifdef RTE_LIBRTE_DPAA2_PMD ++ if (mp->flags & MEMPOOL_F_HW_PKT_POOL) { ++ if (hw_mbuf_free_bulk(mp, obj_table, n) == 0) ++ return; ++ } ++#endif + __mempool_check_cookies(mp, obj_table, n, 0); + __mempool_put_bulk(mp, obj_table, n, !(mp->flags & MEMPOOL_F_SP_PUT)); + } +@@ -1091,6 +1111,14 @@ static inline int __attribute__((always_inline)) + rte_mempool_get_bulk(struct rte_mempool *mp, void **obj_table, unsigned n) + { + int ret; ++ ++#ifdef RTE_LIBRTE_DPAA2_PMD ++ if (mp->flags & MEMPOOL_F_HW_PKT_POOL) { ++ ret = hw_mbuf_alloc_bulk(mp, obj_table, n); ++ if (ret > -2) ++ return ret; ++ } ++#endif + ret = __mempool_get_bulk(mp, obj_table, n, + !(mp->flags & MEMPOOL_F_SC_GET)); + if (ret == 0) +diff --git a/mk/machine/dpaa2/rte.vars.mk b/mk/machine/dpaa2/rte.vars.mk +new file mode 100644 +index 0000000..8541633 +--- /dev/null ++++ b/mk/machine/dpaa2/rte.vars.mk +@@ -0,0 +1,60 @@ ++# BSD LICENSE ++# ++# Copyright(c) 2016 Freescale Semiconductor, Inc. All rights reserved. ++# ++# Redistribution and use in source and binary forms, with or without ++# modification, are permitted provided that the following conditions ++# are met: ++# ++# * Redistributions of source code must retain the above copyright ++# notice, this list of conditions and the following disclaimer. ++# * Redistributions in binary form must reproduce the above copyright ++# notice, this list of conditions and the following disclaimer in ++# the documentation and/or other materials provided with the ++# distribution. ++# * Neither the name of Freescale Semiconductor nor the names of its ++# contributors may be used to endorse or promote products derived ++# from this software without specific prior written permission. ++# ++# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ ++# ++# machine: ++# ++# - can define ARCH variable (overridden by cmdline value) ++# - can define CROSS variable (overridden by cmdline value) ++# - define MACHINE_CFLAGS variable (overridden by cmdline value) ++# - define MACHINE_LDFLAGS variable (overridden by cmdline value) ++# - define MACHINE_ASFLAGS variable (overridden by cmdline value) ++# - can define CPU_CFLAGS variable (overridden by cmdline value) that ++# overrides the one defined in arch. ++# - can define CPU_LDFLAGS variable (overridden by cmdline value) that ++# overrides the one defined in arch. ++# - can define CPU_ASFLAGS variable (overridden by cmdline value) that ++# overrides the one defined in arch. ++# - may override any previously defined variable ++# ++ ++# ARCH = ++# CROSS = ++# MACHINE_CFLAGS = ++# MACHINE_LDFLAGS = ++# MACHINE_ASFLAGS = ++# CPU_CFLAGS = ++# CPU_LDFLAGS = ++# CPU_ASFLAGS = ++MACHINE_CFLAGS += -march=armv8-a ++ ++ifdef CONFIG_RTE_ARCH_ARM_TUNE ++MACHINE_CFLAGS += -mcpu=$(CONFIG_RTE_ARCH_ARM_TUNE) ++endif +diff --git a/mk/rte.app.mk b/mk/rte.app.mk +index c66e491..ee25ba3 100644 +--- a/mk/rte.app.mk ++++ b/mk/rte.app.mk +@@ -125,6 +125,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE) += -lrte_cfgfile + _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += -lrte_pmd_bond + + _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += -lrte_pmd_xenvirt ++_LDLIBS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD) += -lrte_pmd_dpaa2 + + ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),n) + # plugins (link only if static libraries) +-- +2.5.0 + -- cgit 1.2.3-korg From 808b2db9648b444dec906d27050afd9af6138f90 Mon Sep 17 00:00:00 2001 From: Sachin Date: Sat, 18 Jun 2016 15:56:35 +0530 Subject: Improving cross_ldflags arguments for dpaa2 platform - This helps in avoiding manual export of LD_LIBRARY_PATH for /usr/lib64/ Change-Id: I15fc9c9f961848411b093c891ca9517ef4e074a0 Signed-off-by: Sachin --- build-data/platforms/dpaa2.mk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'build-data/platforms/dpaa2.mk') diff --git a/build-data/platforms/dpaa2.mk b/build-data/platforms/dpaa2.mk index 7833b876..fd33d22d 100644 --- a/build-data/platforms/dpaa2.mk +++ b/build-data/platforms/dpaa2.mk @@ -18,7 +18,8 @@ dpaa2_target = aarch64-linux-gnu dpaa2_mtune = cortex-A57 dpaa2_march = "armv8-a+fp+simd+crc+crypto" dpaa2_cross_ldflags = \ - -Wl,--dynamic-linker=/lib/ld-linux-aarch64.so.1 + -Wl,--dynamic-linker=/lib/ld-linux-aarch64.so.1 \ + -Wl,-rpath=/usr/lib64 dpaa2_native_tools = vppapigen dpaa2_root_packages = vpp vlib vlib-api vnet svm vpp-api-test -- cgit 1.2.3-korg From ea3e1fc8754d7ebeca85ecc448b263f6ccb6ae6f Mon Sep 17 00:00:00 2001 From: Ole Troan Date: Fri, 24 Jun 2016 20:10:30 +0200 Subject: Plugins: Clean up the plugin directory so that each plugin has its own directory and GNU autotools setup. Change-Id: I6c59d1297389c9413db0c0b9bdf3b759080bf1b8 Signed-off-by: Ole Troan --- build-data/platforms/arm32.mk | 4 +- build-data/platforms/dpaa2.mk | 4 +- build-data/platforms/qppc.mk | 4 +- build-data/platforms/thunder.mk | 4 +- build-data/platforms/vpp_lite.mk | 4 +- plugins/Makefile.am | 136 +- plugins/build-data/packages/ioam-plugin.mk | 47 + plugins/build-data/packages/sixrd-plugin.mk | 47 + plugins/build-data/packages/vcgn-plugin.mk | 47 + plugins/configure.ac | 57 + plugins/ioam-plugin/Makefile.am | 62 + plugins/ioam-plugin/configure.ac | 17 + plugins/ioam-plugin/ioam/encap/ip6_ioam_pot.c | 282 ++ plugins/ioam-plugin/ioam/lib-pot/math64.h | 159 + plugins/ioam-plugin/ioam/lib-pot/pot.api | 97 + plugins/ioam-plugin/ioam/lib-pot/pot_all_api_h.h | 16 + plugins/ioam-plugin/ioam/lib-pot/pot_api.c | 230 ++ plugins/ioam-plugin/ioam/lib-pot/pot_msg_enum.h | 28 + plugins/ioam-plugin/ioam/lib-pot/pot_test.c | 313 ++ plugins/ioam-plugin/ioam/lib-pot/pot_util.c | 446 +++ plugins/ioam-plugin/ioam/lib-pot/pot_util.h | 195 + plugins/plugins/ioam/encap/ip6_ioam_pot.c | 282 -- plugins/plugins/ioam/lib-pot/math64.h | 159 - plugins/plugins/ioam/lib-pot/pot.api | 97 - plugins/plugins/ioam/lib-pot/pot_all_api_h.h | 16 - plugins/plugins/ioam/lib-pot/pot_api.c | 230 -- plugins/plugins/ioam/lib-pot/pot_msg_enum.h | 28 - plugins/plugins/ioam/lib-pot/pot_test.c | 313 -- plugins/plugins/ioam/lib-pot/pot_util.c | 446 --- plugins/plugins/ioam/lib-pot/pot_util.h | 195 - plugins/plugins/sixrd/ip4_sixrd.c | 127 - plugins/plugins/sixrd/ip6_sixrd.c | 129 - plugins/plugins/sixrd/sixrd.c | 379 -- plugins/plugins/sixrd/sixrd.h | 144 - plugins/plugins/vcgn/README | 100 - plugins/plugins/vcgn/cgn_bitmap.h | 133 - plugins/plugins/vcgn/cgse_defs.h | 88 - plugins/plugins/vcgn/cnat_bulk_port.c | 964 ----- plugins/plugins/vcgn/cnat_bulk_port.h | 157 - plugins/plugins/vcgn/cnat_bulk_port_defs.h | 57 - plugins/plugins/vcgn/cnat_cli.h | 206 -- plugins/plugins/vcgn/cnat_cli_handler.c | 961 ----- plugins/plugins/vcgn/cnat_common_api.h | 22 - plugins/plugins/vcgn/cnat_config.c | 77 - plugins/plugins/vcgn/cnat_config.h | 582 --- plugins/plugins/vcgn/cnat_config_api.h | 46 - plugins/plugins/vcgn/cnat_db.h | 701 ---- plugins/plugins/vcgn/cnat_db_scanner.c | 493 --- plugins/plugins/vcgn/cnat_db_v2.c | 3802 -------------------- plugins/plugins/vcgn/cnat_debug_msg_handler.c | 1780 --------- plugins/plugins/vcgn/cnat_global.c | 79 - plugins/plugins/vcgn/cnat_global.h | 87 - plugins/plugins/vcgn/cnat_ipv4_icmp.h | 60 - .../vcgn/cnat_ipv4_icmp_error_inside_input.c | 476 --- .../vcgn/cnat_ipv4_icmp_error_outside_input.c | 452 --- .../vcgn/cnat_ipv4_icmp_query_inside_input.c | 404 --- .../cnat_ipv4_icmp_query_inside_input_exception.c | 235 -- .../vcgn/cnat_ipv4_icmp_query_outside_input.c | 381 -- plugins/plugins/vcgn/cnat_ipv4_tcp_inside_input.c | 424 --- .../vcgn/cnat_ipv4_tcp_inside_input_exceptions.c | 314 -- plugins/plugins/vcgn/cnat_ipv4_tcp_outside_input.c | 382 -- plugins/plugins/vcgn/cnat_ipv4_udp.h | 41 - plugins/plugins/vcgn/cnat_ipv4_udp_inside_input.c | 508 --- .../vcgn/cnat_ipv4_udp_inside_input_exceptions.c | 283 -- plugins/plugins/vcgn/cnat_ipv4_udp_outside_input.c | 605 ---- plugins/plugins/vcgn/cnat_log_api.h | 114 - plugins/plugins/vcgn/cnat_log_common.h | 79 - plugins/plugins/vcgn/cnat_logging.c | 3518 ------------------ plugins/plugins/vcgn/cnat_logging.h | 1091 ------ plugins/plugins/vcgn/cnat_pcp_server.h | 398 -- plugins/plugins/vcgn/cnat_ports.c | 1113 ------ plugins/plugins/vcgn/cnat_ports.h | 208 -- plugins/plugins/vcgn/cnat_show.c | 810 ----- plugins/plugins/vcgn/cnat_show_api.h | 40 - plugins/plugins/vcgn/cnat_show_response.h | 580 --- plugins/plugins/vcgn/cnat_syslog.c | 1787 --------- plugins/plugins/vcgn/cnat_syslog.h | 190 - plugins/plugins/vcgn/cnat_util.c | 2256 ------------ plugins/plugins/vcgn/cnat_v4_ftp_alg.h | 133 - plugins/plugins/vcgn/cnat_v4_functions.c | 364 -- plugins/plugins/vcgn/cnat_v4_functions.h | 342 -- plugins/plugins/vcgn/cnat_v4_pptp_alg.h | 150 - plugins/plugins/vcgn/cnat_v4_tcp_in2out_stages.c | 679 ---- plugins/plugins/vcgn/cnat_va_db.c | 286 -- plugins/plugins/vcgn/cnat_va_db.h | 121 - plugins/plugins/vcgn/dslite_db.h | 170 - plugins/plugins/vcgn/dslite_defs.h | 336 -- plugins/plugins/vcgn/index_list.c | 336 -- plugins/plugins/vcgn/index_list.h | 118 - plugins/plugins/vcgn/nat64_db.h | 480 --- plugins/plugins/vcgn/nat64_defs.h | 576 --- plugins/plugins/vcgn/nat64_tcp_sm.h | 91 - plugins/plugins/vcgn/platform_common.h | 136 - plugins/plugins/vcgn/platform_common_override.h | 304 -- plugins/plugins/vcgn/spp_ctx.h | 76 - plugins/plugins/vcgn/spp_platform_trace_log.c | 989 ----- plugins/plugins/vcgn/spp_platform_trace_log.h | 358 -- plugins/plugins/vcgn/spp_timers.h | 139 - plugins/plugins/vcgn/tcp_header_definitions.h | 1582 -------- plugins/plugins/vcgn/vcgn_classify.c | 1508 -------- plugins/plugins/vcgn/vcgn_db.h | 117 - plugins/sample-plugin/Makefile.am | 5 +- plugins/sixrd-plugin/Makefile.am | 37 + plugins/sixrd-plugin/configure.ac | 17 + plugins/sixrd-plugin/sixrd/ip4_sixrd.c | 127 + plugins/sixrd-plugin/sixrd/ip6_sixrd.c | 129 + plugins/sixrd-plugin/sixrd/sixrd.c | 379 ++ plugins/sixrd-plugin/sixrd/sixrd.h | 144 + plugins/vcgn-plugin/Makefile.am | 99 + plugins/vcgn-plugin/configure.ac | 17 + plugins/vcgn-plugin/vcgn/README | 100 + plugins/vcgn-plugin/vcgn/cgn_bitmap.h | 133 + plugins/vcgn-plugin/vcgn/cgse_defs.h | 88 + plugins/vcgn-plugin/vcgn/cnat_bulk_port.c | 964 +++++ plugins/vcgn-plugin/vcgn/cnat_bulk_port.h | 157 + plugins/vcgn-plugin/vcgn/cnat_bulk_port_defs.h | 57 + plugins/vcgn-plugin/vcgn/cnat_cli.h | 206 ++ plugins/vcgn-plugin/vcgn/cnat_cli_handler.c | 961 +++++ plugins/vcgn-plugin/vcgn/cnat_common_api.h | 22 + plugins/vcgn-plugin/vcgn/cnat_config.c | 77 + plugins/vcgn-plugin/vcgn/cnat_config.h | 582 +++ plugins/vcgn-plugin/vcgn/cnat_config_api.h | 46 + plugins/vcgn-plugin/vcgn/cnat_db.h | 701 ++++ plugins/vcgn-plugin/vcgn/cnat_db_scanner.c | 493 +++ plugins/vcgn-plugin/vcgn/cnat_db_v2.c | 3802 ++++++++++++++++++++ plugins/vcgn-plugin/vcgn/cnat_debug_msg_handler.c | 1780 +++++++++ plugins/vcgn-plugin/vcgn/cnat_global.c | 79 + plugins/vcgn-plugin/vcgn/cnat_global.h | 87 + plugins/vcgn-plugin/vcgn/cnat_ipv4_icmp.h | 60 + .../vcgn/cnat_ipv4_icmp_error_inside_input.c | 476 +++ .../vcgn/cnat_ipv4_icmp_error_outside_input.c | 452 +++ .../vcgn/cnat_ipv4_icmp_query_inside_input.c | 404 +++ .../cnat_ipv4_icmp_query_inside_input_exception.c | 235 ++ .../vcgn/cnat_ipv4_icmp_query_outside_input.c | 381 ++ .../vcgn-plugin/vcgn/cnat_ipv4_tcp_inside_input.c | 424 +++ .../vcgn/cnat_ipv4_tcp_inside_input_exceptions.c | 314 ++ .../vcgn-plugin/vcgn/cnat_ipv4_tcp_outside_input.c | 382 ++ plugins/vcgn-plugin/vcgn/cnat_ipv4_udp.h | 41 + .../vcgn-plugin/vcgn/cnat_ipv4_udp_inside_input.c | 508 +++ .../vcgn/cnat_ipv4_udp_inside_input_exceptions.c | 283 ++ .../vcgn-plugin/vcgn/cnat_ipv4_udp_outside_input.c | 605 ++++ plugins/vcgn-plugin/vcgn/cnat_log_api.h | 114 + plugins/vcgn-plugin/vcgn/cnat_log_common.h | 79 + plugins/vcgn-plugin/vcgn/cnat_logging.c | 3518 ++++++++++++++++++ plugins/vcgn-plugin/vcgn/cnat_logging.h | 1091 ++++++ plugins/vcgn-plugin/vcgn/cnat_pcp_server.h | 398 ++ plugins/vcgn-plugin/vcgn/cnat_ports.c | 1113 ++++++ plugins/vcgn-plugin/vcgn/cnat_ports.h | 208 ++ plugins/vcgn-plugin/vcgn/cnat_show.c | 810 +++++ plugins/vcgn-plugin/vcgn/cnat_show_api.h | 40 + plugins/vcgn-plugin/vcgn/cnat_show_response.h | 580 +++ plugins/vcgn-plugin/vcgn/cnat_syslog.c | 1787 +++++++++ plugins/vcgn-plugin/vcgn/cnat_syslog.h | 190 + plugins/vcgn-plugin/vcgn/cnat_util.c | 2256 ++++++++++++ plugins/vcgn-plugin/vcgn/cnat_v4_ftp_alg.h | 133 + plugins/vcgn-plugin/vcgn/cnat_v4_functions.c | 364 ++ plugins/vcgn-plugin/vcgn/cnat_v4_functions.h | 342 ++ plugins/vcgn-plugin/vcgn/cnat_v4_pptp_alg.h | 150 + .../vcgn-plugin/vcgn/cnat_v4_tcp_in2out_stages.c | 679 ++++ plugins/vcgn-plugin/vcgn/cnat_va_db.c | 286 ++ plugins/vcgn-plugin/vcgn/cnat_va_db.h | 121 + plugins/vcgn-plugin/vcgn/dslite_db.h | 170 + plugins/vcgn-plugin/vcgn/dslite_defs.h | 336 ++ plugins/vcgn-plugin/vcgn/index_list.c | 336 ++ plugins/vcgn-plugin/vcgn/index_list.h | 118 + plugins/vcgn-plugin/vcgn/nat64_db.h | 480 +++ plugins/vcgn-plugin/vcgn/nat64_defs.h | 576 +++ plugins/vcgn-plugin/vcgn/nat64_tcp_sm.h | 91 + plugins/vcgn-plugin/vcgn/platform_common.h | 136 + .../vcgn-plugin/vcgn/platform_common_override.h | 304 ++ plugins/vcgn-plugin/vcgn/spp_ctx.h | 76 + plugins/vcgn-plugin/vcgn/spp_platform_trace_log.c | 989 +++++ plugins/vcgn-plugin/vcgn/spp_platform_trace_log.h | 358 ++ plugins/vcgn-plugin/vcgn/spp_timers.h | 139 + plugins/vcgn-plugin/vcgn/tcp_header_definitions.h | 1582 ++++++++ plugins/vcgn-plugin/vcgn/vcgn_classify.c | 1508 ++++++++ plugins/vcgn-plugin/vcgn/vcgn_db.h | 117 + 177 files changed, 39491 insertions(+), 39157 deletions(-) create mode 100644 plugins/build-data/packages/ioam-plugin.mk create mode 100644 plugins/build-data/packages/sixrd-plugin.mk create mode 100644 plugins/build-data/packages/vcgn-plugin.mk create mode 100644 plugins/ioam-plugin/Makefile.am create mode 100644 plugins/ioam-plugin/configure.ac create mode 100644 plugins/ioam-plugin/ioam/encap/ip6_ioam_pot.c create mode 100644 plugins/ioam-plugin/ioam/lib-pot/math64.h create mode 100644 plugins/ioam-plugin/ioam/lib-pot/pot.api create mode 100644 plugins/ioam-plugin/ioam/lib-pot/pot_all_api_h.h create mode 100644 plugins/ioam-plugin/ioam/lib-pot/pot_api.c create mode 100644 plugins/ioam-plugin/ioam/lib-pot/pot_msg_enum.h create mode 100644 plugins/ioam-plugin/ioam/lib-pot/pot_test.c create mode 100644 plugins/ioam-plugin/ioam/lib-pot/pot_util.c create mode 100644 plugins/ioam-plugin/ioam/lib-pot/pot_util.h delete mode 100644 plugins/plugins/ioam/encap/ip6_ioam_pot.c delete mode 100644 plugins/plugins/ioam/lib-pot/math64.h delete mode 100644 plugins/plugins/ioam/lib-pot/pot.api delete mode 100644 plugins/plugins/ioam/lib-pot/pot_all_api_h.h delete mode 100644 plugins/plugins/ioam/lib-pot/pot_api.c delete mode 100644 plugins/plugins/ioam/lib-pot/pot_msg_enum.h delete mode 100644 plugins/plugins/ioam/lib-pot/pot_test.c delete mode 100644 plugins/plugins/ioam/lib-pot/pot_util.c delete mode 100644 plugins/plugins/ioam/lib-pot/pot_util.h delete mode 100644 plugins/plugins/sixrd/ip4_sixrd.c delete mode 100644 plugins/plugins/sixrd/ip6_sixrd.c delete mode 100644 plugins/plugins/sixrd/sixrd.c delete mode 100644 plugins/plugins/sixrd/sixrd.h delete mode 100644 plugins/plugins/vcgn/README delete mode 100644 plugins/plugins/vcgn/cgn_bitmap.h delete mode 100644 plugins/plugins/vcgn/cgse_defs.h delete mode 100644 plugins/plugins/vcgn/cnat_bulk_port.c delete mode 100644 plugins/plugins/vcgn/cnat_bulk_port.h delete mode 100644 plugins/plugins/vcgn/cnat_bulk_port_defs.h delete mode 100644 plugins/plugins/vcgn/cnat_cli.h delete mode 100644 plugins/plugins/vcgn/cnat_cli_handler.c delete mode 100644 plugins/plugins/vcgn/cnat_common_api.h delete mode 100644 plugins/plugins/vcgn/cnat_config.c delete mode 100644 plugins/plugins/vcgn/cnat_config.h delete mode 100644 plugins/plugins/vcgn/cnat_config_api.h delete mode 100644 plugins/plugins/vcgn/cnat_db.h delete mode 100644 plugins/plugins/vcgn/cnat_db_scanner.c delete mode 100644 plugins/plugins/vcgn/cnat_db_v2.c delete mode 100644 plugins/plugins/vcgn/cnat_debug_msg_handler.c delete mode 100644 plugins/plugins/vcgn/cnat_global.c delete mode 100644 plugins/plugins/vcgn/cnat_global.h delete mode 100644 plugins/plugins/vcgn/cnat_ipv4_icmp.h delete mode 100644 plugins/plugins/vcgn/cnat_ipv4_icmp_error_inside_input.c delete mode 100644 plugins/plugins/vcgn/cnat_ipv4_icmp_error_outside_input.c delete mode 100644 plugins/plugins/vcgn/cnat_ipv4_icmp_query_inside_input.c delete mode 100644 plugins/plugins/vcgn/cnat_ipv4_icmp_query_inside_input_exception.c delete mode 100644 plugins/plugins/vcgn/cnat_ipv4_icmp_query_outside_input.c delete mode 100644 plugins/plugins/vcgn/cnat_ipv4_tcp_inside_input.c delete mode 100644 plugins/plugins/vcgn/cnat_ipv4_tcp_inside_input_exceptions.c delete mode 100644 plugins/plugins/vcgn/cnat_ipv4_tcp_outside_input.c delete mode 100644 plugins/plugins/vcgn/cnat_ipv4_udp.h delete mode 100644 plugins/plugins/vcgn/cnat_ipv4_udp_inside_input.c delete mode 100644 plugins/plugins/vcgn/cnat_ipv4_udp_inside_input_exceptions.c delete mode 100644 plugins/plugins/vcgn/cnat_ipv4_udp_outside_input.c delete mode 100644 plugins/plugins/vcgn/cnat_log_api.h delete mode 100644 plugins/plugins/vcgn/cnat_log_common.h delete mode 100644 plugins/plugins/vcgn/cnat_logging.c delete mode 100644 plugins/plugins/vcgn/cnat_logging.h delete mode 100644 plugins/plugins/vcgn/cnat_pcp_server.h delete mode 100644 plugins/plugins/vcgn/cnat_ports.c delete mode 100644 plugins/plugins/vcgn/cnat_ports.h delete mode 100644 plugins/plugins/vcgn/cnat_show.c delete mode 100644 plugins/plugins/vcgn/cnat_show_api.h delete mode 100644 plugins/plugins/vcgn/cnat_show_response.h delete mode 100644 plugins/plugins/vcgn/cnat_syslog.c delete mode 100644 plugins/plugins/vcgn/cnat_syslog.h delete mode 100644 plugins/plugins/vcgn/cnat_util.c delete mode 100644 plugins/plugins/vcgn/cnat_v4_ftp_alg.h delete mode 100644 plugins/plugins/vcgn/cnat_v4_functions.c delete mode 100644 plugins/plugins/vcgn/cnat_v4_functions.h delete mode 100644 plugins/plugins/vcgn/cnat_v4_pptp_alg.h delete mode 100644 plugins/plugins/vcgn/cnat_v4_tcp_in2out_stages.c delete mode 100644 plugins/plugins/vcgn/cnat_va_db.c delete mode 100644 plugins/plugins/vcgn/cnat_va_db.h delete mode 100644 plugins/plugins/vcgn/dslite_db.h delete mode 100644 plugins/plugins/vcgn/dslite_defs.h delete mode 100644 plugins/plugins/vcgn/index_list.c delete mode 100644 plugins/plugins/vcgn/index_list.h delete mode 100644 plugins/plugins/vcgn/nat64_db.h delete mode 100644 plugins/plugins/vcgn/nat64_defs.h delete mode 100644 plugins/plugins/vcgn/nat64_tcp_sm.h delete mode 100644 plugins/plugins/vcgn/platform_common.h delete mode 100644 plugins/plugins/vcgn/platform_common_override.h delete mode 100644 plugins/plugins/vcgn/spp_ctx.h delete mode 100644 plugins/plugins/vcgn/spp_platform_trace_log.c delete mode 100644 plugins/plugins/vcgn/spp_platform_trace_log.h delete mode 100644 plugins/plugins/vcgn/spp_timers.h delete mode 100644 plugins/plugins/vcgn/tcp_header_definitions.h delete mode 100644 plugins/plugins/vcgn/vcgn_classify.c delete mode 100644 plugins/plugins/vcgn/vcgn_db.h create mode 100644 plugins/sixrd-plugin/Makefile.am create mode 100644 plugins/sixrd-plugin/configure.ac create mode 100644 plugins/sixrd-plugin/sixrd/ip4_sixrd.c create mode 100644 plugins/sixrd-plugin/sixrd/ip6_sixrd.c create mode 100644 plugins/sixrd-plugin/sixrd/sixrd.c create mode 100644 plugins/sixrd-plugin/sixrd/sixrd.h create mode 100644 plugins/vcgn-plugin/Makefile.am create mode 100644 plugins/vcgn-plugin/configure.ac create mode 100644 plugins/vcgn-plugin/vcgn/README create mode 100644 plugins/vcgn-plugin/vcgn/cgn_bitmap.h create mode 100644 plugins/vcgn-plugin/vcgn/cgse_defs.h create mode 100644 plugins/vcgn-plugin/vcgn/cnat_bulk_port.c create mode 100644 plugins/vcgn-plugin/vcgn/cnat_bulk_port.h create mode 100644 plugins/vcgn-plugin/vcgn/cnat_bulk_port_defs.h create mode 100644 plugins/vcgn-plugin/vcgn/cnat_cli.h create mode 100644 plugins/vcgn-plugin/vcgn/cnat_cli_handler.c create mode 100644 plugins/vcgn-plugin/vcgn/cnat_common_api.h create mode 100644 plugins/vcgn-plugin/vcgn/cnat_config.c create mode 100644 plugins/vcgn-plugin/vcgn/cnat_config.h create mode 100644 plugins/vcgn-plugin/vcgn/cnat_config_api.h create mode 100644 plugins/vcgn-plugin/vcgn/cnat_db.h create mode 100644 plugins/vcgn-plugin/vcgn/cnat_db_scanner.c create mode 100644 plugins/vcgn-plugin/vcgn/cnat_db_v2.c create mode 100644 plugins/vcgn-plugin/vcgn/cnat_debug_msg_handler.c create mode 100644 plugins/vcgn-plugin/vcgn/cnat_global.c create mode 100644 plugins/vcgn-plugin/vcgn/cnat_global.h create mode 100644 plugins/vcgn-plugin/vcgn/cnat_ipv4_icmp.h create mode 100644 plugins/vcgn-plugin/vcgn/cnat_ipv4_icmp_error_inside_input.c create mode 100644 plugins/vcgn-plugin/vcgn/cnat_ipv4_icmp_error_outside_input.c create mode 100644 plugins/vcgn-plugin/vcgn/cnat_ipv4_icmp_query_inside_input.c create mode 100644 plugins/vcgn-plugin/vcgn/cnat_ipv4_icmp_query_inside_input_exception.c create mode 100644 plugins/vcgn-plugin/vcgn/cnat_ipv4_icmp_query_outside_input.c create mode 100644 plugins/vcgn-plugin/vcgn/cnat_ipv4_tcp_inside_input.c create mode 100644 plugins/vcgn-plugin/vcgn/cnat_ipv4_tcp_inside_input_exceptions.c create mode 100644 plugins/vcgn-plugin/vcgn/cnat_ipv4_tcp_outside_input.c create mode 100644 plugins/vcgn-plugin/vcgn/cnat_ipv4_udp.h create mode 100644 plugins/vcgn-plugin/vcgn/cnat_ipv4_udp_inside_input.c create mode 100644 plugins/vcgn-plugin/vcgn/cnat_ipv4_udp_inside_input_exceptions.c create mode 100644 plugins/vcgn-plugin/vcgn/cnat_ipv4_udp_outside_input.c create mode 100644 plugins/vcgn-plugin/vcgn/cnat_log_api.h create mode 100644 plugins/vcgn-plugin/vcgn/cnat_log_common.h create mode 100644 plugins/vcgn-plugin/vcgn/cnat_logging.c create mode 100644 plugins/vcgn-plugin/vcgn/cnat_logging.h create mode 100644 plugins/vcgn-plugin/vcgn/cnat_pcp_server.h create mode 100644 plugins/vcgn-plugin/vcgn/cnat_ports.c create mode 100644 plugins/vcgn-plugin/vcgn/cnat_ports.h create mode 100644 plugins/vcgn-plugin/vcgn/cnat_show.c create mode 100644 plugins/vcgn-plugin/vcgn/cnat_show_api.h create mode 100644 plugins/vcgn-plugin/vcgn/cnat_show_response.h create mode 100644 plugins/vcgn-plugin/vcgn/cnat_syslog.c create mode 100644 plugins/vcgn-plugin/vcgn/cnat_syslog.h create mode 100644 plugins/vcgn-plugin/vcgn/cnat_util.c create mode 100644 plugins/vcgn-plugin/vcgn/cnat_v4_ftp_alg.h create mode 100644 plugins/vcgn-plugin/vcgn/cnat_v4_functions.c create mode 100644 plugins/vcgn-plugin/vcgn/cnat_v4_functions.h create mode 100644 plugins/vcgn-plugin/vcgn/cnat_v4_pptp_alg.h create mode 100644 plugins/vcgn-plugin/vcgn/cnat_v4_tcp_in2out_stages.c create mode 100644 plugins/vcgn-plugin/vcgn/cnat_va_db.c create mode 100644 plugins/vcgn-plugin/vcgn/cnat_va_db.h create mode 100644 plugins/vcgn-plugin/vcgn/dslite_db.h create mode 100644 plugins/vcgn-plugin/vcgn/dslite_defs.h create mode 100644 plugins/vcgn-plugin/vcgn/index_list.c create mode 100644 plugins/vcgn-plugin/vcgn/index_list.h create mode 100644 plugins/vcgn-plugin/vcgn/nat64_db.h create mode 100644 plugins/vcgn-plugin/vcgn/nat64_defs.h create mode 100644 plugins/vcgn-plugin/vcgn/nat64_tcp_sm.h create mode 100644 plugins/vcgn-plugin/vcgn/platform_common.h create mode 100644 plugins/vcgn-plugin/vcgn/platform_common_override.h create mode 100644 plugins/vcgn-plugin/vcgn/spp_ctx.h create mode 100644 plugins/vcgn-plugin/vcgn/spp_platform_trace_log.c create mode 100644 plugins/vcgn-plugin/vcgn/spp_platform_trace_log.h create mode 100644 plugins/vcgn-plugin/vcgn/spp_timers.h create mode 100644 plugins/vcgn-plugin/vcgn/tcp_header_definitions.h create mode 100644 plugins/vcgn-plugin/vcgn/vcgn_classify.c create mode 100644 plugins/vcgn-plugin/vcgn/vcgn_db.h (limited to 'build-data/platforms/dpaa2.mk') diff --git a/build-data/platforms/arm32.mk b/build-data/platforms/arm32.mk index 5e1adabf..ab8d5864 100644 --- a/build-data/platforms/arm32.mk +++ b/build-data/platforms/arm32.mk @@ -22,8 +22,8 @@ arm32_root_packages = vpp vlib vlib-api vnet svm vpp-api-test \ vpp-japi gmod vlib_configure_args_arm32 = --with-pre-data=128 -vnet_configure_args_arm32 = --with-dpdk --without-vcgn --without-ipsec --without-ipv6sr -vpp_configure_args_arm32 = --with-dpdk --without-vcgn --without-ipsec --without-ipv6sr +vnet_configure_args_arm32 = --with-dpdk --without-ipsec --without-ipv6sr +vpp_configure_args_arm32 = --with-dpdk --without-ipsec --without-ipv6sr arm32_dpdk_arch = "armv7a" arm32_dpdk_target = "arm-armv7a-linuxapp-gcc" diff --git a/build-data/platforms/dpaa2.mk b/build-data/platforms/dpaa2.mk index fd33d22d..7f25d212 100644 --- a/build-data/platforms/dpaa2.mk +++ b/build-data/platforms/dpaa2.mk @@ -42,9 +42,9 @@ dpaa2_dpdk_make_extra_args = "CROSS=$(dpaa2_target)-" endif endif -vpp_configure_args_dpaa2 = --with-dpdk --without-ipsec --without-vcgn \ +vpp_configure_args_dpaa2 = --with-dpdk --without-ipsec \ --without-ipv6sr --with-sysroot=$(SYSROOT) -vnet_configure_args_dpaa2 = --with-dpdk --without-ipsec --without-vcgn \ +vnet_configure_args_dpaa2 = --with-dpdk --without-ipsec \ --without-ipv6sr --with-sysroot=$(SYSROOT) # Set these parameters carefully. The vlib_buffer_t is 128 bytes, i.e. diff --git a/build-data/platforms/qppc.mk b/build-data/platforms/qppc.mk index 3206928b..244747e7 100644 --- a/build-data/platforms/qppc.mk +++ b/build-data/platforms/qppc.mk @@ -11,10 +11,10 @@ qppc_root_packages = vppinfra vlib vlib-api vnet svm \ vpp vpp-api-test vnet_configure_args_qppc = \ - --without-ipsec --without-vcgn --without-ipv6sr + --without-ipsec --without-ipv6sr vpp_configure_args_qppc = \ - --without-ipsec --without-vcgn --without-ipv6sr + --without-ipsec --without-ipv6sr vlib_configure_args_qppc = --with-pre-data=128 diff --git a/build-data/platforms/thunder.mk b/build-data/platforms/thunder.mk index 8fb00456..f891f4a1 100644 --- a/build-data/platforms/thunder.mk +++ b/build-data/platforms/thunder.mk @@ -15,10 +15,10 @@ thunder_root_packages = vppinfra vlib-cavium-dpdk vnet-cavium-dpdk cavium-dpdk \ vpp-cavium-dpdk vpp-api-test-cavium-dpdk vnet-cavium-dpdk_configure_args_thunder = \ - --with-dpdk --without-ipsec --without-vcgn --without-ipv6sr + --with-dpdk --without-ipsec --without-ipv6sr vpp-cavium-dpdk_configure_args_thunder = \ - --with-dpdk --without-ipsec --without-vcgn --without-ipv6sr + --with-dpdk --without-ipsec --without-ipv6sr cavium-dpdk_configure_args_thunder = --with-headroom=256 diff --git a/build-data/platforms/vpp_lite.mk b/build-data/platforms/vpp_lite.mk index d35d2347..a28fec2f 100644 --- a/build-data/platforms/vpp_lite.mk +++ b/build-data/platforms/vpp_lite.mk @@ -24,8 +24,8 @@ vpp_lite_root_packages = vpp vlib vlib-api vnet svm vpp-api-test \ vlib_configure_args_vpp_lite = --with-pre-data=128 -vnet_configure_args_vpp_lite = --without-vcgn -vpp_configure_args_vpp_lite = --without-vcgn +vnet_configure_args_vpp_lite = +vpp_configure_args_vpp_lite = vpp_lite_debug_TAG_CFLAGS = -g -O0 -DCLIB_DEBUG -DFORTIFY_SOURCE=2 -march=$(MARCH) \ -fstack-protector-all -fPIC -Werror diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 2087c4e8..1fcc18ec 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -13,131 +13,19 @@ AUTOMAKE_OPTIONS = foreign subdir-objects -AM_CFLAGS = -Wall -I@TOOLKIT_INCLUDE@ - - -######################################## -# SIXRD (RFC5969) -######################################## -libsixrd_plugin_la_SOURCES = plugins/sixrd/sixrd.c plugins/sixrd/ip4_sixrd.c plugins/sixrd/ip6_sixrd.c -nobase_include_HEADERS = plugins/sixrd/sixrd.h - -libsixrd_plugin_la_LDFLAGS = -module -#BUILT_SOURCES = - -lib_LTLIBRARIES = libsixrd_plugin.la - -######################################## -# iOAM Proof of Transit -######################################## - -ioam_pot_plugin_la_SOURCES = plugins/ioam/lib-pot/pot_util.c plugins/ioam/encap/ip6_ioam_pot.c \ - plugins/ioam/lib-pot/pot_util.h plugins/ioam/lib-pot/math64.h plugins/ioam/lib-pot/pot_api.c -ioam_pot_plugin_la_LDFLAGS = -module - -BUILT_SOURCES = plugins/ioam/lib-pot/pot.api.h -SUFFIXES = .api.h .api - -%.api.h: %.api - mkdir -p `dirname $@` ; \ - $(CC) $(CPPFLAGS) -E -P -C -x c $^ \ - | vppapigen --input - --output $@ --show-name $@ - -nobase_include_HEADERS += \ - plugins/ioam/lib-pot/pot_all_api_h.h \ - plugins/ioam/lib-pot/pot_msg_enum.h \ - plugins/ioam/lib-pot/pot.api.h \ - plugins/ioam/lib-pot/pot_util.h \ - plugins/ioam/lib-pot/math64.h - -ioam_pot_test_plugin_la_SOURCES = plugins/ioam/lib-pot/pot_test.c plugins/ioam/lib-pot/pot_plugin.api.h -ioam_pot_test_plugin_la_LDFLAGS = -module - -lib_LTLIBRARIES += ioam_pot_plugin.la ioam_pot_test_plugin.la - -######################################## -# Virtual Carrier Grade NAT -######################################## - -libvcgn_plugin_la_SOURCES = \ - plugins/vcgn/cnat_bulk_port.c \ - plugins/vcgn/cnat_config.c \ - plugins/vcgn/cnat_db_scanner.c \ - plugins/vcgn/cnat_db_v2.c \ - plugins/vcgn/cnat_debug_msg_handler.c \ - plugins/vcgn/cnat_cli_handler.c \ - plugins/vcgn/cnat_global.c \ - plugins/vcgn/cnat_ipv4_udp_inside_input.c \ - plugins/vcgn/cnat_ipv4_udp_inside_input_exceptions.c \ - plugins/vcgn/cnat_ipv4_udp_outside_input.c \ - plugins/vcgn/cnat_ipv4_tcp_inside_input.c \ - plugins/vcgn/cnat_ipv4_tcp_inside_input_exceptions.c \ - plugins/vcgn/cnat_ipv4_tcp_outside_input.c \ - plugins/vcgn/cnat_ipv4_icmp_query_inside_input.c \ - plugins/vcgn/cnat_ipv4_icmp_query_inside_input_exception.c \ - plugins/vcgn/cnat_ipv4_icmp_query_outside_input.c \ - plugins/vcgn/cnat_ipv4_icmp_error_inside_input.c \ - plugins/vcgn/cnat_ipv4_icmp_error_outside_input.c \ - plugins/vcgn/cnat_logging.c \ - plugins/vcgn/cnat_ports.c \ - plugins/vcgn/cnat_util.c \ - plugins/vcgn/cnat_show.c \ - plugins/vcgn/cnat_syslog.c \ - plugins/vcgn/cnat_v4_functions.c \ - plugins/vcgn/index_list.c \ - plugins/vcgn/spp_platform_trace_log.c \ - plugins/vcgn/vcgn_classify.c - -nobase_include_HEADERS += plugins/vcgn/cgn_bitmap.h \ - plugins/vcgn/cgse_defs.h \ - plugins/vcgn/cnat_bulk_port_defs.h \ - plugins/vcgn/cnat_bulk_port.h \ - plugins/vcgn/cnat_cli.h \ - plugins/vcgn/cnat_common_api.h \ - plugins/vcgn/cnat_config_api.h \ - plugins/vcgn/cnat_config.h \ - plugins/vcgn/cnat_db.h \ - plugins/vcgn/cnat_global.h \ - plugins/vcgn/cnat_ipv4_icmp.h \ - plugins/vcgn/cnat_ipv4_udp.h \ - plugins/vcgn/cnat_log_api.h \ - plugins/vcgn/cnat_log_common.h \ - plugins/vcgn/cnat_logging.h \ - plugins/vcgn/cnat_pcp_server.h \ - plugins/vcgn/cnat_ports.h \ - plugins/vcgn/cnat_show_api.h \ - plugins/vcgn/cnat_show_response.h \ - plugins/vcgn/cnat_syslog.h \ - plugins/vcgn/cnat_v4_ftp_alg.h \ - plugins/vcgn/cnat_v4_functions.h \ - plugins/vcgn/cnat_v4_pptp_alg.h \ - plugins/vcgn/cnat_va_db.h \ - plugins/vcgn/dslite_db.h \ - plugins/vcgn/dslite_defs.h \ - plugins/vcgn/index_list.h \ - plugins/vcgn/nat64_db.h \ - plugins/vcgn/nat64_defs.h \ - plugins/vcgn/nat64_tcp_sm.h \ - plugins/vcgn/platform_common.h \ - plugins/vcgn/platform_common_override.h \ - plugins/vcgn/spp_ctx.h \ - plugins/vcgn/spp_platform_trace_log.h \ - plugins/vcgn/spp_timers.h \ - plugins/vcgn/tcp_header_definitions.h \ - plugins/vcgn/vcgn_db.h - -libvcgn_plugin_la_LDFLAGS = -module +SUBDIRS = +if ENABLE_SAMPLE_PLUGIN +SUBDIRS += sample-plugin +endif -lib_LTLIBRARIES += libvcgn_plugin.la +if ENABLE_SIXRD_PLUGIN +SUBDIRS += sixrd-plugin +endif -if WITH_PLUGIN_TOOLKIT -install-data-hook: - mkdir /usr/lib/vpp_plugins || true - mkdir /usr/lib/vpp_api_test_plugins || true - cp $(prefix)/lib/libsixrd_plugin.so.*.*.* /usr/lib/vpp_plugins - cp $(prefix)/lib/libvcgn_plugin.so.*.*.* /usr/lib/vpp_plugins - cp $(prefix)/lib/ioam_pot_plugin.so.*.*.* /usr/lib/vpp_plugins - cp $(prefix)/lib/ioam_pot_test_plugin.so.*.*.* \ - /usr/lib/vpp_api_test_plugins +if ENABLE_IOAM_PLUGIN +SUBDIRS += ioam-plugin endif +if ENABLE_VCGN_PLUGIN +SUBDIRS += vcgn-plugin +endif diff --git a/plugins/build-data/packages/ioam-plugin.mk b/plugins/build-data/packages/ioam-plugin.mk new file mode 100644 index 00000000..1ebe8184 --- /dev/null +++ b/plugins/build-data/packages/ioam-plugin.mk @@ -0,0 +1,47 @@ +ioam-plugin_configure_depend = \ + vppinfra-install \ + svm-install \ + vlib-api-install \ + vlib-install \ + vnet-install \ + vpp-install \ + vpp-api-test-install + +ioam-plugin_CPPFLAGS = $(call installed_includes_fn, \ + vppinfra \ + openssl \ + svm \ + vlib \ + vlib-api \ + vnet \ + vpp \ + vpp-api-test) + +ioam-plugin_LDFLAGS = $(call installed_libs_fn, \ + vppinfra \ + openssl \ + svm \ + vlib \ + vlib-api \ + vnet \ + vpp \ + vpp-api-test) + +ioam-plugin_post_install = \ + mkdir -p $(PACKAGE_INSTALL_DIR)/$(arch_lib_dir)/vlib_plugins ; \ + cp $(PACKAGE_INSTALL_DIR)/$(arch_lib_dir)/*.so \ + $(PACKAGE_INSTALL_DIR)/$(arch_lib_dir)/vlib_plugins + +ioam-plugin_image_include = echo $(arch_lib_dir)/vlib_plugins + +ifneq ($($(PLATFORM)_uses_dpdk),no) +ioam-plugin_configure_args = --with-dpdk +ifeq ($($(PLATFORM)_uses_external_dpdk),yes) +ioam-plugin_CPPFLAGS += -I$($(PLATFORM)_dpdk_inc_dir) +ioam-plugin_LDFLAGS += -L$($(PLATFORM)_dpdk_lib_dir) +else +ioam-plugin_configure_depend += dpdk-install +ioam-plugin_CPPFLAGS += $(call installed_includes_fn, dpdk) +ioam-plugin_LDFLAGS += $(call installed_libs_fn, dpdk) +endif +endif diff --git a/plugins/build-data/packages/sixrd-plugin.mk b/plugins/build-data/packages/sixrd-plugin.mk new file mode 100644 index 00000000..186d9b8f --- /dev/null +++ b/plugins/build-data/packages/sixrd-plugin.mk @@ -0,0 +1,47 @@ +sixrd-plugin_configure_depend = \ + vppinfra-install \ + svm-install \ + vlib-api-install \ + vlib-install \ + vnet-install \ + vpp-install \ + vpp-api-test-install + +sixrd-plugin_CPPFLAGS = $(call installed_includes_fn, \ + vppinfra \ + openssl \ + svm \ + vlib \ + vlib-api \ + vnet \ + vpp \ + vpp-api-test) + +sixrd-plugin_LDFLAGS = $(call installed_libs_fn, \ + vppinfra \ + openssl \ + svm \ + vlib \ + vlib-api \ + vnet \ + vpp \ + vpp-api-test) + +sixrd-plugin_post_install = \ + mkdir -p $(PACKAGE_INSTALL_DIR)/$(arch_lib_dir)/vlib_plugins ; \ + cp $(PACKAGE_INSTALL_DIR)/$(arch_lib_dir)/*.so \ + $(PACKAGE_INSTALL_DIR)/$(arch_lib_dir)/vlib_plugins + +sixrd-plugin_image_include = echo $(arch_lib_dir)/vlib_plugins + +ifneq ($($(PLATFORM)_uses_dpdk),no) +sixrd-plugin_configure_args = --with-dpdk +ifeq ($($(PLATFORM)_uses_external_dpdk),yes) +sixrd-plugin_CPPFLAGS += -I$($(PLATFORM)_dpdk_inc_dir) +sixrd-plugin_LDFLAGS += -L$($(PLATFORM)_dpdk_lib_dir) +else +sixrd-plugin_configure_depend += dpdk-install +sixrd-plugin_CPPFLAGS += $(call installed_includes_fn, dpdk) +sixrd-plugin_LDFLAGS += $(call installed_libs_fn, dpdk) +endif +endif diff --git a/plugins/build-data/packages/vcgn-plugin.mk b/plugins/build-data/packages/vcgn-plugin.mk new file mode 100644 index 00000000..cd865c15 --- /dev/null +++ b/plugins/build-data/packages/vcgn-plugin.mk @@ -0,0 +1,47 @@ +vcgn-plugin_configure_depend = \ + vppinfra-install \ + svm-install \ + vlib-api-install \ + vlib-install \ + vnet-install \ + vpp-install \ + vpp-api-test-install + +vcgn-plugin_CPPFLAGS = $(call installed_includes_fn, \ + vppinfra \ + openssl \ + svm \ + vlib \ + vlib-api \ + vnet \ + vpp \ + vpp-api-test) + +vcgn-plugin_LDFLAGS = $(call installed_libs_fn, \ + vppinfra \ + openssl \ + svm \ + vlib \ + vlib-api \ + vnet \ + vpp \ + vpp-api-test) + +vcgn-plugin_post_install = \ + mkdir -p $(PACKAGE_INSTALL_DIR)/$(arch_lib_dir)/vlib_plugins ; \ + cp $(PACKAGE_INSTALL_DIR)/$(arch_lib_dir)/*.so \ + $(PACKAGE_INSTALL_DIR)/$(arch_lib_dir)/vlib_plugins + +vcgn-plugin_image_include = echo $(arch_lib_dir)/vlib_plugins + +ifneq ($($(PLATFORM)_uses_dpdk),no) +vcgn-plugin_configure_args = --with-dpdk +ifeq ($($(PLATFORM)_uses_external_dpdk),yes) +vcgn-plugin_CPPFLAGS += -I$($(PLATFORM)_dpdk_inc_dir) +vcgn-plugin_LDFLAGS += -L$($(PLATFORM)_dpdk_lib_dir) +else +vcgn-plugin_configure_depend += dpdk-install +vcgn-plugin_CPPFLAGS += $(call installed_includes_fn, dpdk) +vcgn-plugin_LDFLAGS += $(call installed_libs_fn, dpdk) +endif +endif diff --git a/plugins/configure.ac b/plugins/configure.ac index bf01aacb..40c0babd 100644 --- a/plugins/configure.ac +++ b/plugins/configure.ac @@ -20,4 +20,61 @@ AC_ARG_WITH(plugin-toolkit, AC_SUBST(TOOLKIT_INCLUDE,[${with_plugin_toolkit}]) AM_CONDITIONAL(WITH_PLUGIN_TOOLKIT, test "$with_plugin_toolkit" != ".") AM_CONDITIONAL(ENABLE_TESTS, test "$enable_tests" = "1") + +# +# Sample plugin +# +AC_ARG_ENABLE(sample_plugin, + AC_HELP_STRING([--enable-sample-plugin], [Build sample plugin]), + [enable_sample_plugin=1], + [enable_sample_plugin=0]) + +if test "x$enable_sample_plugin" = x1; then + AC_CONFIG_SUBDIRS([sample-plugin]) +fi + +AM_CONDITIONAL(ENABLE_SAMPLE_PLUGIN, test "$enable_sample_plugin" = "1") + +# +# SIXRD plugin +# +AC_ARG_ENABLE(sixrd_plugin, + AC_HELP_STRING([--enable-sixrd-plugin], [Build sixrd plugin]), + [], + [enable_sixrd_plugin=1]) + +if test "x$enable_sixrd_plugin" = x1; then + AC_CONFIG_SUBDIRS([sixrd-plugin]) +fi + +AM_CONDITIONAL(ENABLE_SIXRD_PLUGIN, test "$enable_sixrd_plugin" = "1") + +# +# IOAM plugin +# +AC_ARG_ENABLE(ioam_plugin, + AC_HELP_STRING([--enable-ioam-plugin], [Build ioam plugin]), + [], + [enable_ioam_plugin=1]) + +if test "x$enable_ioam_plugin" = x1; then + AC_CONFIG_SUBDIRS([ioam-plugin]) +fi + +AM_CONDITIONAL(ENABLE_IOAM_PLUGIN, test "$enable_ioam_plugin" = "1") + +# +# VCGN plugin +# +AC_ARG_ENABLE(vcgn_plugin, + AC_HELP_STRING([--enable-vcgn-plugin], [Build vcgn plugin]), + [enable_vcgn_plugin=1], + [enable_vcgn_plugin=0]) + +if test "x$enable_vcgn_plugin" = x1; then + AC_CONFIG_SUBDIRS([vcgn-plugin]) +fi + +AM_CONDITIONAL(ENABLE_VCGN_PLUGIN, test "$enable_vcgn_plugin" = "1") + AC_OUTPUT([Makefile]) diff --git a/plugins/ioam-plugin/Makefile.am b/plugins/ioam-plugin/Makefile.am new file mode 100644 index 00000000..e62525f1 --- /dev/null +++ b/plugins/ioam-plugin/Makefile.am @@ -0,0 +1,62 @@ +# Copyright (c) 2015 Cisco and/or its affiliates. +# 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. + +AUTOMAKE_OPTIONS = foreign subdir-objects + +AM_CFLAGS = -Wall -I@TOOLKIT_INCLUDE@ + +######################################## +# iOAM Proof of Transit +######################################## + +ioam_pot_plugin_la_SOURCES = \ + ioam/lib-pot/pot_util.c \ + ioam/encap/ip6_ioam_pot.c \ + ioam/lib-pot/pot_util.h \ + ioam/lib-pot/math64.h \ + ioam/lib-pot/pot_api.c + +ioam_pot_plugin_la_LDFLAGS = -module + +BUILT_SOURCES = \ + ioam/lib-pot/pot.api.h + +SUFFIXES = .api.h .api + +%.api.h: %.api + mkdir -p `dirname $@` ; \ + $(CC) $(CPPFLAGS) -E -P -C -x c $^ \ + | vppapigen --input - --output $@ --show-name $@ + +nobase_include_HEADERS = \ + ioam/lib-pot/pot_all_api_h.h \ + ioam/lib-pot/pot_msg_enum.h \ + ioam/lib-pot/pot.api.h \ + ioam/lib-pot/pot_util.h \ + ioam/lib-pot/math64.h + +ioam_pot_test_plugin_la_SOURCES = \ + ioam/lib-pot/pot_test.c \ + ioam/lib-pot/pot_plugin.api.h + +ioam_pot_test_plugin_la_LDFLAGS = -module + +lib_LTLIBRARIES = ioam_pot_plugin.la ioam_pot_test_plugin.la + +if WITH_PLUGIN_TOOLKIT +install-data-hook: + mkdir /usr/lib/vpp_plugins || true + mkdir /usr/lib/vpp_api_test_plugins || true + cp -L $(prefix)/lib/ioam_pot_plugin.so /usr/lib/vpp_plugins + cp -L $(prefix)/lib/ioam_pot_test_plugin.so /usr/lib/vpp_api_test_plugins +endif diff --git a/plugins/ioam-plugin/configure.ac b/plugins/ioam-plugin/configure.ac new file mode 100644 index 00000000..8c828575 --- /dev/null +++ b/plugins/ioam-plugin/configure.ac @@ -0,0 +1,17 @@ +AC_INIT(ioam_plugin, 1.0) +LT_INIT +AM_INIT_AUTOMAKE + +AM_PROG_AS +AC_PROG_CC +AM_PROG_CC_C_O + +AC_ARG_WITH(plugin-toolkit, + AC_HELP_STRING([--with-plugin-toolkit], + [build using the vpp toolkit]), + [with_plugin_toolkit=${prefix}/include], + [with_plugin_toolkit=.]) + +AC_SUBST(TOOLKIT_INCLUDE,[${with_plugin_toolkit}]) +AM_CONDITIONAL(WITH_PLUGIN_TOOLKIT, test "$with_plugin_toolkit" != ".") +AC_OUTPUT([Makefile]) diff --git a/plugins/ioam-plugin/ioam/encap/ip6_ioam_pot.c b/plugins/ioam-plugin/ioam/encap/ip6_ioam_pot.c new file mode 100644 index 00000000..0a239457 --- /dev/null +++ b/plugins/ioam-plugin/ioam/encap/ip6_ioam_pot.c @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * 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 +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +typedef CLIB_PACKED(struct { + ip6_hop_by_hop_option_t hdr; + u8 pot_type; +#define PROFILE_ID_MASK 0xF + u8 reserved_profile_id; /* 4 bits reserved, 4 bits to carry profile id */ + u64 random; + u64 cumulative; +}) ioam_pot_option_t; + +#define foreach_ip6_hop_by_hop_ioam_pot_stats \ + _(PROCESSED, "Pkts with ip6 hop-by-hop pot options") \ + _(PROFILE_MISS, "Pkts with ip6 hop-by-hop pot options but no profile set") \ + _(PASSED, "Pkts with POT in Policy") \ + _(FAILED, "Pkts with POT out of Policy") + +static char * ip6_hop_by_hop_ioam_pot_stats_strings[] = { +#define _(sym,string) string, + foreach_ip6_hop_by_hop_ioam_pot_stats +#undef _ +}; + +typedef enum { +#define _(sym,str) IP6_IOAM_POT_##sym, + foreach_ip6_hop_by_hop_ioam_pot_stats +#undef _ + IP6_IOAM_POT_N_STATS, +} ip6_ioam_pot_stats_t; + +typedef struct { + /* stats */ + u64 counters[ARRAY_LEN(ip6_hop_by_hop_ioam_pot_stats_strings)]; + + /* convenience */ + vlib_main_t * vlib_main; + vnet_main_t * vnet_main; +} ip6_hop_by_hop_ioam_pot_main_t; + +ip6_hop_by_hop_ioam_pot_main_t ip6_hop_by_hop_ioam_pot_main; + +always_inline void +ip6_ioam_stats_increment_counter (u32 counter_index, u64 increment) +{ + ip6_hop_by_hop_ioam_pot_main_t *hm = &ip6_hop_by_hop_ioam_pot_main; + + hm->counters[counter_index] += increment; +} + + +static u8 * format_ioam_pot (u8 * s, va_list * args) +{ + ioam_pot_option_t * pot0 = va_arg (*args, ioam_pot_option_t *); + u64 random, cumulative; + random = cumulative = 0; + if (pot0) + { + random = clib_net_to_host_u64 (pot0->random); + cumulative = clib_net_to_host_u64 (pot0->cumulative); + } + + s = format (s, "random = 0x%Lx, Cumulative = 0x%Lx, Index = 0x%x", + random, cumulative, pot0->reserved_profile_id); + return s; +} + +u8 * +ip6_hbh_ioam_proof_of_transit_trace_handler (u8 *s, ip6_hop_by_hop_option_t *opt) +{ + ioam_pot_option_t *pot; + + s = format (s, " POT opt present\n"); + pot = (ioam_pot_option_t *) opt; + s = format (s, " %U\n", format_ioam_pot, pot); + return (s); +} + +int +ip6_hbh_ioam_proof_of_transit_handler (vlib_buffer_t *b, + ip6_header_t *ip, + ip6_hop_by_hop_option_t *opt0) +{ + ioam_pot_option_t * pot0; + u64 random = 0, cumulative = 0; + int rv = 0; + u8 pot_profile_index; + pot_profile *pot_profile = 0, *new_profile = 0; + u8 pot_encap = 0; + + pot0 = (ioam_pot_option_t *) opt0; + pot_encap = (pot0->random == 0); + pot_profile_index = pot_profile_get_active_id(); + pot_profile = pot_profile_get_active(); + if (pot_encap && PREDICT_FALSE(!pot_profile)) + { + ip6_ioam_stats_increment_counter (IP6_IOAM_POT_PROFILE_MISS, 1); + return(-1); + } + if (pot_encap) + { + pot0->reserved_profile_id = + pot_profile_index & PROFILE_ID_MASK; + pot_profile_incr_usage_stats(pot_profile); + } + else + { /* Non encap node */ + if (PREDICT_FALSE(pot0->reserved_profile_id != + pot_profile_index || pot_profile == 0)) + { + /* New profile announced by encap node. */ + new_profile = + pot_profile_find(pot0->reserved_profile_id); + if (PREDICT_FALSE(new_profile == 0 || + new_profile->valid == 0)) + { + ip6_ioam_stats_increment_counter (IP6_IOAM_POT_PROFILE_MISS, 1); + return(-1); + } + else + { + pot_profile_index = pot0->reserved_profile_id; + pot_profile = new_profile; + pot_profile_set_active(pot_profile_index); + pot_profile_reset_usage_stats(pot_profile); + } + } + pot_profile_incr_usage_stats(pot_profile); + } + + if (pot0->random == 0) + { + pot0->random = clib_host_to_net_u64(pot_generate_random(pot_profile)); + pot0->cumulative = 0; + } + random = clib_net_to_host_u64(pot0->random); + cumulative = clib_net_to_host_u64(pot0->cumulative); + pot0->cumulative = clib_host_to_net_u64( + pot_update_cumulative(pot_profile, + cumulative, + random)); + ip6_ioam_stats_increment_counter (IP6_IOAM_POT_PROCESSED, 1); + + return (rv); +} + +int +ip6_hbh_ioam_proof_of_transit_pop_handler (ip6_header_t *ip, + ip6_hop_by_hop_option_t *opt0) +{ + ioam_pot_option_t * pot0; + u64 random = 0; + u64 cumulative = 0; + int rv = 0; + pot_profile *pot_profile = 0; + u8 result = 0; + + pot0 = (ioam_pot_option_t *) opt0; + random = clib_net_to_host_u64(pot0->random); + cumulative = clib_net_to_host_u64(pot0->cumulative); + pot_profile = pot_profile_get_active(); + result = pot_validate (pot_profile, + cumulative, random); + + if (result == 1) + { + ip6_ioam_stats_increment_counter (IP6_IOAM_POT_PASSED, 1); + } + else + { + ip6_ioam_stats_increment_counter (IP6_IOAM_POT_FAILED, 1); + } + return (rv); +} + +int ip6_hop_by_hop_ioam_pot_rewrite_handler (u8 *rewrite_string, u8 rewrite_size) +{ + ioam_pot_option_t * pot_option; + if (rewrite_string && rewrite_size == sizeof(ioam_pot_option_t)) + { + pot_option = (ioam_pot_option_t *)rewrite_string; + pot_option->hdr.type = HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT + | HBH_OPTION_TYPE_DATA_CHANGE_ENROUTE; + pot_option->hdr.length = sizeof (ioam_pot_option_t) - + sizeof (ip6_hop_by_hop_option_t); + return(0); + } + return(-1); +} + +static clib_error_t * +ip6_show_ioam_pot_cmd_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + ip6_hop_by_hop_ioam_pot_main_t *hm = &ip6_hop_by_hop_ioam_pot_main; + u8 *s = 0; + int i = 0; + + for ( i = 0; i < IP6_IOAM_POT_N_STATS; i++) + { + s = format(s, " %s - %lu\n", ip6_hop_by_hop_ioam_pot_stats_strings[i], + hm->counters[i]); + } + + vlib_cli_output(vm, "%v", s); + vec_free(s); + return 0; +} + + +VLIB_CLI_COMMAND (ip6_show_ioam_pot_cmd, static) = { + .path = "show ioam pot", + .short_help = "iOAM pot statistics", + .function = ip6_show_ioam_pot_cmd_fn, +}; + + +static clib_error_t * +ip6_hop_by_hop_ioam_pot_init (vlib_main_t * vm) +{ + ip6_hop_by_hop_ioam_pot_main_t * hm = &ip6_hop_by_hop_ioam_pot_main; + clib_error_t * error; + + if ((error = vlib_call_init_function (vm, ip_main_init))) + return(error); + + if ((error = vlib_call_init_function (vm, ip6_lookup_init))) + return error; + + if ((error = vlib_call_init_function (vm, ip6_hop_by_hop_ioam_init))) + return(error); + + hm->vlib_main = vm; + hm->vnet_main = vnet_get_main(); + memset(hm->counters, 0, sizeof(hm->counters)); + + if (ip6_hbh_register_option(HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT, ip6_hbh_ioam_proof_of_transit_handler, + ip6_hbh_ioam_proof_of_transit_trace_handler) < 0) + return (clib_error_create("registration of HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT failed")); + + if (ip6_hbh_add_register_option(HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT, + sizeof(ioam_pot_option_t), + ip6_hop_by_hop_ioam_pot_rewrite_handler) < 0) + return (clib_error_create("registration of HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT for rewrite failed")); + + if (ip6_hbh_pop_register_option(HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT, + ip6_hbh_ioam_proof_of_transit_pop_handler) < 0) + return (clib_error_create("registration of HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT POP failed")); + + return (0); +} + +VLIB_INIT_FUNCTION (ip6_hop_by_hop_ioam_pot_init); + + diff --git a/plugins/ioam-plugin/ioam/lib-pot/math64.h b/plugins/ioam-plugin/ioam/lib-pot/math64.h new file mode 100644 index 00000000..4c608a37 --- /dev/null +++ b/plugins/ioam-plugin/ioam/lib-pot/math64.h @@ -0,0 +1,159 @@ +/* + * math64.h provides the 64 bit unsigned integer add, multiply followed by modulo operation + * The linux/math64.h provides divide and multiply 64 bit integers but: + * 1. multiply: mul_u64_u64_shr - only returns 64 bits of the result and has to be called + * twice to get the complete 128 bits of the result. + * 2. Modulo operation of the result of addition and multiplication of u64 that may result + * in integers > 64 bits is not supported + * Hence this header to combine add/multiply followed by modulo of u64 integrers + * always resulting in u64. + * + * Copyright (c) 2016 Cisco and/or its affiliates. + * 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_vnet_math64_h +#define include_vnet_math64_h +#include + +/* + * multiplies and returns result in hi and lo + */ +static inline void mul64by64(u64 a, u64 b, u64 * hi, u64 * lo) +{ + u64 a_lo = (u64) (uint32_t) a; + u64 a_hi = a >> 32; + u64 b_lo = (u64) (u32) b; + u64 b_hi = b >> 32; + + u64 p0 = a_lo * b_lo; + u64 p1 = a_lo * b_hi; + u64 p2 = a_hi * b_lo; + u64 p3 = a_hi * b_hi; + + u32 cy = (u32) (((p0 >> 32) + (u32) p1 + (u32) p2) >> 32); + + *lo = p0 + (p1 << 32) + (p2 << 32); + *hi = p3 + (p1 >> 32) + (p2 >> 32) + cy; + return; +} + +#define TWO64 18446744073709551616.0 + +static inline u64 mod128by64(u64 x, u64 y, u64 m, double di) +{ + u64 q1, q2, q; + u64 p1, p0; + double dq; + + /* calculate quotient first pass 53 bits */ + dq = (TWO64 * (double)x + (double)y) * di; + + if (dq >= TWO64) + q1 = 0xfffffffffffff800L; + else + q1 = dq; + + /* q1 * m to compare the product to the dividend. */ + mul64by64(q1, m, &p1, &p0); + + /* Adjust quotient. is it > actual result: */ + if (x < p1 || (x == p1 && y < p0)) + { + /* q1 > quotient. calculate abs remainder */ + x = p1 - (x + (p0 < y)); + y = p0 - y; + + /* use the remainder as new dividend to adjust quotient */ + q2 = (u64) ((TWO64 * (double)x + (double)y) * di); + mul64by64(q2, m, &p1, &p0); + + q = q1 - q2; + if (x < p1 || (x == p1 && y <= p0)) + { + y = p0 - y; + } + else + { + y = p0 - y; + y += m; + q--; + } + } + else + { + x = x - (p1 + (y < p0)); + y = y - p0; + + q2 = (u64) ((TWO64 * (double)x + (double)y) * di); + mul64by64(q2, m, &p1, &p0); + + q = q1 + q2; + if (x < p1 || (x == p1 && y < p0)) + { + y = y - p0; + y += m; + q--; + } + else + { + y = y - p0; + if (y >= m) + { + y -= m; + q++; + } + } + } + + return y; +} + +/* + * returns a % p + */ +static inline u64 mod64by64(u64 a, u64 p, u64 primeinv) +{ + return (mod128by64(0, a, p, primeinv)); +} + +static inline void add64(u64 a, u64 b, u64 * whi, u64 * wlo) +{ + *wlo = a + b; + if (*wlo < a) + *whi = 1; + +} + +/* + * returns (a + b)%p + */ +static inline u64 add64_mod(u64 a, u64 b, u64 p, double pi) +{ + u64 shi = 0, slo = 0; + + add64(a, b, &shi, &slo); + return (mod128by64(shi, slo, p, pi)); +} + +/* + * returns (ab) % p + */ +static inline u64 mul64_mod(u64 a, u64 b, u64 p, double pi) +{ + u64 phi = 0, plo = 0; + + mul64by64(a, b, &phi, &plo); + return (mod128by64(phi, plo, p, pi)); +} + +#endif diff --git a/plugins/ioam-plugin/ioam/lib-pot/pot.api b/plugins/ioam-plugin/ioam/lib-pot/pot.api new file mode 100644 index 00000000..7fd06b51 --- /dev/null +++ b/plugins/ioam-plugin/ioam/lib-pot/pot.api @@ -0,0 +1,97 @@ +/* Hey Emacs use -*- mode: C -*- */ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * 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. + */ + + +/** \brief Proof of Transit(POT): Set POT profile + @param id - id of the profile + @param validator - True/False to indicate if this is verifier + @param secret_key - Verification key + @param secret_share - Share of the 1st polynomial + @param prime - Prime number used for modulo operation + @param max_bits - Max bits to be used for Random number generation + @param lpc - Lagrange basis polynomial + @param polynomial_public - pre-evaluated public polynomial + @param list_name_len - length of the name of this profile list + @param list_name - name of this profile list +*/ +define pot_profile_add { + u32 client_index; + u32 context; + u8 id; + u8 validator; + u64 secret_key; + u64 secret_share; + u64 prime; + u8 max_bits; + u64 lpc; + u64 polynomial_public; + u8 list_name_len; + u8 list_name[0]; +}; + +/** \brief Proof of Transit profile add / del response + @param context - sender context, to match reply w/ request + @param retval - return value for request +*/ +define pot_profile_add_reply { + u32 context; + i32 retval; +}; + + +/** \brief Proof of Transit(POT): Activate POT profile in the list + @param id - id of the profile + @param list_name_len - length of the name of this profile list + @param list_name - name of this profile list +*/ +define pot_profile_activate { + u32 client_index; + u32 context; + u8 id; + u8 list_name_len; + u8 list_name[0]; +}; + +/** \brief Proof of Transit profile activate response + @param context - sender context, to match reply w/ request + @param retval - return value for request +*/ +define pot_profile_activate_reply { + u32 context; + i32 retval; +}; + +/** \brief Delete POT Profile + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param list_name_len - length of the name of the profile list + @param list_name - name of profile list to delete +*/ +define pot_profile_del { + u32 client_index; + u32 context; + u8 list_name_len; + u8 list_name[0]; +}; + +/** \brief Proof of Transit profile add / del response + @param context - sender context, to match reply w/ request + @param retval - return value for request +*/ +define pot_profile_del_reply { + u32 context; + i32 retval; +}; diff --git a/plugins/ioam-plugin/ioam/lib-pot/pot_all_api_h.h b/plugins/ioam-plugin/ioam/lib-pot/pot_all_api_h.h new file mode 100644 index 00000000..63967c45 --- /dev/null +++ b/plugins/ioam-plugin/ioam/lib-pot/pot_all_api_h.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * 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 the generated file, see BUILT_SOURCES in Makefile.am */ +#include diff --git a/plugins/ioam-plugin/ioam/lib-pot/pot_api.c b/plugins/ioam-plugin/ioam/lib-pot/pot_api.c new file mode 100644 index 00000000..95be9e02 --- /dev/null +++ b/plugins/ioam-plugin/ioam/lib-pot/pot_api.c @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * 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. + */ +/* + *------------------------------------------------------------------ + * pot_api.c - Proof of Transit related APIs to create + * and maintain profiles + *------------------------------------------------------------------ + */ + +#include +#include +#include + +#include +#include +#include + +/* define message IDs */ +#include + +/* define message structures */ +#define vl_typedefs +#include +#undef vl_typedefs + +/* define generated endian-swappers */ +#define vl_endianfun +#include +#undef vl_endianfun + +/* instantiate all the print functions we know about */ +#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__) +#define vl_printfun +#include +#undef vl_printfun + +/* Get the API version number */ +#define vl_api_version(n,v) static u32 api_version=(v); +#include +#undef vl_api_version + +/* + * A handy macro to set up a message reply. + * Assumes that the following variables are available: + * mp - pointer to request message + * rmp - pointer to reply message type + * rv - return value + */ + +#define REPLY_MACRO(t) \ +do { \ + unix_shared_memory_queue_t * q = \ + vl_api_client_index_to_input_queue (mp->client_index); \ + if (!q) \ + return; \ + \ + rmp = vl_msg_api_alloc (sizeof (*rmp)); \ + rmp->_vl_msg_id = ntohs((t)+sm->msg_id_base); \ + rmp->context = mp->context; \ + rmp->retval = ntohl(rv); \ + \ + vl_msg_api_send_shmem (q, (u8 *)&rmp); \ +} while(0); + +#define REPLY_MACRO2(t, body) \ +do { \ + unix_shared_memory_queue_t * q; \ + rv = vl_msg_api_pd_handler (mp, rv); \ + q = vl_api_client_index_to_input_queue (mp->client_index); \ + if (!q) \ + return; \ + \ + rmp = vl_msg_api_alloc (sizeof (*rmp)); \ + rmp->_vl_msg_id = ntohs((t)); \ + rmp->context = mp->context; \ + rmp->retval = ntohl(rv); \ + do {body;} while (0); \ + vl_msg_api_send_shmem (q, (u8 *)&rmp); \ +} while(0); + +/* List of message types that this plugin understands */ + +#define foreach_pot_plugin_api_msg \ +_(POT_PROFILE_ADD, pot_profile_add) \ +_(POT_PROFILE_ACTIVATE, pot_profile_activate) \ +_(POT_PROFILE_DEL, pot_profile_del) \ + +static void vl_api_pot_profile_add_t_handler +(vl_api_pot_profile_add_t *mp) +{ + pot_main_t * sm = &pot_main; + int rv = 0; + vl_api_pot_profile_add_reply_t * rmp; + u8 id; + pot_profile *profile = NULL; + u8 *name = 0; + + if (mp->list_name_len) + name = format(0, "%s", mp->list_name); + + pot_profile_list_init(name); + id = mp->id; + profile = pot_profile_find(id); + if (profile) { + rv = pot_profile_create(profile, + clib_net_to_host_u64(mp->prime), + clib_net_to_host_u64(mp->polynomial_public), + clib_net_to_host_u64(mp->lpc), + clib_net_to_host_u64(mp->secret_share)); + if (rv != 0) + goto ERROROUT; + if (1 == mp->validator) + (void)pot_set_validator(profile, clib_net_to_host_u64(mp->secret_key)); + (void)pot_profile_set_bit_mask(profile, mp->max_bits); + } else { + rv = -3; + } + ERROROUT: + vec_free(name); + REPLY_MACRO(VL_API_POT_PROFILE_ADD_REPLY); +} + +static void vl_api_pot_profile_activate_t_handler +(vl_api_pot_profile_activate_t *mp) +{ + pot_main_t * sm = &pot_main; + int rv = 0; + vl_api_pot_profile_add_reply_t * rmp; + u8 id; + u8 *name = NULL; + + if (mp->list_name_len) + name = format(0, "%s", mp->list_name); + if (!pot_profile_list_is_enabled(name)) { + rv = -1; + } else { + id = mp->id; + rv = pot_profile_set_active(id); + } + + vec_free(name); + REPLY_MACRO(VL_API_POT_PROFILE_ACTIVATE_REPLY); +} + + +static void vl_api_pot_profile_del_t_handler +(vl_api_pot_profile_del_t *mp) +{ + pot_main_t * sm = &pot_main; + int rv = 0; + vl_api_pot_profile_del_reply_t * rmp; + + clear_pot_profiles(); + + REPLY_MACRO(VL_API_POT_PROFILE_DEL_REPLY); +} + + +/* + * This routine exists to convince the vlib plugin framework that + * we haven't accidentally copied a random .dll into the plugin directory. + * + * Also collects global variable pointers passed from the vpp engine + */ + +clib_error_t * +vlib_plugin_register (vlib_main_t * vm, vnet_plugin_handoff_t * h, + int from_early_init) +{ + pot_main_t * sm = &pot_main; + clib_error_t * error = 0; + + sm->vlib_main = vm; + sm->vnet_main = h->vnet_main; + return error; +} + +/* Set up the API message handling tables */ +static clib_error_t * +pot_plugin_api_hookup (vlib_main_t *vm) +{ + pot_main_t * sm = &pot_main; +#define _(N,n) \ + vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base), \ + #n, \ + vl_api_##n##_t_handler, \ + vl_noop_handler, \ + vl_api_##n##_t_endian, \ + vl_api_##n##_t_print, \ + sizeof(vl_api_##n##_t), 1); + foreach_pot_plugin_api_msg; +#undef _ + + return 0; +} + +static clib_error_t * pot_init (vlib_main_t * vm) +{ + pot_main_t * sm = &pot_main; + clib_error_t * error = 0; + u8 * name; + + bzero(sm, sizeof(pot_main)); + (void)pot_util_init(); + name = format (0, "pot_%08x%c", api_version, 0); + + /* Ask for a correctly-sized block of API message decode slots */ + sm->msg_id_base = vl_msg_api_get_msg_ids + ((char *) name, VL_MSG_FIRST_AVAILABLE); + + error = pot_plugin_api_hookup (vm); + + vec_free(name); + + return error; +} + +VLIB_INIT_FUNCTION (pot_init); diff --git a/plugins/ioam-plugin/ioam/lib-pot/pot_msg_enum.h b/plugins/ioam-plugin/ioam/lib-pot/pot_msg_enum.h new file mode 100644 index 00000000..a4a88bed --- /dev/null +++ b/plugins/ioam-plugin/ioam/lib-pot/pot_msg_enum.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * 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 included_pot_msg_enum_h +#define included_pot_msg_enum_h + +#include + +#define vl_msg_id(n,h) n, +typedef enum { +#include + /* We'll want to know how many messages IDs we need... */ + VL_MSG_FIRST_AVAILABLE, +} vl_msg_id_t; +#undef vl_msg_id + +#endif /* included_pot_msg_enum_h */ diff --git a/plugins/ioam-plugin/ioam/lib-pot/pot_test.c b/plugins/ioam-plugin/ioam/lib-pot/pot_test.c new file mode 100644 index 00000000..8e728cea --- /dev/null +++ b/plugins/ioam-plugin/ioam/lib-pot/pot_test.c @@ -0,0 +1,313 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * 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. + */ +/* + *------------------------------------------------------------------ + * pot_test.c - test harness for pot plugin + *------------------------------------------------------------------ + */ + +#include +#include +#include +#include +#include + +/* Declare message IDs */ +#include + +/* define message structures */ +#define vl_typedefs +#include +#undef vl_typedefs + +/* declare message handlers for each api */ + +#define vl_endianfun /* define message structures */ +#include +#undef vl_endianfun + +/* instantiate all the print functions we know about */ +#define vl_print(handle, ...) +#define vl_printfun +#include +#undef vl_printfun + +/* Get the API version number. */ +#define vl_api_version(n,v) static u32 api_version=(v); +#include +#undef vl_api_version + + +typedef struct { + /* API message ID base */ + u16 msg_id_base; + vat_main_t *vat_main; +} pot_test_main_t; + +pot_test_main_t pot_test_main; + +#define foreach_standard_reply_retval_handler \ +_(pot_profile_add_reply) \ +_(pot_profile_activate_reply) \ +_(pot_profile_del_reply) + +#define _(n) \ + static void vl_api_##n##_t_handler \ + (vl_api_##n##_t * mp) \ + { \ + vat_main_t * vam = pot_test_main.vat_main; \ + i32 retval = ntohl(mp->retval); \ + if (vam->async_mode) { \ + vam->async_errors += (retval < 0); \ + } else { \ + vam->retval = retval; \ + vam->result_ready = 1; \ + } \ + } +foreach_standard_reply_retval_handler; +#undef _ + +/* + * Table of message reply handlers, must include boilerplate handlers + * we just generated + */ +#define foreach_vpe_api_reply_msg \ +_(POT_PROFILE_ADD_REPLY, pot_profile_add_reply) \ +_(POT_PROFILE_ACTIVATE_REPLY, pot_profile_activate_reply) \ +_(POT_PROFILE_DEL_REPLY, pot_profile_del_reply) \ + + +/* M: construct, but don't yet send a message */ + +#define M(T,t) \ +do { \ + vam->result_ready = 0; \ + mp = vl_msg_api_alloc(sizeof(*mp)); \ + memset (mp, 0, sizeof (*mp)); \ + mp->_vl_msg_id = ntohs (VL_API_##T + sm->msg_id_base); \ + mp->client_index = vam->my_client_index; \ +} while(0); + +#define M2(T,t,n) \ +do { \ + vam->result_ready = 0; \ + mp = vl_msg_api_alloc(sizeof(*mp)+(n)); \ + memset (mp, 0, sizeof (*mp)); \ + mp->_vl_msg_id = ntohs (VL_API_##T + sm->msg_id_base); \ + mp->client_index = vam->my_client_index; \ +} while(0); + +/* S: send a message */ +#define S (vl_msg_api_send_shmem (vam->vl_input_queue, (u8 *)&mp)) + +/* W: wait for results, with timeout */ +#define W \ +do { \ + timeout = vat_time_now (vam) + 1.0; \ + \ + while (vat_time_now (vam) < timeout) { \ + if (vam->result_ready == 1) { \ + return (vam->retval); \ + } \ + } \ + return -99; \ +} while(0); + + +static int api_pot_profile_add (vat_main_t *vam) +{ +#define MAX_BITS 64 + pot_test_main_t * sm = &pot_test_main; + unformat_input_t *input = vam->input; + vl_api_pot_profile_add_t *mp; + u8 *name = NULL; + u64 prime = 0; + u64 secret_share = 0; + u64 secret_key = 0; + u32 bits = MAX_BITS; + u64 lpc = 0, poly2 = 0; + f64 timeout; + u8 id = 0; + int rv = 0; + + while (unformat_check_input(input) != UNFORMAT_END_OF_INPUT) + { + if (unformat(input, "name %s", &name)) + ; + else if(unformat(input, "id %d", &id)) + ; + else if (unformat(input, "validator-key 0x%Lx", &secret_key)) + ; + else if (unformat(input, "prime-number 0x%Lx", &prime)) + ; + else if (unformat(input, "secret-share 0x%Lx", &secret_share)) + ; + else if (unformat(input, "polynomial-public 0x%Lx", &poly2)) + ; + else if (unformat(input, "lpc 0x%Lx", &lpc)) + ; + else if (unformat(input, "bits-in-random %u", &bits)) + { + if (bits > MAX_BITS) + bits = MAX_BITS; + } + else + break; + } + + if (!name) + { + errmsg ("name required\n"); + rv = -99; + goto OUT; + } + + M2(POT_PROFILE_ADD, pot_profile_add, vec_len(name)); + + mp->list_name_len = vec_len(name); + clib_memcpy(mp->list_name, name, mp->list_name_len); + mp->secret_share = clib_host_to_net_u64(secret_share); + mp->polynomial_public = clib_host_to_net_u64(poly2); + mp->lpc = clib_host_to_net_u64(lpc); + mp->prime = clib_host_to_net_u64(prime); + if (secret_key != 0) + { + mp->secret_key = clib_host_to_net_u64(secret_key); + mp->validator = 1; + } + else + { + mp->validator = 0; + } + mp->id = id; + mp->max_bits = bits; + + S; W; + +OUT: + vec_free(name); + return(rv); +} + +static int api_pot_profile_activate (vat_main_t *vam) +{ +#define MAX_BITS 64 + pot_test_main_t * sm = &pot_test_main; + unformat_input_t *input = vam->input; + vl_api_pot_profile_activate_t *mp; + u8 *name = NULL; + u8 id = 0; + int rv = 0; + f64 timeout; + + while (unformat_check_input(input) != UNFORMAT_END_OF_INPUT) + { + if (unformat(input, "name %s", &name)) + ; + else if(unformat(input, "id %d", &id)) + ; + else + break; + } + + if (!name) + { + errmsg ("name required\n"); + rv = -99; + goto OUT; + } + + M2(POT_PROFILE_ACTIVATE, pot_profile_activate, vec_len(name)); + + mp->list_name_len = vec_len(name); + clib_memcpy(mp->list_name, name, mp->list_name_len); + mp->id = id; + + S; W; + +OUT: + vec_free(name); + return(rv); +} + + +static int api_pot_profile_del (vat_main_t *vam) +{ + pot_test_main_t * sm = &pot_test_main; + vl_api_pot_profile_del_t *mp; + f64 timeout; + + M(POT_PROFILE_DEL, pot_profile_del); + mp->list_name_len = 0; + S; W; + return 0; +} + +/* + * List of messages that the api test plugin sends, + * and that the data plane plugin processes + */ +#define foreach_vpe_api_msg \ +_(pot_profile_add, "name id [0-1] " \ + "prime-number <0xu64> bits-in-random [0-64] " \ + "secret-share <0xu64> lpc <0xu64> polynomial-public <0xu64> " \ + "[validator-key <0xu64>] [validity <0xu64>]") \ +_(pot_profile_activate, "name id [0-1] ") \ +_(pot_profile_del, "[id ]") \ + + +void vat_api_hookup (vat_main_t *vam) +{ + pot_test_main_t * sm = &pot_test_main; + /* Hook up handlers for replies from the data plane plug-in */ +#define _(N,n) \ + vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base), \ + #n, \ + vl_api_##n##_t_handler, \ + vl_noop_handler, \ + vl_api_##n##_t_endian, \ + vl_api_##n##_t_print, \ + sizeof(vl_api_##n##_t), 1); + foreach_vpe_api_reply_msg; +#undef _ + + /* API messages we can send */ +#define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n); + foreach_vpe_api_msg; +#undef _ + + /* Help strings */ +#define _(n,h) hash_set_mem (vam->help_by_name, #n, h); + foreach_vpe_api_msg; +#undef _ +} + +clib_error_t * vat_plugin_register (vat_main_t *vam) +{ + pot_test_main_t * sm = &pot_test_main; + u8 * name; + + sm->vat_main = vam; + + name = format (0, "pot_%08x%c", api_version, 0); + sm->msg_id_base = vl_client_get_first_plugin_msg_id ((char *) name); + + if (sm->msg_id_base != (u16) ~0) + vat_api_hookup (vam); + + vec_free(name); + + return 0; +} diff --git a/plugins/ioam-plugin/ioam/lib-pot/pot_util.c b/plugins/ioam-plugin/ioam/lib-pot/pot_util.c new file mode 100644 index 00000000..0309cbec --- /dev/null +++ b/plugins/ioam-plugin/ioam/lib-pot/pot_util.c @@ -0,0 +1,446 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * 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 +#include +#include +#include +#include +#include "math64.h" +#include "pot_util.h" + +pot_main_t pot_main; + +static void pot_profile_cleanup(pot_profile *profile); + +static void pot_main_profiles_reset (void) +{ + pot_main_t *sm = &pot_main; + int i = 0; + + for (i = 0; i < MAX_POT_PROFILES; i++) + { + pot_profile_cleanup(&(sm->profile_list[i])); + } + sm->active_profile_id = 0; + if (sm->profile_list_name) + vec_free(sm->profile_list_name); + sm->profile_list_name = NULL; +} + +int pot_util_init (void) +{ + pot_main_profiles_reset(); + + return(0); +} + +static void pot_profile_init(pot_profile * new, u8 id) +{ + if (new) + { + memset(new, 0, sizeof(pot_profile)); + new->id = id; + } +} + +pot_profile *pot_profile_find(u8 id) +{ + pot_main_t *sm = &pot_main; + + if (id >= 0 && id < MAX_POT_PROFILES) + { + return (&(sm->profile_list[id])); + } + return (NULL); +} +static int pot_profile_name_equal (u8 *name0, u8 *name1) +{ + int len0, len1; + + len0 = vec_len (name0); + len1 = vec_len (name1); + if (len0 != len1) + return(0); + return (0==strncmp ((char *) name0, (char *)name1, len0)); +} + +int pot_profile_list_is_enabled (u8 *name) +{ + pot_main_t *sm = &pot_main; + return (pot_profile_name_equal(sm->profile_list_name, name)); +} + +void pot_profile_list_init(u8 * profile_list_name) +{ + pot_main_t *sm = &pot_main; + int i = 0; + + /* If it is the same profile list skip reset */ + if (pot_profile_name_equal(sm->profile_list_name, profile_list_name)) + { + return; + } + + pot_main_profiles_reset(); + if (vec_len(profile_list_name)) + sm->profile_list_name = (u8 *)vec_dup(profile_list_name); + else + sm->profile_list_name = 0; + sm->active_profile_id = 0; + + for (i = 0; i < MAX_POT_PROFILES; i++) + { + pot_profile_init(&(sm->profile_list[i]), i); + } +} + +static void pot_profile_cleanup(pot_profile * profile) +{ + u16 id = profile->id; + + memset(profile, 0, sizeof(pot_profile)); + profile->id = id; /* Restore id alone */ +} + +int pot_profile_create(pot_profile * profile, u64 prime, + u64 poly2, u64 lpc, u64 secret_share) +{ + if (profile && !profile->in_use) + { + pot_profile_cleanup(profile); + profile->prime = prime; + profile->primeinv = 1.0 / prime; + profile->lpc = lpc; + profile->poly_pre_eval = poly2; + profile->secret_share = secret_share; + profile->total_pkts_using_this_profile = 0; + profile->valid = 1; + return(0); + } + + return(-1); +} + +int pot_set_validator(pot_profile * profile, u64 key) +{ + if (profile && !profile->in_use) + { + profile->validator = 1; + profile->secret_key = key; + return(0); + } + return(-1); +} + +always_inline u64 pot_update_cumulative_inline(u64 cumulative, u64 random, + u64 secret_share, u64 prime, u64 lpc, u64 pre_split, double prime_inv) +{ + u64 share_random = 0; + u64 cumulative_new = 0; + + /* + * calculate split share for random + */ + share_random = add64_mod(pre_split, random, prime, prime_inv); + + /* + * lpc * (share_secret + share_random) + */ + share_random = add64_mod(share_random, secret_share, prime, prime_inv); + share_random = mul64_mod(share_random, lpc, prime, prime_inv); + + cumulative_new = add64_mod(cumulative, share_random, prime, prime_inv); + + return (cumulative_new); +} + +u64 pot_update_cumulative(pot_profile * profile, u64 cumulative, u64 random) +{ + if (profile && profile->valid != 0) + { + return (pot_update_cumulative_inline(cumulative, random, profile->secret_share, + profile->prime, profile->lpc, profile->poly_pre_eval, + profile->primeinv)); + } + return (0); +} + +always_inline u8 pot_validate_inline(u64 secret, u64 prime, double prime_inv, + u64 cumulative, u64 random) +{ + if (cumulative == (random + secret)) + { + return (1); + } + else if (cumulative == add64_mod(random, secret, prime, prime_inv)) + { + return (1); + } + return (0); +} + +/* + * return True if the cumulative matches secret from a profile + */ +u8 pot_validate(pot_profile * profile, u64 cumulative, u64 random) +{ + if (profile && profile->validator) + { + return (pot_validate_inline(profile->secret_key, profile->prime, + profile->primeinv, cumulative, random)); + } + return (0); +} + +/* + * Utility function to get random number per pack + */ +u64 pot_generate_random(pot_profile * profile) +{ + u64 random = 0; + int32_t second_half; + static u32 seed = 0; + + if (PREDICT_FALSE(!seed)) + seed = random_default_seed(); + + /* + * Upper 4 bytes seconds + */ + random = (u64) time(NULL); + + random &= 0xffffffff; + random = random << 32; + /* + * Lower 4 bytes random number + */ + second_half = random_u32(&seed); + + random |= second_half; + + if (PREDICT_TRUE(profile != NULL)) + { + random &= profile->bit_mask; + } + return (random); +} + +int pot_profile_set_bit_mask(pot_profile * profile, u16 bits) +{ + int sizeInBits; + + if (profile && !profile->in_use) + { + sizeInBits = sizeof(profile->bit_mask) * 8; + profile->bit_mask = + (bits >= + sizeInBits ? (u64) - 1 : (u64) ((u64) 1 << (u64) bits) - 1); + return(0); + } + return(-1); +} + +clib_error_t *clear_pot_profile_command_fn(vlib_main_t * vm, + unformat_input_t * input, vlib_cli_command_t * cmd) +{ + + pot_main_profiles_reset(); + + return 0; +} + +void clear_pot_profiles() +{ + clear_pot_profile_command_fn(0, 0, 0); +} + +VLIB_CLI_COMMAND(clear_pot_profile_command) = +{ +.path = "clear pot profile", +.short_help = "clear pot profile [|all]", +.function = clear_pot_profile_command_fn, +}; + +static clib_error_t *set_pot_profile_command_fn(vlib_main_t * vm, + unformat_input_t * input, vlib_cli_command_t * cmd) +{ + u64 prime; + u64 secret_share; + u64 secret_key; + u8 validator = 0; + u32 profile_id; + u32 bits; + u64 lpc = 0, poly2 = 0; + pot_profile *profile = NULL; + u8 *profile_list_name = NULL; + + bits = MAX_BITS; + + while (unformat_check_input(input) != UNFORMAT_END_OF_INPUT) + { + if (unformat(input, "name %s", + &profile_list_name)); + else if (unformat(input, "id %d", &profile_id)) + ; + else if (unformat(input, "validate-key 0x%Lx", &secret_key)) + validator = 1; + else if (unformat(input, "prime-number 0x%Lx", &prime)) + ; + else if (unformat(input, "secret_share 0x%Lx", &secret_share)) + ; + else if (unformat(input, "polynomial2 0x%Lx", &poly2)) + ; + else if (unformat(input, "lpc 0x%Lx", &lpc)) + ; + else if (unformat(input, "bits-in-random %d", &bits)) + { + if (bits > MAX_BITS) + bits = MAX_BITS; + } + else + return clib_error_return(0, "unknown input `%U'", + format_unformat_error, input); + } + if (profile_list_name == 0) + { + return clib_error_return(0, "Name cannot be null"); + } + pot_profile_list_init(profile_list_name); + profile = pot_profile_find(profile_id); + + if (profile) + { + pot_profile_create(profile, prime, poly2, lpc, secret_share); + if (validator) + pot_set_validator(profile, secret_key); + pot_profile_set_bit_mask(profile, bits); + } + vec_free(profile_list_name); + return 0; +} + +VLIB_CLI_COMMAND(set_pot_profile_command) = +{ +.path = "set pot profile", +.short_help = "set pot profile name id [0-1] [validator-key 0xu64] \ + prime-number 0xu64 secret_share 0xu64 lpc 0xu64 \ + polynomial2 0xu64 bits-in-random [0-64] ", +.function = set_pot_profile_command_fn, +}; + +static clib_error_t *set_pot_profile_activate_command_fn(vlib_main_t * vm, + unformat_input_t * input, vlib_cli_command_t * cmd) +{ + pot_main_t *sm = &pot_main; + u8 *profile_list_name = NULL; + u32 id = 0; + clib_error_t *result = NULL; + + while (unformat_check_input(input) != UNFORMAT_END_OF_INPUT) + { + if (unformat(input, "name %s", + &profile_list_name)); + else if (unformat(input, "id %d", &id)) + ; + else + return clib_error_return(0, "unknown input `%U'", + format_unformat_error, input); + } + if (profile_list_name == 0) + { + return clib_error_return(0, "Name cannot be null"); + } + + if (!pot_profile_list_is_enabled(profile_list_name)) { + result = clib_error_return(0, "%s list is not enabled, profile in use %s", + profile_list_name, sm->profile_list_name); + } else if (0 != pot_profile_set_active((u8)id)) { + result = clib_error_return(0, "Profile %d not defined in %s", + id, sm->profile_list_name); + } + vec_free(profile_list_name); + return result; +} + +VLIB_CLI_COMMAND(set_pot_profile_activate_command) = +{ +.path = "set pot profile-active", +.short_help = "set pot profile-active name id [0-1]", +.function = set_pot_profile_activate_command_fn, +}; + +static clib_error_t *show_pot_profile_command_fn(vlib_main_t * vm, + unformat_input_t * input, vlib_cli_command_t * cmd) +{ + pot_main_t *sm = &pot_main; + pot_profile *p = NULL; + u16 i; + u8 *s = 0; + + if (vec_len(sm->profile_list_name) == 0) + { + s = format(s, "POT Profiles not configured\n"); + vlib_cli_output(vm, "%v", s); + return 0; + } + s = format(s, "Profile list in use : %s\n",sm->profile_list_name); + for (i = 0; i < MAX_POT_PROFILES; i++) + { + p = pot_profile_find(i); + if (p->valid == 0) + continue; + s = format(s, "POT Profile at index: %d\n", i); + s = format(s, " Id : %d\n", p->id); + s = format(s, " Validator : %s (%d)\n", + (p->validator) ? "True" : "False", p->validator); + if (p->validator == 1) + s = format(s, " Secret key : 0x%Lx (%Ld)\n", + p->secret_key, p->secret_key); + s = format(s, " Secret share : 0x%Lx (%Ld)\n", + p->secret_share, p->secret_share); + s = format(s, " Prime number : 0x%Lx (%Ld)\n", + p->prime, p->prime); + s = format(s, "2nd polynomial(eval) : 0x%Lx (%Ld)\n", + p->poly_pre_eval, p->poly_pre_eval); + s = format(s, " LPC : 0x%Lx (%Ld)\n", p->lpc, p->lpc); + + s = format(s, " Bit mask : 0x%Lx (%Ld)\n", + p->bit_mask, p->bit_mask); + } + + p = pot_profile_find(sm->active_profile_id); + + if (p && p->valid && p->in_use) { + s = format(s, "\nProfile index in use: %d\n", sm->active_profile_id); + s = format(s, "Pkts passed : 0x%Lx (%Ld)\n", + p->total_pkts_using_this_profile, + p->total_pkts_using_this_profile); + if (pot_is_decap(p)) + s = format(s, " This is Decap node. \n"); + } else { + s = format(s, "\nProfile index in use: None\n"); + } + vlib_cli_output(vm, "%v", s); + vec_free(s); + + return 0; +} + +VLIB_CLI_COMMAND(show_pot_profile_command) = +{ +.path = "show pot profile", +.short_help = "show pot profile", +.function = show_pot_profile_command_fn, +}; diff --git a/plugins/ioam-plugin/ioam/lib-pot/pot_util.h b/plugins/ioam-plugin/ioam/lib-pot/pot_util.h new file mode 100644 index 00000000..9df31fae --- /dev/null +++ b/plugins/ioam-plugin/ioam/lib-pot/pot_util.h @@ -0,0 +1,195 @@ +/* + * pot_util.h -- Proof Of Transit Utility Header + * + * Copyright (c) 2016 Cisco and/or its affiliates. + * 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_vnet_pot_util_h +#define include_vnet_pot_util_h + +#include +#define debug_ioam debug_ioam_fn +/* Dont change this size 256. This is there across multiple components */ +#define PATH_NAME_SIZE 256 + +/* Ring size. this should be same as the one in ODL. Do not change this + without change in ODL. */ +#define MAX_POT_PROFILES 2 + +/** + * Usage: + * + * On any node that participates in Proof of Transit: + * + * Step 1: Initialize this library by calling pot_init() + * Step 2: Setup a proof of transit profile that contains all the parameters needed to compute cumulative: + * Call these functions: + * pot_profile_find + * pot_profile_create + * pot_profile_set_bit_mask - To setup how large we want the numbers used in the computation and random number <= 64 bits + * Step 2a: For validator do this: + * pot_set_validator + * Step 2b: On initial node enable the profile to be used: + * pot_profile_set_active / pot_profile_get_active will return the profile + * Step 3a: At the initial node to generate Random number that will be read by all other nodes: + * pot_generate_random + * Step 3b: At all nodes including initial and verifier call this to compute cumulative: + * pot_update_cumulative + * Step 4: At the verifier: + * pot_validate + * + */ + +typedef struct pot_profile_ +{ + u8 id : 1; + u8 valid : 1; + u8 in_use : 1; + u64 random; + u8 validator; + u64 secret_key; + u64 secret_share; + u64 prime; + u64 lpc; + u64 poly_pre_eval; + u64 bit_mask; + u64 limit; + double primeinv; + u64 total_pkts_using_this_profile; +} pot_profile; + +typedef struct { + /* Name of the default profile list in use*/ + u8 *profile_list_name; + pot_profile profile_list[MAX_POT_PROFILES]; + /* number of profiles in the list */ + u8 active_profile_id : 1; + + /* API message ID base */ + u16 msg_id_base; + + /* convenience */ + vlib_main_t * vlib_main; + vnet_main_t * vnet_main; +} pot_main_t; + +extern pot_main_t pot_main; + +/* + * Initialize proof of transit + */ +int pot_util_init(void); +void pot_profile_list_init(u8 * name); + + +/* + * Find a pot profile by ID + */ +pot_profile *pot_profile_find(u8 id); + +static inline u16 pot_profile_get_id(pot_profile * profile) +{ + if (profile) + { + return (profile->id); + } + return (0); +} + +/* setup and clean up profile */ +int pot_profile_create(pot_profile * profile, u64 prime, + u64 poly2, u64 lpc, u64 secret_share); +/* + * Setup profile as a validator + */ +int pot_set_validator(pot_profile * profile, u64 key); + +/* + * Setup max bits to be used for random number generation + */ +#define MAX_BITS 64 +int pot_profile_set_bit_mask(pot_profile * profile, u16 bits); + +/* + * Given a random and cumulative compute the new cumulative for a given profile + */ +u64 pot_update_cumulative(pot_profile * profile, u64 cumulative, u64 random); + +/* + * return True if the cumulative matches secret from a profile + */ +u8 pot_validate(pot_profile * profile, u64 cumulative, u64 random); + +/* + * Utility function to get random number per pack + */ +u64 pot_generate_random(pot_profile * profile); + + +extern void clear_pot_profiles(); +extern int pot_profile_list_is_enabled(u8 *name); + +static inline u8 pot_is_decap(pot_profile * p) +{ + return (p->validator == 1); +} + +static inline int pot_profile_set_active (u8 id) +{ + pot_main_t *sm = &pot_main; + pot_profile *profile = NULL; + pot_profile *current_active_prof = NULL; + + current_active_prof = pot_profile_find(sm->active_profile_id); + profile = pot_profile_find(id); + if (profile && profile->valid) { + sm->active_profile_id = id; + current_active_prof->in_use = 0; + profile->in_use = 1; + return(0); + } + return(-1); +} +static inline u8 pot_profile_get_active_id (void) +{ + pot_main_t *sm = &pot_main; + return (sm->active_profile_id); +} + +static inline pot_profile * pot_profile_get_active (void) +{ + pot_main_t *sm = &pot_main; + pot_profile *profile = NULL; + profile = pot_profile_find(sm->active_profile_id); + if (profile && profile->in_use) + return(profile); + return (NULL); +} + +static inline void pot_profile_reset_usage_stats (pot_profile *pow) +{ + if (pow) { + pow->total_pkts_using_this_profile = 0; + } +} + +static inline void pot_profile_incr_usage_stats (pot_profile *pow) +{ + if (pow) { + pow->total_pkts_using_this_profile++; + } +} + + +#endif diff --git a/plugins/plugins/ioam/encap/ip6_ioam_pot.c b/plugins/plugins/ioam/encap/ip6_ioam_pot.c deleted file mode 100644 index 7af805e3..00000000 --- a/plugins/plugins/ioam/encap/ip6_ioam_pot.c +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * 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 -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include - -typedef CLIB_PACKED(struct { - ip6_hop_by_hop_option_t hdr; - u8 pot_type; -#define PROFILE_ID_MASK 0xF - u8 reserved_profile_id; /* 4 bits reserved, 4 bits to carry profile id */ - u64 random; - u64 cumulative; -}) ioam_pot_option_t; - -#define foreach_ip6_hop_by_hop_ioam_pot_stats \ - _(PROCESSED, "Pkts with ip6 hop-by-hop pot options") \ - _(PROFILE_MISS, "Pkts with ip6 hop-by-hop pot options but no profile set") \ - _(PASSED, "Pkts with POT in Policy") \ - _(FAILED, "Pkts with POT out of Policy") - -static char * ip6_hop_by_hop_ioam_pot_stats_strings[] = { -#define _(sym,string) string, - foreach_ip6_hop_by_hop_ioam_pot_stats -#undef _ -}; - -typedef enum { -#define _(sym,str) IP6_IOAM_POT_##sym, - foreach_ip6_hop_by_hop_ioam_pot_stats -#undef _ - IP6_IOAM_POT_N_STATS, -} ip6_ioam_pot_stats_t; - -typedef struct { - /* stats */ - u64 counters[ARRAY_LEN(ip6_hop_by_hop_ioam_pot_stats_strings)]; - - /* convenience */ - vlib_main_t * vlib_main; - vnet_main_t * vnet_main; -} ip6_hop_by_hop_ioam_pot_main_t; - -ip6_hop_by_hop_ioam_pot_main_t ip6_hop_by_hop_ioam_pot_main; - -always_inline void -ip6_ioam_stats_increment_counter (u32 counter_index, u64 increment) -{ - ip6_hop_by_hop_ioam_pot_main_t *hm = &ip6_hop_by_hop_ioam_pot_main; - - hm->counters[counter_index] += increment; -} - - -static u8 * format_ioam_pot (u8 * s, va_list * args) -{ - ioam_pot_option_t * pot0 = va_arg (*args, ioam_pot_option_t *); - u64 random, cumulative; - random = cumulative = 0; - if (pot0) - { - random = clib_net_to_host_u64 (pot0->random); - cumulative = clib_net_to_host_u64 (pot0->cumulative); - } - - s = format (s, "random = 0x%Lx, Cumulative = 0x%Lx, Index = 0x%x", - random, cumulative, pot0->reserved_profile_id); - return s; -} - -u8 * -ip6_hbh_ioam_proof_of_transit_trace_handler (u8 *s, ip6_hop_by_hop_option_t *opt) -{ - ioam_pot_option_t *pot; - - s = format (s, " POT opt present\n"); - pot = (ioam_pot_option_t *) opt; - s = format (s, " %U\n", format_ioam_pot, pot); - return (s); -} - -int -ip6_hbh_ioam_proof_of_transit_handler (vlib_buffer_t *b, - ip6_header_t *ip, - ip6_hop_by_hop_option_t *opt0) -{ - ioam_pot_option_t * pot0; - u64 random = 0, cumulative = 0; - int rv = 0; - u8 pot_profile_index; - pot_profile *pot_profile = 0, *new_profile = 0; - u8 pot_encap = 0; - - pot0 = (ioam_pot_option_t *) opt0; - pot_encap = (pot0->random == 0); - pot_profile_index = pot_profile_get_active_id(); - pot_profile = pot_profile_get_active(); - if (pot_encap && PREDICT_FALSE(!pot_profile)) - { - ip6_ioam_stats_increment_counter (IP6_IOAM_POT_PROFILE_MISS, 1); - return(-1); - } - if (pot_encap) - { - pot0->reserved_profile_id = - pot_profile_index & PROFILE_ID_MASK; - pot_profile_incr_usage_stats(pot_profile); - } - else - { /* Non encap node */ - if (PREDICT_FALSE(pot0->reserved_profile_id != - pot_profile_index || pot_profile == 0)) - { - /* New profile announced by encap node. */ - new_profile = - pot_profile_find(pot0->reserved_profile_id); - if (PREDICT_FALSE(new_profile == 0 || - new_profile->valid == 0)) - { - ip6_ioam_stats_increment_counter (IP6_IOAM_POT_PROFILE_MISS, 1); - return(-1); - } - else - { - pot_profile_index = pot0->reserved_profile_id; - pot_profile = new_profile; - pot_profile_set_active(pot_profile_index); - pot_profile_reset_usage_stats(pot_profile); - } - } - pot_profile_incr_usage_stats(pot_profile); - } - - if (pot0->random == 0) - { - pot0->random = clib_host_to_net_u64(pot_generate_random(pot_profile)); - pot0->cumulative = 0; - } - random = clib_net_to_host_u64(pot0->random); - cumulative = clib_net_to_host_u64(pot0->cumulative); - pot0->cumulative = clib_host_to_net_u64( - pot_update_cumulative(pot_profile, - cumulative, - random)); - ip6_ioam_stats_increment_counter (IP6_IOAM_POT_PROCESSED, 1); - - return (rv); -} - -int -ip6_hbh_ioam_proof_of_transit_pop_handler (ip6_header_t *ip, - ip6_hop_by_hop_option_t *opt0) -{ - ioam_pot_option_t * pot0; - u64 random = 0; - u64 cumulative = 0; - int rv = 0; - pot_profile *pot_profile = 0; - u8 result = 0; - - pot0 = (ioam_pot_option_t *) opt0; - random = clib_net_to_host_u64(pot0->random); - cumulative = clib_net_to_host_u64(pot0->cumulative); - pot_profile = pot_profile_get_active(); - result = pot_validate (pot_profile, - cumulative, random); - - if (result == 1) - { - ip6_ioam_stats_increment_counter (IP6_IOAM_POT_PASSED, 1); - } - else - { - ip6_ioam_stats_increment_counter (IP6_IOAM_POT_FAILED, 1); - } - return (rv); -} - -int ip6_hop_by_hop_ioam_pot_rewrite_handler (u8 *rewrite_string, u8 rewrite_size) -{ - ioam_pot_option_t * pot_option; - if (rewrite_string && rewrite_size == sizeof(ioam_pot_option_t)) - { - pot_option = (ioam_pot_option_t *)rewrite_string; - pot_option->hdr.type = HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT - | HBH_OPTION_TYPE_DATA_CHANGE_ENROUTE; - pot_option->hdr.length = sizeof (ioam_pot_option_t) - - sizeof (ip6_hop_by_hop_option_t); - return(0); - } - return(-1); -} - -static clib_error_t * -ip6_show_ioam_pot_cmd_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - ip6_hop_by_hop_ioam_pot_main_t *hm = &ip6_hop_by_hop_ioam_pot_main; - u8 *s = 0; - int i = 0; - - for ( i = 0; i < IP6_IOAM_POT_N_STATS; i++) - { - s = format(s, " %s - %lu\n", ip6_hop_by_hop_ioam_pot_stats_strings[i], - hm->counters[i]); - } - - vlib_cli_output(vm, "%v", s); - vec_free(s); - return 0; -} - - -VLIB_CLI_COMMAND (ip6_show_ioam_pot_cmd, static) = { - .path = "show ioam pot", - .short_help = "iOAM pot statistics", - .function = ip6_show_ioam_pot_cmd_fn, -}; - - -static clib_error_t * -ip6_hop_by_hop_ioam_pot_init (vlib_main_t * vm) -{ - ip6_hop_by_hop_ioam_pot_main_t * hm = &ip6_hop_by_hop_ioam_pot_main; - clib_error_t * error; - - if ((error = vlib_call_init_function (vm, ip_main_init))) - return(error); - - if ((error = vlib_call_init_function (vm, ip6_lookup_init))) - return error; - - if ((error = vlib_call_init_function (vm, ip6_hop_by_hop_ioam_init))) - return(error); - - hm->vlib_main = vm; - hm->vnet_main = vnet_get_main(); - memset(hm->counters, 0, sizeof(hm->counters)); - - if (ip6_hbh_register_option(HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT, ip6_hbh_ioam_proof_of_transit_handler, - ip6_hbh_ioam_proof_of_transit_trace_handler) < 0) - return (clib_error_create("registration of HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT failed")); - - if (ip6_hbh_add_register_option(HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT, - sizeof(ioam_pot_option_t), - ip6_hop_by_hop_ioam_pot_rewrite_handler) < 0) - return (clib_error_create("registration of HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT for rewrite failed")); - - if (ip6_hbh_pop_register_option(HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT, - ip6_hbh_ioam_proof_of_transit_pop_handler) < 0) - return (clib_error_create("registration of HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT POP failed")); - - return (0); -} - -VLIB_INIT_FUNCTION (ip6_hop_by_hop_ioam_pot_init); - - diff --git a/plugins/plugins/ioam/lib-pot/math64.h b/plugins/plugins/ioam/lib-pot/math64.h deleted file mode 100644 index 4c608a37..00000000 --- a/plugins/plugins/ioam/lib-pot/math64.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - * math64.h provides the 64 bit unsigned integer add, multiply followed by modulo operation - * The linux/math64.h provides divide and multiply 64 bit integers but: - * 1. multiply: mul_u64_u64_shr - only returns 64 bits of the result and has to be called - * twice to get the complete 128 bits of the result. - * 2. Modulo operation of the result of addition and multiplication of u64 that may result - * in integers > 64 bits is not supported - * Hence this header to combine add/multiply followed by modulo of u64 integrers - * always resulting in u64. - * - * Copyright (c) 2016 Cisco and/or its affiliates. - * 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_vnet_math64_h -#define include_vnet_math64_h -#include - -/* - * multiplies and returns result in hi and lo - */ -static inline void mul64by64(u64 a, u64 b, u64 * hi, u64 * lo) -{ - u64 a_lo = (u64) (uint32_t) a; - u64 a_hi = a >> 32; - u64 b_lo = (u64) (u32) b; - u64 b_hi = b >> 32; - - u64 p0 = a_lo * b_lo; - u64 p1 = a_lo * b_hi; - u64 p2 = a_hi * b_lo; - u64 p3 = a_hi * b_hi; - - u32 cy = (u32) (((p0 >> 32) + (u32) p1 + (u32) p2) >> 32); - - *lo = p0 + (p1 << 32) + (p2 << 32); - *hi = p3 + (p1 >> 32) + (p2 >> 32) + cy; - return; -} - -#define TWO64 18446744073709551616.0 - -static inline u64 mod128by64(u64 x, u64 y, u64 m, double di) -{ - u64 q1, q2, q; - u64 p1, p0; - double dq; - - /* calculate quotient first pass 53 bits */ - dq = (TWO64 * (double)x + (double)y) * di; - - if (dq >= TWO64) - q1 = 0xfffffffffffff800L; - else - q1 = dq; - - /* q1 * m to compare the product to the dividend. */ - mul64by64(q1, m, &p1, &p0); - - /* Adjust quotient. is it > actual result: */ - if (x < p1 || (x == p1 && y < p0)) - { - /* q1 > quotient. calculate abs remainder */ - x = p1 - (x + (p0 < y)); - y = p0 - y; - - /* use the remainder as new dividend to adjust quotient */ - q2 = (u64) ((TWO64 * (double)x + (double)y) * di); - mul64by64(q2, m, &p1, &p0); - - q = q1 - q2; - if (x < p1 || (x == p1 && y <= p0)) - { - y = p0 - y; - } - else - { - y = p0 - y; - y += m; - q--; - } - } - else - { - x = x - (p1 + (y < p0)); - y = y - p0; - - q2 = (u64) ((TWO64 * (double)x + (double)y) * di); - mul64by64(q2, m, &p1, &p0); - - q = q1 + q2; - if (x < p1 || (x == p1 && y < p0)) - { - y = y - p0; - y += m; - q--; - } - else - { - y = y - p0; - if (y >= m) - { - y -= m; - q++; - } - } - } - - return y; -} - -/* - * returns a % p - */ -static inline u64 mod64by64(u64 a, u64 p, u64 primeinv) -{ - return (mod128by64(0, a, p, primeinv)); -} - -static inline void add64(u64 a, u64 b, u64 * whi, u64 * wlo) -{ - *wlo = a + b; - if (*wlo < a) - *whi = 1; - -} - -/* - * returns (a + b)%p - */ -static inline u64 add64_mod(u64 a, u64 b, u64 p, double pi) -{ - u64 shi = 0, slo = 0; - - add64(a, b, &shi, &slo); - return (mod128by64(shi, slo, p, pi)); -} - -/* - * returns (ab) % p - */ -static inline u64 mul64_mod(u64 a, u64 b, u64 p, double pi) -{ - u64 phi = 0, plo = 0; - - mul64by64(a, b, &phi, &plo); - return (mod128by64(phi, plo, p, pi)); -} - -#endif diff --git a/plugins/plugins/ioam/lib-pot/pot.api b/plugins/plugins/ioam/lib-pot/pot.api deleted file mode 100644 index 7fd06b51..00000000 --- a/plugins/plugins/ioam/lib-pot/pot.api +++ /dev/null @@ -1,97 +0,0 @@ -/* Hey Emacs use -*- mode: C -*- */ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * 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. - */ - - -/** \brief Proof of Transit(POT): Set POT profile - @param id - id of the profile - @param validator - True/False to indicate if this is verifier - @param secret_key - Verification key - @param secret_share - Share of the 1st polynomial - @param prime - Prime number used for modulo operation - @param max_bits - Max bits to be used for Random number generation - @param lpc - Lagrange basis polynomial - @param polynomial_public - pre-evaluated public polynomial - @param list_name_len - length of the name of this profile list - @param list_name - name of this profile list -*/ -define pot_profile_add { - u32 client_index; - u32 context; - u8 id; - u8 validator; - u64 secret_key; - u64 secret_share; - u64 prime; - u8 max_bits; - u64 lpc; - u64 polynomial_public; - u8 list_name_len; - u8 list_name[0]; -}; - -/** \brief Proof of Transit profile add / del response - @param context - sender context, to match reply w/ request - @param retval - return value for request -*/ -define pot_profile_add_reply { - u32 context; - i32 retval; -}; - - -/** \brief Proof of Transit(POT): Activate POT profile in the list - @param id - id of the profile - @param list_name_len - length of the name of this profile list - @param list_name - name of this profile list -*/ -define pot_profile_activate { - u32 client_index; - u32 context; - u8 id; - u8 list_name_len; - u8 list_name[0]; -}; - -/** \brief Proof of Transit profile activate response - @param context - sender context, to match reply w/ request - @param retval - return value for request -*/ -define pot_profile_activate_reply { - u32 context; - i32 retval; -}; - -/** \brief Delete POT Profile - @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request - @param list_name_len - length of the name of the profile list - @param list_name - name of profile list to delete -*/ -define pot_profile_del { - u32 client_index; - u32 context; - u8 list_name_len; - u8 list_name[0]; -}; - -/** \brief Proof of Transit profile add / del response - @param context - sender context, to match reply w/ request - @param retval - return value for request -*/ -define pot_profile_del_reply { - u32 context; - i32 retval; -}; diff --git a/plugins/plugins/ioam/lib-pot/pot_all_api_h.h b/plugins/plugins/ioam/lib-pot/pot_all_api_h.h deleted file mode 100644 index 74dfc484..00000000 --- a/plugins/plugins/ioam/lib-pot/pot_all_api_h.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * 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 the generated file, see BUILT_SOURCES in Makefile.am */ -#include diff --git a/plugins/plugins/ioam/lib-pot/pot_api.c b/plugins/plugins/ioam/lib-pot/pot_api.c deleted file mode 100644 index e5af1fae..00000000 --- a/plugins/plugins/ioam/lib-pot/pot_api.c +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * 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. - */ -/* - *------------------------------------------------------------------ - * pot_api.c - Proof of Transit related APIs to create - * and maintain profiles - *------------------------------------------------------------------ - */ - -#include -#include -#include - -#include -#include -#include - -/* define message IDs */ -#include - -/* define message structures */ -#define vl_typedefs -#include -#undef vl_typedefs - -/* define generated endian-swappers */ -#define vl_endianfun -#include -#undef vl_endianfun - -/* instantiate all the print functions we know about */ -#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__) -#define vl_printfun -#include -#undef vl_printfun - -/* Get the API version number */ -#define vl_api_version(n,v) static u32 api_version=(v); -#include -#undef vl_api_version - -/* - * A handy macro to set up a message reply. - * Assumes that the following variables are available: - * mp - pointer to request message - * rmp - pointer to reply message type - * rv - return value - */ - -#define REPLY_MACRO(t) \ -do { \ - unix_shared_memory_queue_t * q = \ - vl_api_client_index_to_input_queue (mp->client_index); \ - if (!q) \ - return; \ - \ - rmp = vl_msg_api_alloc (sizeof (*rmp)); \ - rmp->_vl_msg_id = ntohs((t)+sm->msg_id_base); \ - rmp->context = mp->context; \ - rmp->retval = ntohl(rv); \ - \ - vl_msg_api_send_shmem (q, (u8 *)&rmp); \ -} while(0); - -#define REPLY_MACRO2(t, body) \ -do { \ - unix_shared_memory_queue_t * q; \ - rv = vl_msg_api_pd_handler (mp, rv); \ - q = vl_api_client_index_to_input_queue (mp->client_index); \ - if (!q) \ - return; \ - \ - rmp = vl_msg_api_alloc (sizeof (*rmp)); \ - rmp->_vl_msg_id = ntohs((t)); \ - rmp->context = mp->context; \ - rmp->retval = ntohl(rv); \ - do {body;} while (0); \ - vl_msg_api_send_shmem (q, (u8 *)&rmp); \ -} while(0); - -/* List of message types that this plugin understands */ - -#define foreach_pot_plugin_api_msg \ -_(POT_PROFILE_ADD, pot_profile_add) \ -_(POT_PROFILE_ACTIVATE, pot_profile_activate) \ -_(POT_PROFILE_DEL, pot_profile_del) \ - -static void vl_api_pot_profile_add_t_handler -(vl_api_pot_profile_add_t *mp) -{ - pot_main_t * sm = &pot_main; - int rv = 0; - vl_api_pot_profile_add_reply_t * rmp; - u8 id; - pot_profile *profile = NULL; - u8 *name = 0; - - if (mp->list_name_len) - name = format(0, "%s", mp->list_name); - - pot_profile_list_init(name); - id = mp->id; - profile = pot_profile_find(id); - if (profile) { - rv = pot_profile_create(profile, - clib_net_to_host_u64(mp->prime), - clib_net_to_host_u64(mp->polynomial_public), - clib_net_to_host_u64(mp->lpc), - clib_net_to_host_u64(mp->secret_share)); - if (rv != 0) - goto ERROROUT; - if (1 == mp->validator) - (void)pot_set_validator(profile, clib_net_to_host_u64(mp->secret_key)); - (void)pot_profile_set_bit_mask(profile, mp->max_bits); - } else { - rv = -3; - } - ERROROUT: - vec_free(name); - REPLY_MACRO(VL_API_POT_PROFILE_ADD_REPLY); -} - -static void vl_api_pot_profile_activate_t_handler -(vl_api_pot_profile_activate_t *mp) -{ - pot_main_t * sm = &pot_main; - int rv = 0; - vl_api_pot_profile_add_reply_t * rmp; - u8 id; - u8 *name = NULL; - - if (mp->list_name_len) - name = format(0, "%s", mp->list_name); - if (!pot_profile_list_is_enabled(name)) { - rv = -1; - } else { - id = mp->id; - rv = pot_profile_set_active(id); - } - - vec_free(name); - REPLY_MACRO(VL_API_POT_PROFILE_ACTIVATE_REPLY); -} - - -static void vl_api_pot_profile_del_t_handler -(vl_api_pot_profile_del_t *mp) -{ - pot_main_t * sm = &pot_main; - int rv = 0; - vl_api_pot_profile_del_reply_t * rmp; - - clear_pot_profiles(); - - REPLY_MACRO(VL_API_POT_PROFILE_DEL_REPLY); -} - - -/* - * This routine exists to convince the vlib plugin framework that - * we haven't accidentally copied a random .dll into the plugin directory. - * - * Also collects global variable pointers passed from the vpp engine - */ - -clib_error_t * -vlib_plugin_register (vlib_main_t * vm, vnet_plugin_handoff_t * h, - int from_early_init) -{ - pot_main_t * sm = &pot_main; - clib_error_t * error = 0; - - sm->vlib_main = vm; - sm->vnet_main = h->vnet_main; - return error; -} - -/* Set up the API message handling tables */ -static clib_error_t * -pot_plugin_api_hookup (vlib_main_t *vm) -{ - pot_main_t * sm = &pot_main; -#define _(N,n) \ - vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base), \ - #n, \ - vl_api_##n##_t_handler, \ - vl_noop_handler, \ - vl_api_##n##_t_endian, \ - vl_api_##n##_t_print, \ - sizeof(vl_api_##n##_t), 1); - foreach_pot_plugin_api_msg; -#undef _ - - return 0; -} - -static clib_error_t * pot_init (vlib_main_t * vm) -{ - pot_main_t * sm = &pot_main; - clib_error_t * error = 0; - u8 * name; - - bzero(sm, sizeof(pot_main)); - (void)pot_util_init(); - name = format (0, "pot_%08x%c", api_version, 0); - - /* Ask for a correctly-sized block of API message decode slots */ - sm->msg_id_base = vl_msg_api_get_msg_ids - ((char *) name, VL_MSG_FIRST_AVAILABLE); - - error = pot_plugin_api_hookup (vm); - - vec_free(name); - - return error; -} - -VLIB_INIT_FUNCTION (pot_init); diff --git a/plugins/plugins/ioam/lib-pot/pot_msg_enum.h b/plugins/plugins/ioam/lib-pot/pot_msg_enum.h deleted file mode 100644 index 87fae740..00000000 --- a/plugins/plugins/ioam/lib-pot/pot_msg_enum.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * 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 included_pot_msg_enum_h -#define included_pot_msg_enum_h - -#include - -#define vl_msg_id(n,h) n, -typedef enum { -#include - /* We'll want to know how many messages IDs we need... */ - VL_MSG_FIRST_AVAILABLE, -} vl_msg_id_t; -#undef vl_msg_id - -#endif /* included_pot_msg_enum_h */ diff --git a/plugins/plugins/ioam/lib-pot/pot_test.c b/plugins/plugins/ioam/lib-pot/pot_test.c deleted file mode 100644 index a6d9330f..00000000 --- a/plugins/plugins/ioam/lib-pot/pot_test.c +++ /dev/null @@ -1,313 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * 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. - */ -/* - *------------------------------------------------------------------ - * pot_test.c - test harness for pot plugin - *------------------------------------------------------------------ - */ - -#include -#include -#include -#include -#include - -/* Declare message IDs */ -#include - -/* define message structures */ -#define vl_typedefs -#include -#undef vl_typedefs - -/* declare message handlers for each api */ - -#define vl_endianfun /* define message structures */ -#include -#undef vl_endianfun - -/* instantiate all the print functions we know about */ -#define vl_print(handle, ...) -#define vl_printfun -#include -#undef vl_printfun - -/* Get the API version number. */ -#define vl_api_version(n,v) static u32 api_version=(v); -#include -#undef vl_api_version - - -typedef struct { - /* API message ID base */ - u16 msg_id_base; - vat_main_t *vat_main; -} pot_test_main_t; - -pot_test_main_t pot_test_main; - -#define foreach_standard_reply_retval_handler \ -_(pot_profile_add_reply) \ -_(pot_profile_activate_reply) \ -_(pot_profile_del_reply) - -#define _(n) \ - static void vl_api_##n##_t_handler \ - (vl_api_##n##_t * mp) \ - { \ - vat_main_t * vam = pot_test_main.vat_main; \ - i32 retval = ntohl(mp->retval); \ - if (vam->async_mode) { \ - vam->async_errors += (retval < 0); \ - } else { \ - vam->retval = retval; \ - vam->result_ready = 1; \ - } \ - } -foreach_standard_reply_retval_handler; -#undef _ - -/* - * Table of message reply handlers, must include boilerplate handlers - * we just generated - */ -#define foreach_vpe_api_reply_msg \ -_(POT_PROFILE_ADD_REPLY, pot_profile_add_reply) \ -_(POT_PROFILE_ACTIVATE_REPLY, pot_profile_activate_reply) \ -_(POT_PROFILE_DEL_REPLY, pot_profile_del_reply) \ - - -/* M: construct, but don't yet send a message */ - -#define M(T,t) \ -do { \ - vam->result_ready = 0; \ - mp = vl_msg_api_alloc(sizeof(*mp)); \ - memset (mp, 0, sizeof (*mp)); \ - mp->_vl_msg_id = ntohs (VL_API_##T + sm->msg_id_base); \ - mp->client_index = vam->my_client_index; \ -} while(0); - -#define M2(T,t,n) \ -do { \ - vam->result_ready = 0; \ - mp = vl_msg_api_alloc(sizeof(*mp)+(n)); \ - memset (mp, 0, sizeof (*mp)); \ - mp->_vl_msg_id = ntohs (VL_API_##T + sm->msg_id_base); \ - mp->client_index = vam->my_client_index; \ -} while(0); - -/* S: send a message */ -#define S (vl_msg_api_send_shmem (vam->vl_input_queue, (u8 *)&mp)) - -/* W: wait for results, with timeout */ -#define W \ -do { \ - timeout = vat_time_now (vam) + 1.0; \ - \ - while (vat_time_now (vam) < timeout) { \ - if (vam->result_ready == 1) { \ - return (vam->retval); \ - } \ - } \ - return -99; \ -} while(0); - - -static int api_pot_profile_add (vat_main_t *vam) -{ -#define MAX_BITS 64 - pot_test_main_t * sm = &pot_test_main; - unformat_input_t *input = vam->input; - vl_api_pot_profile_add_t *mp; - u8 *name = NULL; - u64 prime = 0; - u64 secret_share = 0; - u64 secret_key = 0; - u32 bits = MAX_BITS; - u64 lpc = 0, poly2 = 0; - f64 timeout; - u8 id = 0; - int rv = 0; - - while (unformat_check_input(input) != UNFORMAT_END_OF_INPUT) - { - if (unformat(input, "name %s", &name)) - ; - else if(unformat(input, "id %d", &id)) - ; - else if (unformat(input, "validator-key 0x%Lx", &secret_key)) - ; - else if (unformat(input, "prime-number 0x%Lx", &prime)) - ; - else if (unformat(input, "secret-share 0x%Lx", &secret_share)) - ; - else if (unformat(input, "polynomial-public 0x%Lx", &poly2)) - ; - else if (unformat(input, "lpc 0x%Lx", &lpc)) - ; - else if (unformat(input, "bits-in-random %u", &bits)) - { - if (bits > MAX_BITS) - bits = MAX_BITS; - } - else - break; - } - - if (!name) - { - errmsg ("name required\n"); - rv = -99; - goto OUT; - } - - M2(POT_PROFILE_ADD, pot_profile_add, vec_len(name)); - - mp->list_name_len = vec_len(name); - clib_memcpy(mp->list_name, name, mp->list_name_len); - mp->secret_share = clib_host_to_net_u64(secret_share); - mp->polynomial_public = clib_host_to_net_u64(poly2); - mp->lpc = clib_host_to_net_u64(lpc); - mp->prime = clib_host_to_net_u64(prime); - if (secret_key != 0) - { - mp->secret_key = clib_host_to_net_u64(secret_key); - mp->validator = 1; - } - else - { - mp->validator = 0; - } - mp->id = id; - mp->max_bits = bits; - - S; W; - -OUT: - vec_free(name); - return(rv); -} - -static int api_pot_profile_activate (vat_main_t *vam) -{ -#define MAX_BITS 64 - pot_test_main_t * sm = &pot_test_main; - unformat_input_t *input = vam->input; - vl_api_pot_profile_activate_t *mp; - u8 *name = NULL; - u8 id = 0; - int rv = 0; - f64 timeout; - - while (unformat_check_input(input) != UNFORMAT_END_OF_INPUT) - { - if (unformat(input, "name %s", &name)) - ; - else if(unformat(input, "id %d", &id)) - ; - else - break; - } - - if (!name) - { - errmsg ("name required\n"); - rv = -99; - goto OUT; - } - - M2(POT_PROFILE_ACTIVATE, pot_profile_activate, vec_len(name)); - - mp->list_name_len = vec_len(name); - clib_memcpy(mp->list_name, name, mp->list_name_len); - mp->id = id; - - S; W; - -OUT: - vec_free(name); - return(rv); -} - - -static int api_pot_profile_del (vat_main_t *vam) -{ - pot_test_main_t * sm = &pot_test_main; - vl_api_pot_profile_del_t *mp; - f64 timeout; - - M(POT_PROFILE_DEL, pot_profile_del); - mp->list_name_len = 0; - S; W; - return 0; -} - -/* - * List of messages that the api test plugin sends, - * and that the data plane plugin processes - */ -#define foreach_vpe_api_msg \ -_(pot_profile_add, "name id [0-1] " \ - "prime-number <0xu64> bits-in-random [0-64] " \ - "secret-share <0xu64> lpc <0xu64> polynomial-public <0xu64> " \ - "[validator-key <0xu64>] [validity <0xu64>]") \ -_(pot_profile_activate, "name id [0-1] ") \ -_(pot_profile_del, "[id ]") \ - - -void vat_api_hookup (vat_main_t *vam) -{ - pot_test_main_t * sm = &pot_test_main; - /* Hook up handlers for replies from the data plane plug-in */ -#define _(N,n) \ - vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base), \ - #n, \ - vl_api_##n##_t_handler, \ - vl_noop_handler, \ - vl_api_##n##_t_endian, \ - vl_api_##n##_t_print, \ - sizeof(vl_api_##n##_t), 1); - foreach_vpe_api_reply_msg; -#undef _ - - /* API messages we can send */ -#define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n); - foreach_vpe_api_msg; -#undef _ - - /* Help strings */ -#define _(n,h) hash_set_mem (vam->help_by_name, #n, h); - foreach_vpe_api_msg; -#undef _ -} - -clib_error_t * vat_plugin_register (vat_main_t *vam) -{ - pot_test_main_t * sm = &pot_test_main; - u8 * name; - - sm->vat_main = vam; - - name = format (0, "pot_%08x%c", api_version, 0); - sm->msg_id_base = vl_client_get_first_plugin_msg_id ((char *) name); - - if (sm->msg_id_base != (u16) ~0) - vat_api_hookup (vam); - - vec_free(name); - - return 0; -} diff --git a/plugins/plugins/ioam/lib-pot/pot_util.c b/plugins/plugins/ioam/lib-pot/pot_util.c deleted file mode 100644 index 0309cbec..00000000 --- a/plugins/plugins/ioam/lib-pot/pot_util.c +++ /dev/null @@ -1,446 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * 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 -#include -#include -#include -#include -#include "math64.h" -#include "pot_util.h" - -pot_main_t pot_main; - -static void pot_profile_cleanup(pot_profile *profile); - -static void pot_main_profiles_reset (void) -{ - pot_main_t *sm = &pot_main; - int i = 0; - - for (i = 0; i < MAX_POT_PROFILES; i++) - { - pot_profile_cleanup(&(sm->profile_list[i])); - } - sm->active_profile_id = 0; - if (sm->profile_list_name) - vec_free(sm->profile_list_name); - sm->profile_list_name = NULL; -} - -int pot_util_init (void) -{ - pot_main_profiles_reset(); - - return(0); -} - -static void pot_profile_init(pot_profile * new, u8 id) -{ - if (new) - { - memset(new, 0, sizeof(pot_profile)); - new->id = id; - } -} - -pot_profile *pot_profile_find(u8 id) -{ - pot_main_t *sm = &pot_main; - - if (id >= 0 && id < MAX_POT_PROFILES) - { - return (&(sm->profile_list[id])); - } - return (NULL); -} -static int pot_profile_name_equal (u8 *name0, u8 *name1) -{ - int len0, len1; - - len0 = vec_len (name0); - len1 = vec_len (name1); - if (len0 != len1) - return(0); - return (0==strncmp ((char *) name0, (char *)name1, len0)); -} - -int pot_profile_list_is_enabled (u8 *name) -{ - pot_main_t *sm = &pot_main; - return (pot_profile_name_equal(sm->profile_list_name, name)); -} - -void pot_profile_list_init(u8 * profile_list_name) -{ - pot_main_t *sm = &pot_main; - int i = 0; - - /* If it is the same profile list skip reset */ - if (pot_profile_name_equal(sm->profile_list_name, profile_list_name)) - { - return; - } - - pot_main_profiles_reset(); - if (vec_len(profile_list_name)) - sm->profile_list_name = (u8 *)vec_dup(profile_list_name); - else - sm->profile_list_name = 0; - sm->active_profile_id = 0; - - for (i = 0; i < MAX_POT_PROFILES; i++) - { - pot_profile_init(&(sm->profile_list[i]), i); - } -} - -static void pot_profile_cleanup(pot_profile * profile) -{ - u16 id = profile->id; - - memset(profile, 0, sizeof(pot_profile)); - profile->id = id; /* Restore id alone */ -} - -int pot_profile_create(pot_profile * profile, u64 prime, - u64 poly2, u64 lpc, u64 secret_share) -{ - if (profile && !profile->in_use) - { - pot_profile_cleanup(profile); - profile->prime = prime; - profile->primeinv = 1.0 / prime; - profile->lpc = lpc; - profile->poly_pre_eval = poly2; - profile->secret_share = secret_share; - profile->total_pkts_using_this_profile = 0; - profile->valid = 1; - return(0); - } - - return(-1); -} - -int pot_set_validator(pot_profile * profile, u64 key) -{ - if (profile && !profile->in_use) - { - profile->validator = 1; - profile->secret_key = key; - return(0); - } - return(-1); -} - -always_inline u64 pot_update_cumulative_inline(u64 cumulative, u64 random, - u64 secret_share, u64 prime, u64 lpc, u64 pre_split, double prime_inv) -{ - u64 share_random = 0; - u64 cumulative_new = 0; - - /* - * calculate split share for random - */ - share_random = add64_mod(pre_split, random, prime, prime_inv); - - /* - * lpc * (share_secret + share_random) - */ - share_random = add64_mod(share_random, secret_share, prime, prime_inv); - share_random = mul64_mod(share_random, lpc, prime, prime_inv); - - cumulative_new = add64_mod(cumulative, share_random, prime, prime_inv); - - return (cumulative_new); -} - -u64 pot_update_cumulative(pot_profile * profile, u64 cumulative, u64 random) -{ - if (profile && profile->valid != 0) - { - return (pot_update_cumulative_inline(cumulative, random, profile->secret_share, - profile->prime, profile->lpc, profile->poly_pre_eval, - profile->primeinv)); - } - return (0); -} - -always_inline u8 pot_validate_inline(u64 secret, u64 prime, double prime_inv, - u64 cumulative, u64 random) -{ - if (cumulative == (random + secret)) - { - return (1); - } - else if (cumulative == add64_mod(random, secret, prime, prime_inv)) - { - return (1); - } - return (0); -} - -/* - * return True if the cumulative matches secret from a profile - */ -u8 pot_validate(pot_profile * profile, u64 cumulative, u64 random) -{ - if (profile && profile->validator) - { - return (pot_validate_inline(profile->secret_key, profile->prime, - profile->primeinv, cumulative, random)); - } - return (0); -} - -/* - * Utility function to get random number per pack - */ -u64 pot_generate_random(pot_profile * profile) -{ - u64 random = 0; - int32_t second_half; - static u32 seed = 0; - - if (PREDICT_FALSE(!seed)) - seed = random_default_seed(); - - /* - * Upper 4 bytes seconds - */ - random = (u64) time(NULL); - - random &= 0xffffffff; - random = random << 32; - /* - * Lower 4 bytes random number - */ - second_half = random_u32(&seed); - - random |= second_half; - - if (PREDICT_TRUE(profile != NULL)) - { - random &= profile->bit_mask; - } - return (random); -} - -int pot_profile_set_bit_mask(pot_profile * profile, u16 bits) -{ - int sizeInBits; - - if (profile && !profile->in_use) - { - sizeInBits = sizeof(profile->bit_mask) * 8; - profile->bit_mask = - (bits >= - sizeInBits ? (u64) - 1 : (u64) ((u64) 1 << (u64) bits) - 1); - return(0); - } - return(-1); -} - -clib_error_t *clear_pot_profile_command_fn(vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) -{ - - pot_main_profiles_reset(); - - return 0; -} - -void clear_pot_profiles() -{ - clear_pot_profile_command_fn(0, 0, 0); -} - -VLIB_CLI_COMMAND(clear_pot_profile_command) = -{ -.path = "clear pot profile", -.short_help = "clear pot profile [|all]", -.function = clear_pot_profile_command_fn, -}; - -static clib_error_t *set_pot_profile_command_fn(vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) -{ - u64 prime; - u64 secret_share; - u64 secret_key; - u8 validator = 0; - u32 profile_id; - u32 bits; - u64 lpc = 0, poly2 = 0; - pot_profile *profile = NULL; - u8 *profile_list_name = NULL; - - bits = MAX_BITS; - - while (unformat_check_input(input) != UNFORMAT_END_OF_INPUT) - { - if (unformat(input, "name %s", - &profile_list_name)); - else if (unformat(input, "id %d", &profile_id)) - ; - else if (unformat(input, "validate-key 0x%Lx", &secret_key)) - validator = 1; - else if (unformat(input, "prime-number 0x%Lx", &prime)) - ; - else if (unformat(input, "secret_share 0x%Lx", &secret_share)) - ; - else if (unformat(input, "polynomial2 0x%Lx", &poly2)) - ; - else if (unformat(input, "lpc 0x%Lx", &lpc)) - ; - else if (unformat(input, "bits-in-random %d", &bits)) - { - if (bits > MAX_BITS) - bits = MAX_BITS; - } - else - return clib_error_return(0, "unknown input `%U'", - format_unformat_error, input); - } - if (profile_list_name == 0) - { - return clib_error_return(0, "Name cannot be null"); - } - pot_profile_list_init(profile_list_name); - profile = pot_profile_find(profile_id); - - if (profile) - { - pot_profile_create(profile, prime, poly2, lpc, secret_share); - if (validator) - pot_set_validator(profile, secret_key); - pot_profile_set_bit_mask(profile, bits); - } - vec_free(profile_list_name); - return 0; -} - -VLIB_CLI_COMMAND(set_pot_profile_command) = -{ -.path = "set pot profile", -.short_help = "set pot profile name id [0-1] [validator-key 0xu64] \ - prime-number 0xu64 secret_share 0xu64 lpc 0xu64 \ - polynomial2 0xu64 bits-in-random [0-64] ", -.function = set_pot_profile_command_fn, -}; - -static clib_error_t *set_pot_profile_activate_command_fn(vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) -{ - pot_main_t *sm = &pot_main; - u8 *profile_list_name = NULL; - u32 id = 0; - clib_error_t *result = NULL; - - while (unformat_check_input(input) != UNFORMAT_END_OF_INPUT) - { - if (unformat(input, "name %s", - &profile_list_name)); - else if (unformat(input, "id %d", &id)) - ; - else - return clib_error_return(0, "unknown input `%U'", - format_unformat_error, input); - } - if (profile_list_name == 0) - { - return clib_error_return(0, "Name cannot be null"); - } - - if (!pot_profile_list_is_enabled(profile_list_name)) { - result = clib_error_return(0, "%s list is not enabled, profile in use %s", - profile_list_name, sm->profile_list_name); - } else if (0 != pot_profile_set_active((u8)id)) { - result = clib_error_return(0, "Profile %d not defined in %s", - id, sm->profile_list_name); - } - vec_free(profile_list_name); - return result; -} - -VLIB_CLI_COMMAND(set_pot_profile_activate_command) = -{ -.path = "set pot profile-active", -.short_help = "set pot profile-active name id [0-1]", -.function = set_pot_profile_activate_command_fn, -}; - -static clib_error_t *show_pot_profile_command_fn(vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) -{ - pot_main_t *sm = &pot_main; - pot_profile *p = NULL; - u16 i; - u8 *s = 0; - - if (vec_len(sm->profile_list_name) == 0) - { - s = format(s, "POT Profiles not configured\n"); - vlib_cli_output(vm, "%v", s); - return 0; - } - s = format(s, "Profile list in use : %s\n",sm->profile_list_name); - for (i = 0; i < MAX_POT_PROFILES; i++) - { - p = pot_profile_find(i); - if (p->valid == 0) - continue; - s = format(s, "POT Profile at index: %d\n", i); - s = format(s, " Id : %d\n", p->id); - s = format(s, " Validator : %s (%d)\n", - (p->validator) ? "True" : "False", p->validator); - if (p->validator == 1) - s = format(s, " Secret key : 0x%Lx (%Ld)\n", - p->secret_key, p->secret_key); - s = format(s, " Secret share : 0x%Lx (%Ld)\n", - p->secret_share, p->secret_share); - s = format(s, " Prime number : 0x%Lx (%Ld)\n", - p->prime, p->prime); - s = format(s, "2nd polynomial(eval) : 0x%Lx (%Ld)\n", - p->poly_pre_eval, p->poly_pre_eval); - s = format(s, " LPC : 0x%Lx (%Ld)\n", p->lpc, p->lpc); - - s = format(s, " Bit mask : 0x%Lx (%Ld)\n", - p->bit_mask, p->bit_mask); - } - - p = pot_profile_find(sm->active_profile_id); - - if (p && p->valid && p->in_use) { - s = format(s, "\nProfile index in use: %d\n", sm->active_profile_id); - s = format(s, "Pkts passed : 0x%Lx (%Ld)\n", - p->total_pkts_using_this_profile, - p->total_pkts_using_this_profile); - if (pot_is_decap(p)) - s = format(s, " This is Decap node. \n"); - } else { - s = format(s, "\nProfile index in use: None\n"); - } - vlib_cli_output(vm, "%v", s); - vec_free(s); - - return 0; -} - -VLIB_CLI_COMMAND(show_pot_profile_command) = -{ -.path = "show pot profile", -.short_help = "show pot profile", -.function = show_pot_profile_command_fn, -}; diff --git a/plugins/plugins/ioam/lib-pot/pot_util.h b/plugins/plugins/ioam/lib-pot/pot_util.h deleted file mode 100644 index 9df31fae..00000000 --- a/plugins/plugins/ioam/lib-pot/pot_util.h +++ /dev/null @@ -1,195 +0,0 @@ -/* - * pot_util.h -- Proof Of Transit Utility Header - * - * Copyright (c) 2016 Cisco and/or its affiliates. - * 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_vnet_pot_util_h -#define include_vnet_pot_util_h - -#include -#define debug_ioam debug_ioam_fn -/* Dont change this size 256. This is there across multiple components */ -#define PATH_NAME_SIZE 256 - -/* Ring size. this should be same as the one in ODL. Do not change this - without change in ODL. */ -#define MAX_POT_PROFILES 2 - -/** - * Usage: - * - * On any node that participates in Proof of Transit: - * - * Step 1: Initialize this library by calling pot_init() - * Step 2: Setup a proof of transit profile that contains all the parameters needed to compute cumulative: - * Call these functions: - * pot_profile_find - * pot_profile_create - * pot_profile_set_bit_mask - To setup how large we want the numbers used in the computation and random number <= 64 bits - * Step 2a: For validator do this: - * pot_set_validator - * Step 2b: On initial node enable the profile to be used: - * pot_profile_set_active / pot_profile_get_active will return the profile - * Step 3a: At the initial node to generate Random number that will be read by all other nodes: - * pot_generate_random - * Step 3b: At all nodes including initial and verifier call this to compute cumulative: - * pot_update_cumulative - * Step 4: At the verifier: - * pot_validate - * - */ - -typedef struct pot_profile_ -{ - u8 id : 1; - u8 valid : 1; - u8 in_use : 1; - u64 random; - u8 validator; - u64 secret_key; - u64 secret_share; - u64 prime; - u64 lpc; - u64 poly_pre_eval; - u64 bit_mask; - u64 limit; - double primeinv; - u64 total_pkts_using_this_profile; -} pot_profile; - -typedef struct { - /* Name of the default profile list in use*/ - u8 *profile_list_name; - pot_profile profile_list[MAX_POT_PROFILES]; - /* number of profiles in the list */ - u8 active_profile_id : 1; - - /* API message ID base */ - u16 msg_id_base; - - /* convenience */ - vlib_main_t * vlib_main; - vnet_main_t * vnet_main; -} pot_main_t; - -extern pot_main_t pot_main; - -/* - * Initialize proof of transit - */ -int pot_util_init(void); -void pot_profile_list_init(u8 * name); - - -/* - * Find a pot profile by ID - */ -pot_profile *pot_profile_find(u8 id); - -static inline u16 pot_profile_get_id(pot_profile * profile) -{ - if (profile) - { - return (profile->id); - } - return (0); -} - -/* setup and clean up profile */ -int pot_profile_create(pot_profile * profile, u64 prime, - u64 poly2, u64 lpc, u64 secret_share); -/* - * Setup profile as a validator - */ -int pot_set_validator(pot_profile * profile, u64 key); - -/* - * Setup max bits to be used for random number generation - */ -#define MAX_BITS 64 -int pot_profile_set_bit_mask(pot_profile * profile, u16 bits); - -/* - * Given a random and cumulative compute the new cumulative for a given profile - */ -u64 pot_update_cumulative(pot_profile * profile, u64 cumulative, u64 random); - -/* - * return True if the cumulative matches secret from a profile - */ -u8 pot_validate(pot_profile * profile, u64 cumulative, u64 random); - -/* - * Utility function to get random number per pack - */ -u64 pot_generate_random(pot_profile * profile); - - -extern void clear_pot_profiles(); -extern int pot_profile_list_is_enabled(u8 *name); - -static inline u8 pot_is_decap(pot_profile * p) -{ - return (p->validator == 1); -} - -static inline int pot_profile_set_active (u8 id) -{ - pot_main_t *sm = &pot_main; - pot_profile *profile = NULL; - pot_profile *current_active_prof = NULL; - - current_active_prof = pot_profile_find(sm->active_profile_id); - profile = pot_profile_find(id); - if (profile && profile->valid) { - sm->active_profile_id = id; - current_active_prof->in_use = 0; - profile->in_use = 1; - return(0); - } - return(-1); -} -static inline u8 pot_profile_get_active_id (void) -{ - pot_main_t *sm = &pot_main; - return (sm->active_profile_id); -} - -static inline pot_profile * pot_profile_get_active (void) -{ - pot_main_t *sm = &pot_main; - pot_profile *profile = NULL; - profile = pot_profile_find(sm->active_profile_id); - if (profile && profile->in_use) - return(profile); - return (NULL); -} - -static inline void pot_profile_reset_usage_stats (pot_profile *pow) -{ - if (pow) { - pow->total_pkts_using_this_profile = 0; - } -} - -static inline void pot_profile_incr_usage_stats (pot_profile *pow) -{ - if (pow) { - pow->total_pkts_using_this_profile++; - } -} - - -#endif diff --git a/plugins/plugins/sixrd/ip4_sixrd.c b/plugins/plugins/sixrd/ip4_sixrd.c deleted file mode 100644 index 2fb8015d..00000000 --- a/plugins/plugins/sixrd/ip4_sixrd.c +++ /dev/null @@ -1,127 +0,0 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2009-2014 Cisco and/or its affiliates. - * 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 "sixrd.h" - -static vlib_node_registration_t ip4_sixrd_node; - -typedef enum { - IP4_SIXRD_NEXT_IP6_LOOKUP, - IP4_SIXRD_NEXT_DROP, - IP4_SIXRD_N_NEXT, -} ip4_sixrd_next_t; - -/* - * ip4_sixrd_sec_check - */ -static_always_inline void -ip4_sixrd_sec_check (sixrd_domain_t *d, ip4_address_t sa4, ip6_address_t sa6, u8 *error) -{ - u32 a = sixrd_get_addr(d, sa6.as_u64[0]); - clib_warning("Security check: %U %U", format_ip4_address, &a, format_ip4_address, &sa4); - if (PREDICT_FALSE(sixrd_get_addr(d, sa6.as_u64[0]) != sa4.as_u32)) - *error = SIXRD_ERROR_SEC_CHECK; -} - -/* - * ip4_sixrd - */ -static uword -ip4_sixrd (vlib_main_t *vm, - vlib_node_runtime_t *node, - vlib_frame_t *frame) -{ - u32 n_left_from, *from, next_index, *to_next, n_left_to_next; - vlib_node_runtime_t *error_node = vlib_node_get_runtime(vm, ip4_sixrd_node.index); - u32 decap = 0; - - from = vlib_frame_vector_args(frame); - n_left_from = frame->n_vectors; - next_index = node->cached_next_index; - while (n_left_from > 0) { - vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next); - - /* Single loop */ - while (n_left_from > 0 && n_left_to_next > 0) { - u32 pi0; - vlib_buffer_t *p0; - u8 error0 = SIXRD_ERROR_NONE; - sixrd_domain_t *d0 = 0; - ip4_header_t *ip40; - ip6_header_t *ip60; - u32 sixrd_domain_index0 = ~0; - u32 next0; - - pi0 = to_next[0] = from[0]; - from += 1; - n_left_from -= 1; - to_next +=1; - n_left_to_next -= 1; - - p0 = vlib_get_buffer(vm, pi0); - ip40 = vlib_buffer_get_current(p0); - - /* Throw away anything that isn't IP in IP. */ - if (PREDICT_TRUE(ip40->protocol == IP_PROTOCOL_IPV6 && clib_net_to_host_u16(ip40->length) >= 60)) { - vlib_buffer_advance(p0, sizeof(ip4_header_t)); - ip60 = vlib_buffer_get_current(p0); - d0 = ip4_sixrd_get_domain(vnet_buffer(p0)->ip.adj_index[VLIB_TX], (ip6_address_t *)&ip60->src_address, - &sixrd_domain_index0, &error0); - } else { - error0 = SIXRD_ERROR_BAD_PROTOCOL; - } - if (d0) { - /* SIXRD inbound security check */ - ip4_sixrd_sec_check(d0, ip40->src_address, ip60->src_address, &error0); - } - - next0 = error0 == SIXRD_ERROR_NONE ? IP4_SIXRD_NEXT_IP6_LOOKUP : IP4_SIXRD_NEXT_DROP; - - if (PREDICT_FALSE(p0->flags & VLIB_BUFFER_IS_TRACED)) { - sixrd_trace_t *tr = vlib_add_trace(vm, node, p0, sizeof(*tr)); - tr->sixrd_domain_index = sixrd_domain_index0; - } - - p0->error = error_node->errors[error0]; - if (PREDICT_TRUE(error0 == SIXRD_ERROR_NONE)) decap++; - vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, pi0, next0); - - } - vlib_put_next_frame(vm, node, next_index, n_left_to_next); - } - vlib_node_increment_counter(vm, ip4_sixrd_node.index, SIXRD_ERROR_DECAPSULATED, decap); - - return frame->n_vectors; -} - -static char *sixrd_error_strings[] = { -#define _(sym,string) string, - foreach_sixrd_error -#undef _ -}; - -VLIB_REGISTER_NODE(ip4_sixrd_node,static) = { - .function = ip4_sixrd, - .name = "ip4-sixrd", - .vector_size = sizeof(u32), - .format_trace = format_sixrd_trace, - .n_errors = SIXRD_N_ERROR, - .error_strings = sixrd_error_strings, - .n_next_nodes = IP4_SIXRD_N_NEXT, - .next_nodes = { - [IP4_SIXRD_NEXT_IP6_LOOKUP] = "ip6-lookup", - [IP4_SIXRD_NEXT_DROP] = "error-drop", - }, -}; diff --git a/plugins/plugins/sixrd/ip6_sixrd.c b/plugins/plugins/sixrd/ip6_sixrd.c deleted file mode 100644 index 36f3fab3..00000000 --- a/plugins/plugins/sixrd/ip6_sixrd.c +++ /dev/null @@ -1,129 +0,0 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2009-2014 Cisco and/or its affiliates. - * 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. - *--------------------------------------------------------------------------- - */ -/* - * Defines used for testing various optimisation schemes - */ -#define SIXRD_ENCAP_DUAL 0 - -#include "sixrd.h" - -static vlib_node_registration_t ip6_sixrd_node; - -typedef enum { - IP6_SIXRD_NEXT_IP4_LOOKUP, - IP6_SIXRD_NEXT_DROP, - IP6_SIXRD_N_NEXT, -} ip6_sixrd_next_t; - -/* - * ip6_sixrd - */ -static uword -ip6_sixrd (vlib_main_t *vm, - vlib_node_runtime_t *node, - vlib_frame_t *frame) -{ - u32 n_left_from, *from, next_index, *to_next, n_left_to_next; - vlib_node_runtime_t *error_node = vlib_node_get_runtime(vm, ip6_sixrd_node.index); - u32 encap = 0; - from = vlib_frame_vector_args(frame); - n_left_from = frame->n_vectors; - next_index = node->cached_next_index; - - while (n_left_from > 0) { - vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next); - - while (n_left_from > 0 && n_left_to_next > 0) { - u32 pi0; - vlib_buffer_t *p0; - sixrd_domain_t *d0; - u8 error0 = SIXRD_ERROR_NONE; - ip6_header_t *ip60; - ip4_header_t *ip4h0; - u32 next0 = IP6_SIXRD_NEXT_IP4_LOOKUP; - u32 sixrd_domain_index0 = ~0; - - pi0 = to_next[0] = from[0]; - from += 1; - n_left_from -= 1; - to_next +=1; - n_left_to_next -= 1; - - p0 = vlib_get_buffer(vm, pi0); - ip60 = vlib_buffer_get_current(p0); - // p0->current_length = clib_net_to_host_u16(ip40->length); - d0 = ip6_sixrd_get_domain(vnet_buffer(p0)->ip.adj_index[VLIB_TX], &sixrd_domain_index0); - ASSERT(d0); - - /* SIXRD calc */ - u64 dal60 = clib_net_to_host_u64(ip60->dst_address.as_u64[0]); - u32 da40 = sixrd_get_addr(d0, dal60); - u16 len = clib_net_to_host_u16(ip60->payload_length) + 60; - if (da40 == 0) error0 = SIXRD_ERROR_UNKNOWN; - - /* construct ipv4 header */ - vlib_buffer_advance(p0, - (sizeof(ip4_header_t))); - ip4h0 = vlib_buffer_get_current(p0); - vnet_buffer(p0)->sw_if_index[VLIB_TX] = (u32)~0; - ip4h0->ip_version_and_header_length = 0x45; - ip4h0->tos = 0; - ip4h0->length = clib_host_to_net_u16(len); - ip4h0->fragment_id = 0; - ip4h0->flags_and_fragment_offset = 0; - ip4h0->ttl = 0x40; - ip4h0->protocol = IP_PROTOCOL_IPV6; - ip4h0->src_address = d0->ip4_src; - ip4h0->dst_address.as_u32 = clib_host_to_net_u32(da40); - ip4h0->checksum = ip4_header_checksum(ip4h0); - - next0 = error0 == SIXRD_ERROR_NONE ? IP6_SIXRD_NEXT_IP4_LOOKUP : IP6_SIXRD_NEXT_DROP; - - if (PREDICT_FALSE(p0->flags & VLIB_BUFFER_IS_TRACED)) { - sixrd_trace_t *tr = vlib_add_trace(vm, node, p0, sizeof(*tr)); - tr->sixrd_domain_index = sixrd_domain_index0; - } - - p0->error = error_node->errors[error0]; - if (PREDICT_TRUE(error0 == SIXRD_ERROR_NONE)) encap++; - - vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, pi0, next0); - } - vlib_put_next_frame(vm, node, next_index, n_left_to_next); - } - vlib_node_increment_counter(vm, ip6_sixrd_node.index, SIXRD_ERROR_ENCAPSULATED, encap); - - return frame->n_vectors; -} - -static char *sixrd_error_strings[] = { -#define _(sym,string) string, - foreach_sixrd_error -#undef _ -}; - -VLIB_REGISTER_NODE(ip6_sixrd_node,static) = { - .function = ip6_sixrd, - .name = "ip6-sixrd", - .vector_size = sizeof(u32), - .format_trace = format_sixrd_trace, - .n_errors = SIXRD_N_ERROR, - .error_strings = sixrd_error_strings, - .n_next_nodes = IP6_SIXRD_N_NEXT, - .next_nodes = { - [IP6_SIXRD_NEXT_IP4_LOOKUP] = "ip4-lookup", - [IP6_SIXRD_NEXT_DROP] = "error-drop", - }, -}; diff --git a/plugins/plugins/sixrd/sixrd.c b/plugins/plugins/sixrd/sixrd.c deleted file mode 100644 index 8ebdb32b..00000000 --- a/plugins/plugins/sixrd/sixrd.c +++ /dev/null @@ -1,379 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * 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 "sixrd.h" -#include - -/* - * This code supports the following sixrd modes: - * - * 32 EA bits (Complete IPv4 address is embedded): - * ea_bits_len = 32 - * IPv4 suffix is embedded: - * ea_bits_len = < 32 - * No embedded address bits (1:1 mode): - * ea_bits_len = 0 - */ - -int -sixrd_create_domain (ip6_address_t *ip6_prefix, - u8 ip6_prefix_len, - ip4_address_t *ip4_prefix, - u8 ip4_prefix_len, - ip4_address_t *ip4_src, - u32 *sixrd_domain_index, - u16 mtu) -{ - sixrd_main_t *mm = &sixrd_main; - ip4_main_t *im4 = &ip4_main; - ip6_main_t *im6 = &ip6_main; - sixrd_domain_t *d; - ip_adjacency_t adj; - ip4_add_del_route_args_t args4; - ip6_add_del_route_args_t args6; - u32 *p; - - /* Get domain index */ - pool_get_aligned(mm->domains, d, CLIB_CACHE_LINE_BYTES); - memset(d, 0, sizeof (*d)); - *sixrd_domain_index = d - mm->domains; - - /* Init domain struct */ - d->ip4_prefix.as_u32 = ip4_prefix->as_u32; - d->ip4_prefix_len = ip4_prefix_len; - d->ip6_prefix = *ip6_prefix; - d->ip6_prefix_len = ip6_prefix_len; - d->ip4_src = *ip4_src; - d->mtu = mtu; - - if (ip4_prefix_len < 32) - d->shift = 64 - ip6_prefix_len + (32 - ip4_prefix_len); - - /* Init IP adjacency */ - memset(&adj, 0, sizeof(adj)); - adj.explicit_fib_index = ~0; - p = (u32 *)&adj.rewrite_data[0]; - *p = (u32) (*sixrd_domain_index); - - /* Create ip6 adjacency */ - memset(&args6, 0, sizeof(args6)); - args6.table_index_or_table_id = 0; - args6.flags = IP6_ROUTE_FLAG_ADD; - args6.dst_address.as_u64[0] = ip6_prefix->as_u64[0]; - args6.dst_address.as_u64[1] = ip6_prefix->as_u64[1]; - args6.dst_address_length = ip6_prefix_len; - args6.adj_index = ~0; - args6.add_adj = &adj; - args6.n_add_adj = 1; - adj.lookup_next_index = mm->ip6_lookup_next_index; - ip6_add_del_route(im6, &args6); - - /* Multiple SIXRD domains may share same source IPv4 TEP */ - uword *q = ip4_get_route(im4, 0, 0, (u8 *)ip4_src, 32); - if (q) { - u32 ai = q[0]; - ip_lookup_main_t *lm4 = &ip4_main.lookup_main; - ip_adjacency_t *adj4 = ip_get_adjacency(lm4, ai); - if (adj4->lookup_next_index != mm->ip4_lookup_next_index) { - clib_warning("BR source address already assigned: %U", format_ip4_address, ip4_src); - pool_put(mm->domains, d); - return -1; - } - /* Shared source */ - p = (u32 *)&adj4->rewrite_data[0]; - p[0] = ~0; - - /* Add refcount, so we don't accidentially delete the route underneath someone */ - p[1]++; - } else { - /* Create ip4 adjacency. */ - memset(&args4, 0, sizeof(args4)); - args4.table_index_or_table_id = 0; - args4.flags = IP4_ROUTE_FLAG_ADD; - args4.dst_address.as_u32 = ip4_src->as_u32; - args4.dst_address_length = 32; - args4.adj_index = ~0; - args4.add_adj = &adj; - args4.n_add_adj = 1; - adj.lookup_next_index = mm->ip4_lookup_next_index; - ip4_add_del_route(im4, &args4); - } - - return 0; -} - -/* - * sixrd_delete_domain - */ -int -sixrd_delete_domain (u32 sixrd_domain_index) -{ - sixrd_main_t *mm = &sixrd_main; - ip4_main_t *im4 = &ip4_main; - ip6_main_t *im6 = &ip6_main; - sixrd_domain_t *d; - ip_adjacency_t adj; - ip4_add_del_route_args_t args4; - ip6_add_del_route_args_t args6; - - if (pool_is_free_index(mm->domains, sixrd_domain_index)) { - clib_warning("SIXRD domain delete: domain does not exist: %d", sixrd_domain_index); - return -1; - } - - d = pool_elt_at_index(mm->domains, sixrd_domain_index); - - memset(&adj, 0, sizeof(adj)); - adj.explicit_fib_index = ~0; - - /* Delete ip6 adjacency */ - memset(&args6, 0, sizeof (args6)); - args6.table_index_or_table_id = 0; - args6.flags = IP6_ROUTE_FLAG_DEL; - args6.dst_address.as_u64[0] = d->ip6_prefix.as_u64[0]; - args6.dst_address.as_u64[1] = d->ip6_prefix.as_u64[1]; - args6.dst_address_length = d->ip6_prefix_len; - args6.adj_index = 0; - args6.add_adj = &adj; - args6.n_add_adj = 0; - ip6_add_del_route(im6, &args6); - - /* Delete ip4 adjacency */ - uword *q = ip4_get_route(im4, 0, 0, (u8 *)&d->ip4_src, 32); - if (q) { - u32 ai = q[0]; - ip_lookup_main_t *lm4 = &ip4_main.lookup_main; - ip_adjacency_t *adj4 = ip_get_adjacency(lm4, ai); - - u32 *p = (u32 *)&adj4->rewrite_data[0]; - /* Delete route when no other domains use this source */ - if (p[1] == 0) { - memset(&args4, 0, sizeof(args4)); - args4.table_index_or_table_id = 0; - args4.flags = IP4_ROUTE_FLAG_DEL; - args4.dst_address.as_u32 = d->ip4_prefix.as_u32; - args4.dst_address_length = d->ip4_prefix_len; - args4.adj_index = 0; - args4.add_adj = &adj; - args4.n_add_adj = 0; - ip4_add_del_route(im4, &args4); - } - p[1]--; - } - - pool_put(mm->domains, d); - - return 0; -} - -static clib_error_t * -sixrd_add_domain_command_fn (vlib_main_t *vm, - unformat_input_t *input, - vlib_cli_command_t *cmd) -{ - unformat_input_t _line_input, *line_input = &_line_input; - ip4_address_t ip4_prefix; - ip6_address_t ip6_prefix; - ip4_address_t ip4_src; - u32 ip6_prefix_len, ip4_prefix_len, sixrd_domain_index; - u32 num_m_args = 0; - /* Optional arguments */ - u32 mtu = 0; - - /* Get a line of input. */ - if (!unformat_user(input, unformat_line_input, line_input)) - return 0; - while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { - if (unformat(line_input, "ip6-pfx %U/%d", unformat_ip6_address, &ip6_prefix, &ip6_prefix_len)) - num_m_args++; - else if (unformat(line_input, "ip4-pfx %U/%d", unformat_ip4_address, &ip4_prefix, &ip4_prefix_len)) - num_m_args++; - else if (unformat(line_input, "ip4-src %U", unformat_ip4_address, &ip4_src)) - num_m_args++; - else if (unformat(line_input, "mtu %d", &mtu)) - num_m_args++; - else - return clib_error_return(0, "unknown input `%U'", - format_unformat_error, input); - } - unformat_free(line_input); - - if (num_m_args < 3) - return clib_error_return(0, "mandatory argument(s) missing"); - - sixrd_create_domain(&ip6_prefix, ip6_prefix_len, &ip4_prefix, ip4_prefix_len, - &ip4_src, &sixrd_domain_index, mtu); - - return 0; -} - -static clib_error_t * -sixrd_del_domain_command_fn (vlib_main_t *vm, - unformat_input_t *input, - vlib_cli_command_t *cmd) -{ - unformat_input_t _line_input, *line_input = &_line_input; - u32 num_m_args = 0; - u32 sixrd_domain_index; - - /* Get a line of input. */ - if (! unformat_user(input, unformat_line_input, line_input)) - return 0; - - while (unformat_check_input(line_input) != UNFORMAT_END_OF_INPUT) { - if (unformat(line_input, "index %d", &sixrd_domain_index)) - num_m_args++; - else - return clib_error_return(0, "unknown input `%U'", - format_unformat_error, input); - } - unformat_free(line_input); - - if (num_m_args != 1) - return clib_error_return(0, "mandatory argument(s) missing"); - - sixrd_delete_domain(sixrd_domain_index); - - return 0; -} - -static u8 * -format_sixrd_domain (u8 *s, va_list *args) -{ - sixrd_domain_t *d = va_arg(*args, sixrd_domain_t *); - sixrd_main_t *mm = &sixrd_main; - - s = format(s, - "[%d] ip6-pfx %U/%d ip4-pfx %U/%d ip4-src %U mtu %d", - d - mm->domains, - format_ip6_address, &d->ip6_prefix, d->ip6_prefix_len, - format_ip4_address, &d->ip4_prefix, d->ip4_prefix_len, - format_ip4_address, &d->ip4_src, d->mtu); - - return s; -} - -static clib_error_t * -show_sixrd_domain_command_fn (vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd) -{ - sixrd_main_t *mm = &sixrd_main; - sixrd_domain_t *d; - - if (pool_elts(mm->domains) == 0) - vlib_cli_output(vm, "No SIXRD domains are configured..."); - - pool_foreach(d, mm->domains, ({vlib_cli_output(vm, "%U", format_sixrd_domain, d);})); - - return 0; - -} - -static clib_error_t * -show_sixrd_stats_command_fn (vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd) -{ - sixrd_main_t *mm = &sixrd_main; - sixrd_domain_t *d; - int domains = 0, domaincount = 0; - if (pool_elts (mm->domains) == 0) - vlib_cli_output (vm, "No SIXRD domains are configured..."); - - pool_foreach(d, mm->domains, ({ - domains += sizeof(*d); - domaincount++; - })); - - vlib_cli_output(vm, "SIXRD domains structure: %d\n", sizeof (sixrd_domain_t)); - vlib_cli_output(vm, "SIXRD domains: %d (%d bytes)\n", domaincount, domains); - - return 0; -} - -/* - * packet trace format function - */ -u8 * -format_sixrd_trace (u8 *s, va_list *args) -{ - CLIB_UNUSED(vlib_main_t *vm) = va_arg (*args, vlib_main_t *); - CLIB_UNUSED(vlib_node_t *node) = va_arg (*args, vlib_node_t *); - sixrd_trace_t *t = va_arg (*args, sixrd_trace_t *); - u32 sixrd_domain_index = t->sixrd_domain_index; - - s = format(s, "SIXRD domain index: %d", sixrd_domain_index); - - return s; -} - -VLIB_CLI_COMMAND(sixrd_add_domain_command, static) = { - .path = "sixrd add domain", - .short_help = - "sixrd add domain ip6-pfx ip4-pfx ip4-src ", - .function = sixrd_add_domain_command_fn, -}; - -VLIB_CLI_COMMAND(sixrd_del_command, static) = { - .path = "sixrd del domain", - .short_help = - "sixrd del domain index ", - .function = sixrd_del_domain_command_fn, -}; - -VLIB_CLI_COMMAND(show_sixrd_domain_command, static) = { - .path = "show sixrd domain", - .function = show_sixrd_domain_command_fn, -}; - -VLIB_CLI_COMMAND(show_sixrd_stats_command, static) = { - .path = "show sixrd stats", - .function = show_sixrd_stats_command_fn, -}; - -/* - * This routine exists to convince the vlib plugin framework that - * we haven't accidentally copied a random .dll into the plugin directory. - * - * Also collects global variable pointers passed from the vpp engine - */ -clib_error_t * -vlib_plugin_register (vlib_main_t * vm, vnet_plugin_handoff_t * h, - int from_early_init) -{ - clib_error_t * error = 0; - sixrd_main_t *mm = &sixrd_main; - - mm->vnet_main = vnet_get_main(); - mm->vlib_main = vm; - - return error; -} - -static clib_error_t * sixrd_init (vlib_main_t * vm) -{ - clib_error_t * error = 0; - sixrd_main_t *mm = &sixrd_main; - - vlib_node_t * ip6_lookup_node = vlib_get_node_by_name(vm, (u8 *)"ip6-lookup"); - vlib_node_t * ip4_lookup_node = vlib_get_node_by_name(vm, (u8 *)"ip4-lookup"); - vlib_node_t * ip6_sixrd_node = vlib_get_node_by_name(vm, (u8 *)"ip6-sixrd"); - vlib_node_t * ip4_sixrd_node = vlib_get_node_by_name(vm, (u8 *)"ip4-sixrd"); - ASSERT(ip6_lookup_node && ip4_lookup_node && ip6_sixrd_node && ip4_sixrd_node); - - mm->ip6_lookup_next_index = vlib_node_add_next(vm, ip6_lookup_node->index, ip6_sixrd_node->index); - mm->ip4_lookup_next_index = vlib_node_add_next(vm, ip4_lookup_node->index, ip4_sixrd_node->index); - - return error; -} - -VLIB_INIT_FUNCTION (sixrd_init); diff --git a/plugins/plugins/sixrd/sixrd.h b/plugins/plugins/sixrd/sixrd.h deleted file mode 100644 index 2f0912f0..00000000 --- a/plugins/plugins/sixrd/sixrd.h +++ /dev/null @@ -1,144 +0,0 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2009-2014 Cisco and/or its affiliates. - * 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 -#include -#include -#include - -int sixrd_create_domain(ip6_address_t *ip6_prefix, u8 ip6_prefix_len, - ip4_address_t *ip4_prefix, u8 ip4_prefix_len, - ip4_address_t *ip4_src, u32 *sixrd_domain_index, u16 mtu); -int sixrd_delete_domain(u32 sixrd_domain_index); -u8 *format_sixrd_trace(u8 *s, va_list *args); - -typedef struct { - ip6_address_t ip6_prefix; - ip4_address_t ip4_prefix; - ip4_address_t ip4_src; - u8 ip6_prefix_len; - u8 ip4_prefix_len; - - /* helpers */ - u8 shift; - - u16 mtu; -} sixrd_domain_t; - -typedef struct { - /* pool of SIXRD domains */ - sixrd_domain_t *domains; - - /* convenience */ - vlib_main_t *vlib_main; - vnet_main_t *vnet_main; - - u32 ip4_lookup_next_index; - u32 ip6_lookup_next_index; -} sixrd_main_t; - -#define foreach_sixrd_error \ - /* Must be first. */ \ - _(NONE, "valid SIXRD packets") \ - _(BAD_PROTOCOL, "bad protocol") \ - _(WRONG_ICMP_TYPE, "wrong icmp type") \ - _(SEC_CHECK, "security check failed") \ - _(ICMP, "unable to translate ICMP") \ - _(UNKNOWN, "unknown") \ - _(NO_DOMAIN, "no domain") \ - _(ENCAPSULATED, "encapsulated") \ - _(DECAPSULATED, "decapsulated") \ - _(TRANSLATED_4TO6, "translated 4 to 6") \ - _(TRANSLATED_6TO4, "translated 6 to 4") \ - _(FRAGMENT, "fragment handling error") \ - _(FRAGMENT_QUEUED, "dropped, missing first fragment") \ - _(FRAGMENTED, "packets requiring fragmentation") \ - _(FRAGMENT_PARTS, "fragment parts") \ - _(MALFORMED, "malformed packet") - -typedef enum { -#define _(sym,str) SIXRD_ERROR_##sym, - foreach_sixrd_error -#undef _ - SIXRD_N_ERROR, - } sixrd_error_t; - -typedef struct { - u32 sixrd_domain_index; -} sixrd_trace_t; - -sixrd_main_t sixrd_main; - -/* - * sixrd_get_addr - */ -static_always_inline u32 -sixrd_get_addr (sixrd_domain_t *d, u64 dal) -{ - - /* 1:1 mode */ - if (d->ip4_prefix_len == 32) return (d->ip4_prefix.as_u32); - - /* Grab 32 - ip4_prefix_len bits out of IPv6 address from offset ip6_prefix_len */ - return (d->ip4_prefix.as_u32 | (u32)(dal >> d->shift)); -} - -/* - * Get the SIXRD domain from an IPv6 lookup adjacency. - */ -static_always_inline sixrd_domain_t * -ip6_sixrd_get_domain (u32 adj_index, u32 *sixrd_domain_index) -{ - sixrd_main_t *mm = &sixrd_main; - ip_lookup_main_t *lm = &ip6_main.lookup_main; - ip_adjacency_t *adj = ip_get_adjacency(lm, adj_index); - ASSERT(adj); - uword *p = (uword *)adj->rewrite_data; - ASSERT(p); - *sixrd_domain_index = p[0]; - return pool_elt_at_index(mm->domains, p[0]); -} - -/* - * Get the SIXRD domain from an IPv4 lookup adjacency. - * If the IPv4 address is not shared, no lookup is required. - * The IPv6 address is used otherwise. - */ -static_always_inline sixrd_domain_t * -ip4_sixrd_get_domain (u32 adj_index, ip6_address_t *addr, - u32 *sixrd_domain_index, u8 *error) -{ - sixrd_main_t *mm = &sixrd_main; - ip6_main_t *im6 = &ip6_main; - ip_lookup_main_t *lm4 = &ip4_main.lookup_main; - ip_lookup_main_t *lm6 = &ip6_main.lookup_main; - ip_adjacency_t *adj = ip_get_adjacency(lm4, adj_index); - ASSERT(adj); - uword *p = (uword *)adj->rewrite_data; - ASSERT(p); - *sixrd_domain_index = p[0]; - if (p[0] != ~0) - return pool_elt_at_index(mm->domains, p[0]); - - u32 ai = ip6_fib_lookup_with_table(im6, 0, addr); - ip_adjacency_t *adj6 = ip_get_adjacency (lm6, ai); - if (PREDICT_TRUE(adj6->lookup_next_index == mm->ip6_lookup_next_index)) { - uword *p = (uword *)adj6->rewrite_data; - *sixrd_domain_index = p[0]; - return pool_elt_at_index(mm->domains, *sixrd_domain_index); - } - *error = SIXRD_ERROR_NO_DOMAIN; - return NULL; -} diff --git a/plugins/plugins/vcgn/README b/plugins/plugins/vcgn/README deleted file mode 100644 index 9b903967..00000000 --- a/plugins/plugins/vcgn/README +++ /dev/null @@ -1,100 +0,0 @@ - ================================= - CARRIER GRADE NAT - NAT44 README - ================================= - -What is implemented: -==================== -* NAT44 UDP, TCP, ICMP protocols -* Show and config commands for various parameters for the same -* NF9 logging is implemented but is not tested - -What is not implemented: -========================= -* TCP MSS -* TCP refresh direction -* Static port forwarding -* Syslog support -* Destination based logging or session logging -* None of the ALGs -* Performance optimization -* Binary APIs, suitable for configuring the feature from netconf/restconf/yang -* Support for VLANs - -Setup -===== - - +--------------+ -+------------+ GEb/0/0 | | -| Tester +-------------->+ vCGN/vPE-f | -| +<--------------+ VM in UCS | -+------------+ GE13/0/0 | | - +--------------+ - -Configure Interfaces and add routes in vPE-f -============================================= -set int ip address GigabitEthernetb/0/0 10.4.5.2/24 -set int state GigabitEthernetb/0/0 up -set int ip address GigabitEthernet13/0/0 20.4.5.2/24 -set int state GigabitEthernet13/0/0 up -ip route add 4.4.4.0/24 via GigabitEthernet13/0/0 -ip route add 1.2.3.0/24 via GigabitEthernetb/0/0 show ip fib - -Configure vCGN NAT44 for UDP/TCP/ICMP -======================================= -set vcgn inside GigabitEthernetb/0/0 outside GigabitEthernet13/0/0 -set vcgn port limit 65535 set vcgn dynamic port start 5641 -set vcgn map 10.1.1.0 - 10.1.1.31 set vcgn tcp timeout active 65535 init 65535 -set vcgn udp timeout active 65535 init 65535 set vcgn icmp timeout 65535 - -Set ARP entries for CGN to Tester -================================== -set ip arp GigabitEthernet13/0/0 4.4.4.4 11:22:33:44:55:00 -set ip arp GigabitEthernetb/0/0 1.2.3.0 11:22:33:44:55:10 -set ip arp GigabitEthernetb/0/0 1.2.3.1 11:22:33:44:55:12 -set ip arp GigabitEthernetb/0/0 1.2.3.2 11:22:33:44:55:13 -set ip arp GigabitEthernetb/0/0 1.2.3.3 11:22:33:44:55:14 -set ip arp GigabitEthernetb/0/0 1.2.3.4 11:22:33:4e:55:11 -set ip arp GigabitEthernetb/0/0 1.2.3.5 11:22:33:44:55:15 -set ip arp GigabitEthernetb/0/0 1.2.3.6 11:22:33:44:55:16 -set ip arp GigabitEthernetb/0/0 1.2.3.7 11:22:33:44:55:17 -set ip arp GigabitEthernetb/0/0 1.2.3.8 11:22:33:44:55:18 -set ip arp GigabitEthernetb/0/0 1.2.3.9 11:22:33:44:55:19 -set ip arp GigabitEthernetb/0/0 1.2.3.10 11:22:33:44:55:1a -set ip arp GigabitEthernetb/0/0 1.2.3.11 11:22:33:44:55:1b -set ip arp GigabitEthernetb/0/0 1.2.3.12 11:22:33:44:55:1c -set ip arp GigabitEthernetb/0/0 1.2.3.13 11:22:33:44:55:1d -set ip arp GigabitEthernetb/0/0 1.2.3.14 11:22:33:44:55:1e -set ip arp GigabitEthernetb/0/0 1.2.3.15 11:22:33:44:55:1f -set ip arp GigabitEthernetb/0/0 1.2.3.16 11:22:33:44:50:01 -set ip arp GigabitEthernetb/0/0 1.2.3.17 11:22:33:44:51:01 -set ip arp GigabitEthernetb/0/0 1.2.3.18 11:22:33:44:52:01 -set ip arp GigabitEthernetb/0/0 1.2.3.19 11:22:33:44:53:01 -set ip arp GigabitEthernetb/0/0 1.2.3.20 11:22:33:44:54:02 -set ip arp GigabitEthernetb/0/0 1.2.3.21 11:22:33:44:55:01 -set ip arp GigabitEthernetb/0/0 1.2.3.22 11:22:33:44:56:02 -set ip arp GigabitEthernetb/0/0 1.2.3.23 11:22:33:44:57:00 -set ip arp GigabitEthernetb/0/0 1.2.3.24 11:22:33:44:58:02 -set ip arp GigabitEthernetb/0/0 1.2.3.25 11:22:33:44:59:03 -set ip arp GigabitEthernetb/0/0 1.2.3.26 11:22:33:44:5a:01 -set ip arp GigabitEthernetb/0/0 1.2.3.27 11:22:33:44:5b:02 -set ip arp GigabitEthernetb/0/0 1.2.3.28 11:22:33:44:5c:03 -set ip arp GigabitEthernetb/0/0 1.2.3.29 11:22:33:44:5d:04 -set ip arp GigabitEthernetb/0/0 1.2.3.30 11:22:33:44:5e:05 -set ip arp GigabitEthernetb/0/0 1.2.3.31 11:22:33:44:5f:06 - - -Show commands -============= -show vcgn config -show vcgn statistics -show node counters -show interface - -Show commands to show translations -================================== -show vcgn inside-translation protocol tcp inside-addr 1.2.3.4 start-port 5641 end-port 5645 -show vcgn outside-translation protocol tcp outside-addr 10.1.1.31 start-port 7000 end-port 8000 -show vcgn inside-translation protocol icmp inside-addr 1.2.3.4 start-port 7000 end-port 8000 -show vcgn outside-translation protocol icmp outside-addr 10.1.1.31 start-port 7000 end-port 8000 - - diff --git a/plugins/plugins/vcgn/cgn_bitmap.h b/plugins/plugins/vcgn/cgn_bitmap.h deleted file mode 100644 index 6c46b75a..00000000 --- a/plugins/plugins/vcgn/cgn_bitmap.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * 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. - */ -/* - * Modifications to this file - * Copyright (c) 2006-2009 by cisco Systems, Inc. - * All rights reserved. - */ - -/* - Copyright (c) 2001, 2002, 2003, 2005 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef __CGN_BITMAP_H__ -#define __CGN_BITMAP_H__ - -/* Bitmaps built as vectors of machine words. */ - -#include -#include -#include -#include -#include - -#define clib_bitmap_dup(v) vec_dup(v) -#define clib_bitmap_free(v) vec_free(v) -#define clib_bitmap_bytes(v) vec_bytes(v) -#define clib_bitmap_zero(v) vec_zero(v) - -/* Allocate bitmap with given number of bits. */ -#define clib_bitmap_alloc(v,n_bits) \ - v = vec_new (uword, ((n_bits) + BITS (uword) - 1) / BITS (uword)) - -/* Sets given bit. Returns old value. */ -static inline uword -cgn_clib_bitmap_set_no_check (uword * a, uword i) -{ - uword i0 = i / BITS (a[0]); - uword bit = (uword) 1 << (i % BITS (a[0])); - uword ai; - -/* ASSERT (i0 < vec_len (a)); */ - ai = a[i0]; - a[i0] = ai | bit; - - return (ai & bit) != 0; -} - -/* Clears given bit. Returns old value. */ -static inline -uword cgn_clib_bitmap_clear_no_check (uword * a, uword i) -{ - uword i0 = i / BITS (a[0]); - uword bit = (uword) 1 << (i % BITS (a[0])); - uword ai; - -/* ASSERT (i0 < vec_len (a)); */ - ai = a[i0]; - a[i0] = ai & ~bit; - - return (ai & bit) != 0; -} - -/* Gets num_bits from ai start at start. assume that all bits are - * in the same uword. - */ -static inline uword cgn_clib_bitmap_get_bits (uword *ai, u16 start, - unsigned char num_bits) -{ - uword i0 = start / BITS (ai[0]); - uword i1 = start % BITS (ai[0]); - uword result = ai[i0] >> i1; - if(num_bits >= BITS(ai[0])) return result; - /* Else, we have to trim the bits */ - result = result & (((uword)1 << num_bits) - 1); - return result; -} - -/* Check if all of the bits from start to numb_bits are avaiable */ -static inline uword cgn_clib_bitmap_check_if_all (uword *ai, u16 start, - i16 num_bits) -{ - /* Now check if any bits are zero.. if yes, return false */ - uword bitmask; - if(num_bits >= BITS(ai[0])) { - /* assume that its going to be multiples of BUTS(ai[0]) */ - uword i0 = start / BITS (ai[0]); - bitmask = ~0; /* set all bits to 1 */ - do { - if(ai[i0] ^ bitmask) return 0; - num_bits = num_bits - BITS (ai[0]); - i0++; - } while (num_bits > 0); - return 1; - } - else { - uword result = cgn_clib_bitmap_get_bits (ai, start, num_bits); - bitmask = ((uword)1 << num_bits) -1; /* set only num_bits */ - return (!(result ^ bitmask)); - } -} - -#endif diff --git a/plugins/plugins/vcgn/cgse_defs.h b/plugins/plugins/vcgn/cgse_defs.h deleted file mode 100644 index 08255875..00000000 --- a/plugins/plugins/vcgn/cgse_defs.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - *------------------------------------------------------------------ - * cgse_defs.h - CGSE specific definiitions - * - * Copyright (c) 2007-2013 Cisco and/or its affiliates. - * 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 __CGSE_DEFS_H__ -#define __CGSE_DEFS_H__ - -#include "spp_platform_common.h" -#include - - -#define CGSE_SVI_TYPE_CNAT 1 -#define CGSE_SVI_TYPE_XLAT 2 -#define CGSE_SVI_TYPE_NAT64_STATEFUL 3 -#define CGSE_SVI_TYPE_V6RD 4 -#define CGSE_SVI_TYPE_INFRA 5 -#define CGSE_SVI_TYPE_DS_LITE 7 -#define CGSE_SVI_TYPE_MAPE 9 - -#define CGSE_SET_TX_PKT_TYPE(type) PLATFORM_SET_CTX_RU_TX_PKT_TYPE(ctx, type) - -#define CGSE_INVALID_UIDX 0xffff /*invalid svi app uidb index */ -#define CGSE_INVALID_VRFID 0xffffffff /*invalid vrf id */ - -#define CGSE_VRF_MASK 0x3fff -#define CGSE_MAX_VRFMAP_ENTRIES (CGSE_VRF_MASK + 1) - -#define CGSE_VRFMAP_ENTRY_INVALID 0xffff - - -#define CGSE_INVALID_CGSE_ID (0) - -#define CGSE_TABLE_ENTRY_DELETED 0 -#define CGSE_TABLE_ENTRY_ACTIVE 1 -#define CGSE_TABLE_ENTRY_DORMANT 2 -#define CGSE_TABLE_ENTRY_INVALID_UIDB 3 - - -#define CGSE_CONFIG_HANDLER_DEBUG_PRINTF1(level, a) \ - if (cgse_config_debug_level > level) printf(a); - -#define CGSE_CONFIG_HANDLER_DEBUG_PRINTF2(level, a, b) \ - if (cgse_config_debug_level > level) printf(a, b); - -#define CGSE_CONFIG_HANDLER_DEBUG_PRINTF3(level, a, b, c) \ - if (cgse_config_debug_level > level) printf(a, b, c); - -#define CGSE_CONFIG_HANDLER_DEBUG_PRINTF4(level, a, b, c, d) \ - if (cgse_config_debug_level > level) printf(a, b, c, d); - -#define CGSE_CONFIG_HANDLER_DEBUG_PRINTF5(level, a, b, c, d, e) \ - if (cgse_config_debug_level > level) printf(a, b, c, d, e); - -#define CGSE_CONFIG_HANDLER_DEBUG_PRINTF6(level, a, b, c, d, e, f) \ - if (cgse_config_debug_level > level) printf(a, b, c, d, e, f); - -#define CGSE_CONFIG_HANDLER_DEBUG_PRINTF7(level, a, b, c, d, e, f, g) \ - if (cgse_config_debug_level > level) printf(a, b, c, d, e, f, g); - -#define CGSE_CONFIG_HANDLER_DEBUG_PRINTF8(level, a, b, c, d, e, f, g, h) \ - if (cgse_config_debug_level > level) printf(a, b, c, d, e, f, g, h); - -#define CGSE_CONFIG_HANDLER_DEBUG_PRINTF9(level, a, b, c, d, e, f, g, h, i) \ - if (cgse_config_debug_level > level) printf(a, b, c, d, e, f, g, h, i); - -extern u16 *cgse_uidb_index_cgse_id_mapping_ptr; - -#define CGSE_ADD_UIDB_INDEX_CGSE_ID_MAPPING(uidb_index, cgse_id) \ - *(cgse_uidb_index_cgse_id_mapping_ptr + uidb_index) = cgse_id; - -extern u8 my_instance_number; - -#endif diff --git a/plugins/plugins/vcgn/cnat_bulk_port.c b/plugins/plugins/vcgn/cnat_bulk_port.c deleted file mode 100644 index d8894eb8..00000000 --- a/plugins/plugins/vcgn/cnat_bulk_port.c +++ /dev/null @@ -1,964 +0,0 @@ -/* - *------------------------------------------------------------------ - * cnat_bulk_ports.c - wrappers for bulk port allocation - * - * Copyright (c) 2011-2013 Cisco and/or its affiliates. - * 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 -#include -#include -#include -#include -#include -#include -#include - -#include "cnat_db.h" -#include "cnat_config.h" -#include "cnat_global.h" -#include "cnat_logging.h" -#include "spp_timers.h" -#include "platform_common.h" -#include "cgn_bitmap.h" -#include "spp_platform_trace_log.h" -#include "cnat_ports.h" - -#ifndef NO_BULK_LOGGING - -#define PORT_TO_CACHE(y, z) ((y)/(z)) -/* The last bit (MSB) is used to indicate whether the cache entry is full */ -#define CACHE_TO_PORT(x, z) (((x)& 0x7FFF) * (z)) -#define IS_CACHE_ENTRY_FULL(x) ((x) & 0x8000) -#define MARK_CACHE_ENTRY_AS_FULL(x) ((x) = ((x) | 0x8000)) -#define UNMARK_CACHE_ENTRY_AS_FULL(x) ((x) = ((x) & 0x7FFF)) -#define CACHE_ENTRY_WITHOUT_FULL_STAT(x) ((x) & 0x7FFF) - - -#define NUM_BULK_CHECK 128 /* max number of previous chache to check. - * somewhat orbirtrary.. assume 64 as bulk size.. can handle up - * to 128*64 ports allocated by a single subscriber */ - -/* #define DEBUG_BULK_PORT 1 */ -/* #define DEBUG_BULK_PORT_DETAIL 1 */ -#define HAVE_BULK_PORT_STATS 1 - -#ifdef HAVE_BULK_PORT_STATS -static uword bulk_cache_hit_count; -static uword bulk_port_use_count; -static uword bulk_port_alloc_count; -static uword mapped_port_alloc_count; -#endif /* HAVE_BULK_PORT_STATS */ - -static u32 bulk_port_rand_across; - -void show_bulk_port_allocation(u16 in_vrfid, u32 inside_ip) -{ - cnat_db_key_bucket_t u_ki; - cnat_user_db_entry_t *udb; - int i; - u32 head; - cnat_main_db_entry_t *db = NULL; - i16 printed_so_far = 0; /* entries printed so far */ - u16 prev_bulks[NUM_BULK_CHECK]; - cnat_vrfmap_t *my_vrfmap = 0; - cnat_vrfmap_t *vrfmap = 0; - bulk_alloc_size_t bulk_size; - - u_ki.k.k.vrf = in_vrfid; - u_ki.k.k.ipv4 = inside_ip; - u_ki.k.k.port = 0; - - PLATFORM_DEBUG_PRINT("Searching for user %x in invrf %d\n", - inside_ip, in_vrfid); - udb = cnat_user_db_lookup_entry(&u_ki); - if(!udb) { - PLATFORM_DEBUG_PRINT("No such user\n"); return; - } - - pool_foreach (vrfmap, cnat_map_by_vrf, ({ - if(vrfmap->i_vrf == in_vrfid) { - my_vrfmap = vrfmap; - break; - }})); - - if(!my_vrfmap) { - PLATFORM_DEBUG_PRINT("Vrf map not found\n"); - return; - } - bulk_size = BULKSIZE_FROM_VRFMAP(my_vrfmap); - - if(bulk_size == BULK_ALLOC_SIZE_NONE) { - PLATFORM_DEBUG_PRINT("Bulk allocation not enabled\n"); - return; - } - - PLATFORM_DEBUG_PRINT("\nBulk cache for subscriber 0x%x: ", inside_ip); - for(i=0; i < BULK_RANGE_CACHE_SIZE; i++) { - PLATFORM_DEBUG_PRINT("%d , ", - CACHE_TO_PORT(udb->bulk_port_range_cache[i], bulk_size)); - } - PLATFORM_DEBUG_PRINT("\nNon cached bulk allocation for subscriber 0x%x:\n", - inside_ip); - ASSERT(udb); - memset(prev_bulks, 0,sizeof(prev_bulks)); - - head = udb->translation_list_head_index; - if(PREDICT_FALSE(head == EMPTY)) { - return; - } - db = cnat_main_db + head; - while (1) { - /* skip static ports - static ports may not belong to bulk pool*/ - if(db->out2in_key.k.port < cnat_static_port_range) goto next_entry; - - u16 bm_index = PORT_TO_CACHE(db->out2in_key.k.port, bulk_size); - - /*Check if we have already tested this bulk */ - for(i=0; i < printed_so_far; i++) { - if(prev_bulks[i] == bm_index) goto next_entry; - } - - /*Check if this base port is already part of cache */ - for(i=0; i < BULK_RANGE_CACHE_SIZE; i++) { - if(CACHE_ENTRY_WITHOUT_FULL_STAT(udb->bulk_port_range_cache[i]) - == bm_index) { - goto next_entry; - } - } - /* this is not in chache already */ - PLATFORM_DEBUG_PRINT("%d ", CACHE_TO_PORT(bm_index, bulk_size)); - if(printed_so_far < NUM_BULK_CHECK) { - prev_bulks[printed_so_far] = bm_index; - printed_so_far++; - } - -next_entry: - db = cnat_main_db + db->user_ports.next; - /* - * its a circular list, so if we have reached the head again - * all the entries for that user have been read - */ - if (db == (cnat_main_db + head)) { - break; - } - } /* while loop for db entries */ - - PLATFORM_DEBUG_PRINT("\n"); - return; -} - -void show_bulk_port_stats() -{ - - cnat_vrfmap_t *my_vrfmap = 0; - PLATFORM_DEBUG_PRINT("Bulk size settings of each inside vrf ...\n"); - pool_foreach (my_vrfmap, cnat_map_by_vrf, ({ - PLATFORM_DEBUG_PRINT("vrf id %d, bulk size %d\n", my_vrfmap->i_vrf, - BULKSIZE_FROM_VRFMAP(my_vrfmap)); - })); - -#ifdef HAVE_BULK_PORT_STATS - PLATFORM_DEBUG_PRINT("\nBulk port allocation, use and cache hit statistics\n"); - PLATFORM_DEBUG_PRINT("Number of times bulk ports allocated %lld\n", - bulk_port_alloc_count); - PLATFORM_DEBUG_PRINT("Number of times pre-allocated ports used %lld\n", - bulk_port_use_count); - PLATFORM_DEBUG_PRINT( - "Number of times pre-allocated bulk port found from cache %lld\n", - bulk_cache_hit_count); - PLATFORM_DEBUG_PRINT( - "Number of times mapped port (static) allocations made %lld\n", - mapped_port_alloc_count); -#else - PLATFORM_DEBUG_PRINT("\nNat44 bulk port statistics not turned on\n"); -#endif /* HAVE_BULK_PORT_STATS */ -} - -void clear_bulk_port_stats() -{ -#ifdef HAVE_BULK_PORT_STATS - bulk_port_alloc_count = 0; - bulk_port_use_count = 0; - bulk_cache_hit_count = 0; - mapped_port_alloc_count = 0; -#endif /* HAVE_BULK_PORT_STATS */ - return; -} - -void cnat_update_bulk_range_cache(cnat_user_db_entry_t *udb, u16 o_port, - bulk_alloc_size_t bulk_size) -{ - i16 i; - if(!udb) { -#ifdef DEBUG_BULK_PORT - PLATFORM_DEBUG_PRINT("%s, null udb!\n", __func__); -#endif - return; - } - if(BULK_ALLOC_SIZE_NONE == bulk_size) { /* no bulk logging */ - return; - } - - /* Take care of caching */ - if(o_port & 0x1) { - o_port--; - } - if(PREDICT_FALSE(o_port <= 0)) { -#ifdef DEBUG_BULK_PORT - PLATFORM_DEBUG_PRINT("%s invalid port: %d\n", __func__, o_port); -#endif - return; - } - - /* First preference is for the cache entry's that are not used yet */ - for(i=0; i < BULK_RANGE_CACHE_SIZE; i++) { - if(PREDICT_FALSE( - udb->bulk_port_range_cache[i] == (i16)BULK_RANGE_INVALID)) { - udb->bulk_port_range_cache[i] = PORT_TO_CACHE(o_port, bulk_size); - return; - } - } - - /* Now check if any cache entry is full and if it can be replaced */ - for(i=0; i < BULK_RANGE_CACHE_SIZE; i++) { - if(PREDICT_FALSE(IS_CACHE_ENTRY_FULL(udb->bulk_port_range_cache[i]))) { - udb->bulk_port_range_cache[i] = PORT_TO_CACHE(o_port, bulk_size); - return; - } - } - - return; -} - - -void cnat_port_free_v2_bulk ( - cnat_portmap_v2_t *pm, - int index, - port_pair_t ptype, - u16 base_port, - cnat_user_db_entry_t *udb, - u16 static_port_range, - bulk_alloc_size_t bulk_size, - int *nfv9_log_req) -{ - cnat_portmap_v2_t *my_pm; - i16 bm_index; - i16 i; - int unmark_full_status = 0; - - *nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED; - - /* First free up the port */ - cnat_port_free_v2(pm, index, ptype, base_port, static_port_range); - if(BULK_ALLOC_SIZE_NONE == bulk_size) /* no bulk logging */ - return; - if(PREDICT_FALSE(!udb)) { -#ifdef DEBUG_BULK_PORT - PLATFORM_DEBUG_PRINT("%s udb is null\n", __func__); -#endif - } - - if(PREDICT_FALSE(base_port < static_port_range)) { - return; - } - /* Now check if cache needs to be removed */ - my_pm = pm + index; - base_port = base_port/bulk_size; - base_port = base_port * bulk_size; /*Align it to multiples of bulk_size */ - if(PREDICT_TRUE(!cgn_clib_bitmap_check_if_all( - my_pm->bm, base_port, bulk_size))) { - *nfv9_log_req = CACHE_ALLOC_NO_LOG_REQUIRED; - unmark_full_status = 1; - /* One or more ports are still in use */ - } else { - *nfv9_log_req = base_port; /* logging required now. indicate base port*/ - } - bm_index = PORT_TO_CACHE(base_port, bulk_size); - /* Now check if this is in the cache */ - for(i=0; i < BULK_RANGE_CACHE_SIZE; i++) { - if(PREDICT_FALSE( - CACHE_ENTRY_WITHOUT_FULL_STAT(udb->bulk_port_range_cache[i])) - == bm_index) { - if(unmark_full_status) { - /* Unmark full stat.. if it was marked so..*/ - UNMARK_CACHE_ENTRY_AS_FULL(udb->bulk_port_range_cache[i]); - } else { - udb->bulk_port_range_cache[i] = (i16)BULK_RANGE_INVALID; -#ifdef DEBUG_BULK_PORT - PLATFORM_DEBUG_PRINT( - "Clearing cache for client 0x%x, bulk port %d\n", - my_pm->ipv4_address, base_port); -#endif - } - break; - } - } - return; -} - - -/* Get suitable port from range */ -static i16 get_suiting_port_pos_from_range(cnat_portmap_v2_t *my_pm, - u16 bulk_start, i16 bulk_size, port_pair_t pair_type) -{ - i16 num_pos = 0, num_bits, iterations; - uword bulk_ports; - i16 inc = 0; - i16 num_uwords = bulk_size/BITS(my_pm->bm[0]); - - if(PREDICT_FALSE(!num_uwords)) { - iterations = 0; - num_bits = bulk_size; - bulk_size = 0; - } else { - bulk_port_rand_across = randq1(bulk_port_rand_across); - iterations = bulk_port_rand_across % num_uwords; - num_bits = BITS(my_pm->bm[0]); - } - - do { - bulk_ports = cgn_clib_bitmap_get_bits(my_pm->bm, - (bulk_start + iterations * BITS(my_pm->bm[0])), num_bits); -#ifdef DEBUG_BULK_PORT_DETAIL - PLATFORM_DEBUG_PRINT("%s %d, bulk start %d, num_bits %d, ports %lld \n", - __func__, __LINE__, bulk_start, num_bits, bulk_ports); -#endif /* DEBUG_BULK_PORT_DETAIL */ - if(PREDICT_FALSE(!bulk_ports)) goto next_uword; - if(PREDICT_TRUE((pair_type == PORT_SINGLE) - || (pair_type == PORT_PAIR))) { - num_pos =0; - inc = 1; - } else if(pair_type == PORT_S_ODD) { - num_pos = 1; - inc = 2; - } else if(pair_type == PORT_S_EVEN) { - num_pos =0; - inc = 2; - } - - for(; num_pos < num_bits; num_pos = num_pos + inc) { - if(!((bulk_ports >> num_pos) & 1)) - continue; /* In use */ - /* Check if the available port meets our - * criteria such as add, even, pair etc */ - else if(PREDICT_FALSE( - (pair_type == PORT_PAIR) && ((num_pos & 0x1) || - (!((bulk_ports >> (num_pos + 1)) & 1))))) - continue; - else break; /* Found one that meets the criteria */ - } - if(num_pos < num_bits) - return (num_pos + iterations * BITS(my_pm->bm[0])); -next_uword: - num_bits = BITS(my_pm->bm[0]); - bulk_size -= BITS(my_pm->bm[0]); - iterations++; - if(iterations >= num_uwords) iterations = 0; - } while (bulk_size > 0); - - return -2; /* nothing found */ -} - -static cnat_errno_t try_bulk_port_from_non_cache( - cnat_user_db_entry_t *udb, - cnat_portmap_v2_t *my_pm, - port_pair_t pair_type, - bulk_alloc_size_t bulk_size, - u16 *port_available, - u16 static_port_range - ) -{ - /**** - 1. user should have existing translations.. otherwise, we wouldn't get here. - 2. For each, get the outside port. get the base port. - check if it is already in cache - 3. if not, we stand chance. - 4. Check for availability from this non cached pool. - 5. if found, repalce this with one of the cache that is invalid or full?? - 6. if we are replacing the cache.. it has to be governed by user - preference on prefer oldest pool or prefer newest pool - ********/ - u32 head; - cnat_main_db_entry_t *db = NULL; - u16 bulk_start; /* start point in 64 bitmap array to search for port */ - i16 port_pos; /* indicates the position of available port in bulk */ - i16 i; /* just a counter */ - i16 attempts_so_far = 0; /* (futile-;) attemps so far..*/ - u16 prev_bulks[NUM_BULK_CHECK]; - ASSERT(udb); - memset(prev_bulks, 0,sizeof(prev_bulks)); - - head = udb->translation_list_head_index; - if(PREDICT_FALSE(head == EMPTY)) return CNAT_NO_PRE_ALLOCATED_BULK_PORTS; - - db = cnat_main_db + head; - while (1) { //what should be the limit?? - - /* skip static ports - static ports may not belong to bulk pool*/ - if(db->out2in_key.k.port < static_port_range) goto next_entry; - - u16 bm_index = PORT_TO_CACHE(db->out2in_key.k.port, bulk_size); - - /*Check if we have already tested this bulk */ - for(i=0; i < attempts_so_far; i++) { - if(prev_bulks[i] == bm_index) { - goto next_entry; - } - } - - /*Check if this base port is already part of cache */ - for(i=0; i < BULK_RANGE_CACHE_SIZE; i++) { - if(CACHE_ENTRY_WITHOUT_FULL_STAT(udb->bulk_port_range_cache[i]) - == bm_index) - goto next_entry; - } - - /* this is not in chache already */ - bulk_start = CACHE_TO_PORT(bm_index, bulk_size); - port_pos = get_suiting_port_pos_from_range(my_pm, - bulk_start, bulk_size, pair_type); - - if(port_pos < 0) { /* no port available in this range */ - /* Mark this bulk so that we don't have to try this again */ - if(attempts_so_far < NUM_BULK_CHECK) { - prev_bulks[attempts_so_far] = bm_index; - attempts_so_far++; - } - goto next_entry; - } - - /* Got one...Get the port number */ - *port_available = bulk_start + port_pos; - - /* Check to see if we shoud replace one of the cache */ - for(i=0; i < BULK_RANGE_CACHE_SIZE; i++) { - if(PREDICT_FALSE((udb->bulk_port_range_cache[i] - == (i16)BULK_RANGE_INVALID) || ( - IS_CACHE_ENTRY_FULL(udb->bulk_port_range_cache[i])))) { - udb->bulk_port_range_cache[i] = bm_index; - return CNAT_SUCCESS; - } - } - /* Check to replace an existing (in use) entry */ - /* TODO: enforce policy */ - /* order of looping should depend on policy */ - - return CNAT_SUCCESS; - -next_entry: - db = cnat_main_db + db->user_ports.next; - /* - * its a circular list, so if we have reached the head again - * all the entries for that user have been read - */ - if (db == (cnat_main_db + head)) { - break; - } - } /* while loop for db entries */ - /* no ports available from pre allocated bulk pool */ - return CNAT_NO_PORT_FROM_BULK; -} - -cnat_errno_t -cnat_dynamic_port_alloc_v2_bulk ( - cnat_portmap_v2_t *pm, - port_alloc_t atype, - port_pair_t pair_type, - u32 *index, - u32 *o_ipv4_address, - u16 *o_port, - u16 static_port_range, - cnat_user_db_entry_t *udb, - bulk_alloc_size_t bulk_size, - int *nfv9_log_req, - u16 ip_n_to_1, - u32 *rseed_ip - ) -{ - - cnat_errno_t rv; - u16 port_available = 0; - i16 i; - cnat_portmap_v2_t *my_pm; - - if((BULK_ALLOC_SIZE_NONE != bulk_size) /* bulk logging enabled */ - && (udb)) { /* This user does have translations already */ - u16 bulk_start; - i16 port_pos; - - my_pm = pm + *index; - /* We have a case to check if bulk allocated ports can be used */ - /* TODO: order of looping to be based on policy - * like prefer older or prefer newer ?? - * For now, start with most recent cache entry - * so that we stand a better chance of - * finding a port - */ - for(i= 0; i < BULK_RANGE_CACHE_SIZE; i++) { - if(PREDICT_TRUE((udb->bulk_port_range_cache[i] == - (i16)BULK_RANGE_INVALID) || - IS_CACHE_ENTRY_FULL(udb->bulk_port_range_cache[i]))) { - continue; /* This range is not initialized yet or it is full */ - } - bulk_start = CACHE_TO_PORT(udb->bulk_port_range_cache[i], - bulk_size); - port_pos = get_suiting_port_pos_from_range(my_pm, - bulk_start, bulk_size, pair_type); - if(PREDICT_FALSE(port_pos < 0)) { - /* Mark this cache entry as full so that we do not - * waste time on this entry again */ - MARK_CACHE_ENTRY_AS_FULL(udb->bulk_port_range_cache[i]); -#ifdef DEBUG_BULK_PORT - PLATFORM_DEBUG_PRINT("Marked bulk cache entry %d as full for %x \n", - i, my_pm->ipv4_address); -#endif /* #ifdef DEBUG_BULK_PORT */ - continue; - } - /* Get the port number */ - port_available = bulk_start+ port_pos; -#ifdef DEBUG_BULK_PORT - PLATFORM_DEBUG_PRINT( - "Found port from cache : IP 0x%x, port %d %d iterations\n", - my_pm->ipv4_address, port_available, i) -#endif -#ifdef HAVE_BULK_PORT_STATS - bulk_cache_hit_count++; -#endif /* HAVE_BULK_PORT_STATS */ - break; - } /* end of for loop for cache check */ - /* If we have not found a port yet, check if we can have - * pre allocated bulk port from non-cache */ - if(PREDICT_FALSE(i == BULK_RANGE_CACHE_SIZE)) { - if( try_bulk_port_from_non_cache(udb, my_pm, pair_type, - bulk_size, &port_available, - static_port_range) != CNAT_SUCCESS ) { - goto ALLCOATE_NEW_BULK; - } -#ifdef DEBUG_BULK_PORT - PLATFORM_DEBUG_PRINT("Found port from non-cache : IP 0x%x, port %d\n", - my_pm->ipv4_address, port_available); -#endif - } - /* Assign the port, mark it as in use */ - cgn_clib_bitmap_clear_no_check(my_pm->bm, port_available); - (my_pm->inuse)++; - if(PREDICT_FALSE(pair_type == PORT_PAIR)) {/* Mark the next one too */ - cgn_clib_bitmap_clear_no_check(my_pm->bm, port_available + 1); - (my_pm->inuse)++; - } - *o_ipv4_address = my_pm->ipv4_address; - *o_port = port_available; - *nfv9_log_req = CACHE_ALLOC_NO_LOG_REQUIRED; -#ifdef HAVE_BULK_PORT_STATS - bulk_port_use_count++; -#endif /* HAVE_BULK_PORT_STATS */ - return (CNAT_SUCCESS); - } -ALLCOATE_NEW_BULK: -#ifdef DEBUG_BULK_PORT - if(BULK_ALLOC_SIZE_NONE != bulk_size) { - PLATFORM_DEBUG_PRINT( - "No port available from bulk cache, bulk size %d\n", bulk_size); - } -#endif - /* For whatever reason, we have not got a port yet */ - rv = cnat_dynamic_port_alloc_v2(pm, atype, pair_type, index, - o_ipv4_address, o_port, static_port_range, bulk_size, nfv9_log_req, - ip_n_to_1, rseed_ip); - if (PREDICT_FALSE(rv != CNAT_SUCCESS)) { - return rv; - } - /* Take care of caching */ - if(PREDICT_FALSE(udb != NULL)) { - /* Predict false because, we usually allocate for new users */ - cnat_update_bulk_range_cache(udb, *o_port, bulk_size); - } -#ifdef HAVE_BULK_PORT_STATS - bulk_port_alloc_count++; -#endif /* HAVE_BULK_PORT_STATS */ - return (CNAT_SUCCESS); -} - - -cnat_errno_t -cnat_static_port_alloc_v2_bulk ( - cnat_portmap_v2_t *pm, - port_alloc_t atype, - port_pair_t pair_type, - u32 i_ipv4_address, - u16 i_port, - u32 *index, - u32 *o_ipv4_address, - u16 *o_port, - u16 static_port_range, - cnat_user_db_entry_t *udb, - bulk_alloc_size_t bulk_size, - int *nfv9_log_req, - u16 ip_n_to_1 - ) -{ - - /*** - * Requirements - - * 1. If the port allocated is below dyn start, it should be individual - * port (not bulk) - * 2. If NOT, it should be bulk allocated - * 3. Try and keep the inside port same as outside port in both the - * cases (best effort) - - * Algorithm - * 1. Check if it is below stat port start or user is new or bulk is - * disabled. If yes, call existing function - * 2. If not, see if we can pick from bulk and yet try to keep the port - * same - difficult thing - check if the port is free - then check if the - * entire bulk is free - if not check if bulk is owned by the user already. - * If all of these fail, call existing function to allocate a new bulk - * 3. Update cache, etc return log requirements - *****/ - - cnat_errno_t rv; - i16 i; - u32 head; - cnat_portmap_v2_t *my_pm; - uword bit_test_result, start_bit; - cnat_main_db_entry_t *db = NULL; - - if((BULK_ALLOC_SIZE_NONE != bulk_size) /* bulk logging enabled */ - && (udb) && /* This user does have translations already */ - i_port >= static_port_range ) { /* It is outside stat port range*/ - - my_pm = pm + *index; - /* We have a case to check if bulk allocated ports can be used */ - - /* First check if the required port is available. */ - if(PREDICT_FALSE(clib_bitmap_get_no_check(my_pm->bm, i_port) == 0)) { - goto ALLOCATE_NEW_BULK_STATIC; - } - - /* Port is free.. check if the bulk is also free */ - start_bit= ((i_port/bulk_size) * bulk_size); - bit_test_result = cgn_clib_bitmap_check_if_all(my_pm->bm, - start_bit, bulk_size); - if(PREDICT_TRUE(bit_test_result)) { /* bulk is available, grab it */ - goto ALLOCATE_NEW_BULK_STATIC; - } - - /* else, bulk is taken by someone. check if it is me */ - /* Check if we own the bulk by any chance */ - for(i=0; i < BULK_RANGE_CACHE_SIZE; i++) { - if(udb->bulk_port_range_cache[i] == start_bit) break; - } - if(i == BULK_RANGE_CACHE_SIZE) { /* no luck with cache */ - head = udb->translation_list_head_index; - if(PREDICT_FALSE(head == EMPTY)) - goto ALLOCATE_NEW_BULK_STATIC; - db = cnat_main_db + head; - i = 0; - while(1) { - if((db->out2in_key.k.port/bulk_size) * bulk_size == start_bit) { - i = 1; /* Just to indicate it is found */ - break; - } - db = cnat_main_db + db->user_ports.next; - /* - * its a circular list, so if we have reached the head again - * all the entries for that user have been read - */ - if (db == (cnat_main_db + head)) break; - } /* while loop for db entries */ - if(!i) { - goto ALLOCATE_NEW_BULK_STATIC; - } - } - /* Assign the port, mark it as in use */ - cgn_clib_bitmap_clear_no_check(my_pm->bm, i_port); - (my_pm->inuse)++; - *o_ipv4_address = my_pm->ipv4_address; - *o_port = i_port; - *nfv9_log_req = CACHE_ALLOC_NO_LOG_REQUIRED; -#ifdef HAVE_BULK_PORT_STATS - bulk_port_use_count++; -#endif /* HAVE_BULK_PORT_STATS */ - -#ifdef DEBUG_BULK_PORT - PLATFORM_DEBUG_PRINT("%s, %d, found stat port from bulk: %x, %d\n", - __func__, - __LINE__, *o_ipv4_address, *o_port); -#endif /* DEBUG_BULK_PORT */ - return (CNAT_SUCCESS); - } - -ALLOCATE_NEW_BULK_STATIC: -#ifdef DEBUG_BULK_PORT - PLATFORM_DEBUG_PRINT("%s No port available from bulk cache, bulk size %d\n", - __func__,bulk_size); -#endif - /* For whatever reason, we have not got a port yet */ - rv = cnat_static_port_alloc_v2(pm, atype, pair_type, i_ipv4_address, - i_port, index, o_ipv4_address, o_port, static_port_range, - bulk_size, nfv9_log_req,ip_n_to_1); - if (PREDICT_FALSE(rv != CNAT_SUCCESS)) { - return rv; - } - /* Take care of caching only if it was a bulk alloc */ - if(PREDICT_FALSE(udb && (BULK_ALLOC_NOT_ATTEMPTED != *nfv9_log_req))) { - cnat_update_bulk_range_cache(udb, *o_port, bulk_size); - } -#ifdef HAVE_BULK_PORT_STATS - bulk_port_alloc_count++; -#endif /* HAVE_BULK_PORT_STATS */ - return (CNAT_SUCCESS); - -} - -cnat_errno_t -cnat_mapped_static_port_alloc_v2_bulk ( - cnat_portmap_v2_t *pm, - port_alloc_t atype, - u32 *index, - u32 ipv4_address, - u16 port, - cnat_user_db_entry_t *udb, - bulk_alloc_size_t bulk_size, - int *nfv9_log_req, - u16 ip_n_to_1 - ) -{ - /* Requirements : - * 1. Check if bulk allocation is required. - * 2. Call cnat_mapped_static_port_alloc_v2 to allocate - * 3. Decide if alloc has to be cached - * 4. Update nfv9_log_req - */ - cnat_errno_t rv; - rv = cnat_mapped_static_port_alloc_v2 (pm, - atype, index, ipv4_address, port, nfv9_log_req, bulk_size, ip_n_to_1); - if (PREDICT_FALSE(rv != CNAT_SUCCESS)) { - return rv; - } - /* Take care of caching only if it was a bulk alloc */ - if(PREDICT_FALSE(udb && (BULK_ALLOC_NOT_ATTEMPTED != *nfv9_log_req))) { - int i; - port = port*bulk_size; - port = port/bulk_size; /* align it to bulk size boundary */ - for(i=0; i < BULK_RANGE_CACHE_SIZE; i++) { - if(CACHE_ENTRY_WITHOUT_FULL_STAT(udb->bulk_port_range_cache[i]) - == PORT_TO_CACHE(port, bulk_size)) - break; - } - if( i == BULK_RANGE_CACHE_SIZE) { /* else, it is alredy in cache */ - cnat_update_bulk_range_cache(udb, port, bulk_size); - } - } -#ifdef HAVE_BULK_PORT_STATS - mapped_port_alloc_count++; -#endif /* HAVE_BULK_PORT_STATS */ - return (CNAT_SUCCESS); -} - - -cnat_errno_t -cnat_dynamic_port_alloc_rtsp_bulk ( - cnat_portmap_v2_t *pm, - port_alloc_t atype, - port_pair_t pair_type, - u16 i_port, - u32 *index, - u32 *o_ipv4_address, - u16 *o_port, - u16 static_port_range, - cnat_user_db_entry_t *udb, - bulk_alloc_size_t bulk_size, - int *nfv9_log_req, - u32 *rseed_ip) -{ - - /*** - * Algorithm - * 1. Compute the range of ports required based on the number of digits - * in the port request made by the client. - * 2. Check if bulk logging is enabled. If not, use the existing method. - * 3. Check if there are 2 adjacent ports available that meet the above - * criteria in any of the bulk allocations made already. - * 4. If yes, mark them in use and return. - * 5. If not allocate a new bulk and pick 2 ports in it - ***/ - - i16 i; - cnat_portmap_v2_t *my_pm = 0; - u32 start_port1, end_port1, start_port2, end_port2; - int range_loop; - u16 bulk_start; - i16 port_pos; - u16 port_available = 0; - - ASSERT(index); - ASSERT(o_ipv4_address); - ASSERT(o_port); - - /* - * Check if the port is 4 digit or 5 digit. I am assuming we are - * not getting 3 (or 2 or 1) digit ports, which we cannot anyway - * allocate same sized outside ports - as outside ports start from 1024 - * - * Static Port has its own reserved range. Ensure that the range is - * such that atleast few 4 digit ports are available for RTSP. If - * not it does not make sense to do special allocation for RTSP. - */ - if (PREDICT_TRUE(static_port_range < MIN_STATIC_PORT_RANGE_FOR_RTSP)) { - /* - * 4 digit port or less - */ - if (i_port <= 9999) { - start_port1 = static_port_range; - end_port1 = 9999; - - start_port2 = 10000; - end_port2 = PORTS_PER_ADDR - 1; - } else { /* 5 digit port */ - start_port1 = 10000; - end_port1 = PORTS_PER_ADDR - 1; - - start_port2 = static_port_range; - end_port2 = 9999; - } - } else { /* Static port range is too big */ - start_port1 = static_port_range; - end_port1 = PORTS_PER_ADDR - 1; - - /* - * PORTS_PER_ADDR is just a placeholder for - * INVALID_PORT, valid ports are b/w 1 and PORTS_PER_ADDR - */ - start_port2 = PORTS_PER_ADDR; - end_port2 = PORTS_PER_ADDR; - } - - - if(PREDICT_TRUE(udb != NULL)) { - my_pm = pm + *index; - } - - /* Now check if this user already owns a bulk range that is - * within start range 1 - */ - - u32 start_range = start_port1; - u32 end_range = end_port1; - for(range_loop = 0; range_loop < 2; range_loop++) { - if((BULK_ALLOC_SIZE_NONE == bulk_size) || (!udb)) { - goto ALLOCATE_NEW_RTSP_PORTS; - } - for(i= 0; i < BULK_RANGE_CACHE_SIZE; i++) { - if(PREDICT_TRUE((udb->bulk_port_range_cache[i] == - (i16)BULK_RANGE_INVALID) || - IS_CACHE_ENTRY_FULL(udb->bulk_port_range_cache[i]))) { - continue; /* This range is not initialized yet or it is full */ - } - - bulk_start = CACHE_TO_PORT(udb->bulk_port_range_cache[i], - bulk_size); - if(bulk_start < start_port1 || bulk_start >= end_port1) { - continue; /* Not in the range */ - } - - port_pos = get_suiting_port_pos_from_range(my_pm, - bulk_start, bulk_size, pair_type); - if(PREDICT_FALSE(port_pos < 0)) { - /* Not Marking this cache entry as full as it failed - * for pair type. It might have individual entries - */ - continue; - } - /* Get the port number */ - port_available = bulk_start+ port_pos; -#ifdef DEBUG_BULK_PORT - PLATFORM_DEBUG_PRINT( - "Found port from cache : IP 0x%x, port %d %d iterations\n", - my_pm->ipv4_address, port_available, i) -#endif -#ifdef HAVE_BULK_PORT_STATS - bulk_cache_hit_count += 2; -#endif /* HAVE_BULK_PORT_STATS */ - break; - } /* end of for loop for cache check */ - - if(PREDICT_FALSE(i == BULK_RANGE_CACHE_SIZE)) { - /* we have not found a port yet, but to do not want to try - * non-cache bulks.. because, it is a very low probability and - * do not want to tweak that code for this special case - * The impact of non checking the non-cache is, we give this - * user few extra ports .. which is OK - */ - goto ALLOCATE_NEW_RTSP_PORTS; - } -#ifdef DEBUG_BULK_PORT - PLATFORM_DEBUG_PRINT("RTSP: Found port from non-cache : IP 0x%x, port %d\n", - my_pm->ipv4_address, port_available); -#endif - - /* Assign the port, mark it as in use */ - cgn_clib_bitmap_clear_no_check(my_pm->bm, port_available); - (my_pm->inuse)++; - cgn_clib_bitmap_clear_no_check(my_pm->bm, port_available + 1); - (my_pm->inuse)++; - - *o_ipv4_address = my_pm->ipv4_address; - *o_port = port_available; - *nfv9_log_req = CACHE_ALLOC_NO_LOG_REQUIRED; -#ifdef HAVE_BULK_PORT_STATS - bulk_port_use_count += 2; -#endif /* HAVE_BULK_PORT_STATS */ - return (CNAT_SUCCESS); - -ALLOCATE_NEW_RTSP_PORTS: - /* No luck. Let's try allocating new bulk.. */ - if(PREDICT_TRUE(CNAT_SUCCESS == cnat_dynamic_port_alloc_rtsp - (pm, atype, pair_type, - start_range, end_range,index, o_ipv4_address, - o_port, bulk_size, nfv9_log_req,rseed_ip))) { - if(PREDICT_FALSE(udb && - (BULK_ALLOC_NOT_ATTEMPTED != *nfv9_log_req))) { - cnat_update_bulk_range_cache(udb, *o_port, bulk_size); - } -#ifdef HAVE_BULK_PORT_STATS - bulk_port_alloc_count++; -#endif /* HAVE_BULK_PORT_STATS */ - return CNAT_SUCCESS; - } - - /* Could not allocate in range 1.. so move to range 2. */ - start_range = start_port2; - end_range = end_port2; - - } - - return (CNAT_NOT_FOUND_DIRECT); /* if we are here, we could not get any ports */ - -} - -#else /* Dummy definitions */ -void show_bulk_port_stats() -{ - PLATFORM_DEBUG_PRINT("\nBulk logging feature not included\n"); -} - - void clear_bulk_port_stats() -{ - PLATFORM_DEBUG_PRINT("\nBulk logging feature not included\n"); -} -#endif /* NO_BULK_LOGGING */ diff --git a/plugins/plugins/vcgn/cnat_bulk_port.h b/plugins/plugins/vcgn/cnat_bulk_port.h deleted file mode 100644 index 3e48b9a7..00000000 --- a/plugins/plugins/vcgn/cnat_bulk_port.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - *------------------------------------------------------------------ - * cnat_bulk_port_defs.h bulk port alloc definitions - * - * Copyright (c) 2011-2013 Cisco and/or its affiliates. - * 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 __CNAT_BULK_PORT_H__ -#define __CNAT_BULK_PORT_H__ - -#ifndef NO_BULK_LOGGING -#include "cnat_bulk_port_defs.h" - -cnat_errno_t -cnat_dynamic_port_alloc_v2_bulk ( - cnat_portmap_v2_t *pm, - port_alloc_t atype, - port_pair_t pair_type, - u32 *index, - u32 *o_ipv4_address, - u16 *o_port, - u16 static_port_range, - cnat_user_db_entry_t *udb, - bulk_alloc_size_t bulk_size, - int *nfv9_log_req, - u16 ip_n_to_1, - u32 *rseed_ip); - -void cnat_update_bulk_range_cache(cnat_user_db_entry_t *udb, u16 o_port, - bulk_alloc_size_t bulk_size); - -void cnat_port_free_v2_bulk ( - cnat_portmap_v2_t *pm, - int index, - port_pair_t ptype, - u16 base_port, - cnat_user_db_entry_t *udb, - u16 static_port_range, - bulk_alloc_size_t bulk_size, - int *nfv9_log_req); - -cnat_errno_t cnat_static_port_alloc_v2_bulk ( - cnat_portmap_v2_t *pm, - port_alloc_t atype, - port_pair_t pair_type, - u32 i_ipv4_address, - u16 i_port, - u32 *index, - u32 *o_ipv4_address, - u16 *o_port, - u16 static_port_range, - cnat_user_db_entry_t *udb, - bulk_alloc_size_t bulk_size, - int *nfv9_log_req, - u16 ip_n_to_1 - ); - -cnat_errno_t cnat_dynamic_port_alloc_rtsp_bulk ( - cnat_portmap_v2_t *pm, - port_alloc_t atype, - port_pair_t pair_type, - u16 i_port, - u32 *index, - u32 *o_ipv4_address, - u16 *o_port, - u16 static_port_range, - cnat_user_db_entry_t *udb, - bulk_alloc_size_t bulk_size, - int *nfv9_log_req, - u32 *rseed_ip); - -cnat_errno_t -cnat_mapped_static_port_alloc_v2_bulk ( - cnat_portmap_v2_t *pm, - port_alloc_t atype, - u32 *index, - u32 ipv4_address, - u16 port, - cnat_user_db_entry_t *udb, - bulk_alloc_size_t bulk_size, - int *nfv9_log_req, - u16 ip_n_to_1 - ); - -#else /* NO_BULK_LOGGING */ -/* use older code */ -inline cnat_errno_t -cnat_dynamic_port_alloc_v2_bulk ( - cnat_vrfmap_t *vrf_map, - port_alloc_t atype, - port_pair_t pair_type, - u32 *index, - u32 *o_ipv4_address, - u16 *o_port, - u16 static_port_range, - u16 ip_n_to_1, - u32 *rseed_ip - ) -{ - return cnat_dynamic_port_alloc_v2(vrf_map->portmap_list, atype, - pair_type, index, o_ipv4_address, o_port, static_port_range, - ip_n_to_1, rseed_ip); -} - -inline void cnat_port_free_v2_bulk ( - cnat_portmap_v2_t *pm, - int index, - port_pair_t ptype, - u16 base_port, - cnat_user_db_entry_t *udb, - u16 static_port_range); -{ - return cnat_port_free_v2(pm, index, ptype, base_port, - static_port_range); -} - -inline cnat_errno_t cnat_static_port_alloc_v2_bulk ( - cnat_portmap_v2_t *pm, - port_alloc_t atype, - port_pair_t pair_type, - u32 i_ipv4_address, - u16 i_port, - u32 *index, - u32 *o_ipv4_address, - u16 *o_port, - u16 static_port_range) -{ - return cnat_static_port_alloc_v2 (pm, atype, pair_type, - i_ipv4_address, i_port, index, o_ipv4_address, o_port); -} - -inline cnat_errno_t -cnat_mapped_static_port_alloc_v2_bulk ( - cnat_portmap_v2_t *pm, - port_alloc_t atype, - u32 *index, - u32 ipv4_address, - u16 port) -{ - return cnat_mapped_static_port_alloc_v2(pm, atype, index - ipv4_address, port); -} - -#endif /* NO_BULK_LOGGING */ -#endif /* __CNAT_BULK_PORT_H__ */ diff --git a/plugins/plugins/vcgn/cnat_bulk_port_defs.h b/plugins/plugins/vcgn/cnat_bulk_port_defs.h deleted file mode 100644 index edb47b0a..00000000 --- a/plugins/plugins/vcgn/cnat_bulk_port_defs.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - *------------------------------------------------------------------ - * cnat_bulk_port_defs.h bulk port alloc definitions - * - * Copyright (c) 2011 Cisco and/or its affiliates. - * 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 __CNAT_BULK_PORT_DEFS_H__ -#define __CNAT_BULK_PORT_DEFS_H__ - - -#ifndef NO_BULK_LOGGING - -typedef enum { - BULK_ALLOC_SIZE_NONE = 1, - BULK_ALLOC_SIZE_16 = 16, - BULK_ALLOC_SIZE_32 = 32, - BULK_ALLOC_SIZE_64 = 64, - BULK_ALLOC_SIZE_128 = 128, - BULK_ALLOC_SIZE_256 = 256, - BULK_ALLOC_SIZE_512 = 512, - BULK_ALLOC_SIZE_1024 = 1024, - BULK_ALLOC_SIZE_2048 = 2048, - BULK_ALLOC_SIZE_4096 = 4096 -} bulk_alloc_size_t; - -/* #define DEBUG_BULK_PORT 1 TODO: remove this later */ - -#define CACHE_ALLOC_NO_LOG_REQUIRED -1 -#define BULK_ALLOC_NOT_ATTEMPTED -2 - -#define BULK_RANGE_INVALID 0xFFFF -#define BULK_RANGE_CACHE_SIZE 4 - -#define BULKSIZE_FROM_VRFMAP(vrfmap) ((vrfmap)->bulk_size) - -#define INIT_BULK_CACHE(udb) \ - { \ - int i; \ - for(i =0; i < BULK_RANGE_CACHE_SIZE; i++) \ - (udb)->bulk_port_range_cache[i] = (i16)BULK_RANGE_INVALID; \ - } - -#endif /* NO_BULK_LOGGING */ -#endif /* __CNAT_BULK_PORT_DEFS_H__ */ diff --git a/plugins/plugins/vcgn/cnat_cli.h b/plugins/plugins/vcgn/cnat_cli.h deleted file mode 100644 index e9d190a5..00000000 --- a/plugins/plugins/vcgn/cnat_cli.h +++ /dev/null @@ -1,206 +0,0 @@ -/* *------------------------------------------------------------------ - * cnat_cli.h - CLI definitions - * - * Copyright (c) 2007-2013 Cisco and/or its affiliates. - * 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 __CNAT_CLI_H__ -#define __CNAT_CLI_H__ - -#include "cnat_config_api.h" -#include "cnat_show_api.h" - -/* from iox cli error */ -typedef enum { - CNAT_SUCCESS = 0, - CNAT_NO_CONFIG, - CNAT_NO_VRF_RUN, - CNAT_NO_POOL_ANY, - CNAT_NO_PORT_ANY, -#ifndef NO_BULK_LOGGING - CNAT_NO_PORT_FROM_BULK, - CNAT_NO_PRE_ALLOCATED_BULK_PORTS, -#endif /* NO_BULK_LOGGING */ - CNAT_BAD_INUSE_ANY, - CNAT_NOT_FOUND_ANY, - CNAT_INV_PORT_DIRECT, - CNAT_DEL_PORT_DIRECT, - CNAT_BAD_INUSE_DIRECT, - CNAT_NOT_FOUND_DIRECT, - CNAT_OUT_LIMIT, - CNAT_MAIN_DB_LIMIT, - CNAT_USER_DB_LIMIT, - CNAT_NOT_STATIC_PORT, - CNAT_BAD_STATIC_PORT_REQ, - CNAT_NOT_THIS_CORE, - CNAT_ERR_PARSER, - CNAT_ERR_INVALID_MSG_ID, - CNAT_ERR_INVALID_MSG_SIZE, - CNAT_ERR_INVALID_PAYLOAD_SIZE, - CNAT_ERR_BAD_TCP_UDP_PORT, - CNAT_ERR_BULK_SINGLE_FAILURE, - CNAT_ERR_XLAT_ID_INVALID, - CNAT_ERR_XLAT_V6_PREFIX_INVALID, - CNAT_ERR_XLAT_V4_PREFIX_INVALID, - CNAT_ERR_XLAT_TCP_MSS_INVALID, - CNAT_ERR_6RD_ID_INVALID, - CNAT_ERR_6RD_V4_TUNNEL_SRC_INVALID, - CNAT_ERR_6RD_V6_PREFIX_INVALID, - CNAT_ERR_6RD_V6_BR_UNICAST_INVALID, - CNAT_ERR_6RD_V4_PREFIX_MASK_LEN_INVALID, - CNAT_ERR_6RD_V4_SUFFIX_MASK_LEN_INVALID, - CNAT_ERR_6RD_V4_COMBO_MASK_LEN_INVALID, - CNAT_ERR_6RD_TUNNEL_MTU_INVALID, - CNAT_ERR_6RD_TUNNEL_TTL_INVALID, - CNAT_ERR_6RD_TUNNEL_TOS_INVALID, - CNAT_ERR_NAT64_NO_VRF_RUN, - CNAT_ERR_NAT64_ID_INVALID, - CNAT_ERR_NAT64_V6_PREFIX_INVALID, - CNAT_ERR_NAT64_V4_PREFIX_INVALID, - CNAT_ERR_NAT64_TCP_MSS_INVALID, -#ifdef CGSE_DS_LITE - CNAT_ERR_DS_LITE_ID_INVALID, -#endif /* CGSE_DS_LITE */ - CNAT_ERR_NO_SESSION_DB, - CNAT_ERR_MAPE_ID_INVALID, - CNAT_ERR_MAX -} cnat_errno_t; - -#define CNAT_TRUE 1 -#define CNAT_FALSE 0 - - -#define CNAT_DEBUG_NONE (0) -#define CNAT_DEBUG_GLOBAL_ERR (1 << 0) -#define CNAT_DEBUG_DROP_TCP (1 << 0) -#define CNAT_DEBUG_DROP_UDP (1 << 1) -#define CNAT_DEBUG_DROP_ICMP (1 << 2) -#define CNAT_DEBUG_ERR_TCP (1 << 3) -#define CNAT_DEBUG_ERR_UDP (1 << 4) -#define CNAT_DEBUG_ERR_ICMP (1 << 5) -#define CNAT_DEBUG_ERR_ALG (1 << 6) -#define CNAT_DEBUG_GLOBAL_ALL (1 << 7) -#define CNAT_DEBUG_FTP_ALG (1 << 8) - - - -#define CNAT_DEBUG_ALL 0x1FF /*all of above*/ -#define CNAT_DEBUG_ERR_ALL 0x38 - -#define CNAT_DB_CLEAR_SPECIFIC (0) -#define CNAT_DB_CLEAR_ALL (1 << 0) -#define CNAT_DB_CLEAR_VRF (1 << 1) -#define CNAT_DB_CLEAR_ADDR (1 << 2) -#define CNAT_DB_CLEAR_PROTO (1 << 3) -#define CNAT_DB_CLEAR_PORT (1 << 4) - - -#define MAX_UIDX 0x3fff /*the max svi app uidb index */ -/* address mask per core */ -#define ADDR_MASK_PER_CORE PLATFORM_ADDR_MASK_PER_CORE -#define ADDR_MASK_PER_CORE_PER_PARTITION \ - PLATFORM_ADDR_MASK_PER_CORE_PER_PARTITION - -#define MAX_CORES PLATFORM_MAX_CORES -#define MAX_CORES_PER_PARTITION PLATFORM_MAX_CORES_PER_PARTITION - -/* - * Maximum pool size that is supported by platform - */ -#define CNAT_MAX_ADDR_POOL_SIZE PLATFORM_CNAT_MAX_ADDR_POOL_SIZE -#define CNAT_MAX_ADDR_POOL_SIZE_PER_CORE \ - (CNAT_MAX_ADDR_POOL_SIZE / MAX_CORES_PER_PARTITION) - -#define BOUNDARY_VALUE 256 - -#define BOUNDARY_VALUE_MASK 0xff - -#define NUM_ADDR_IN_RANGE(range, value, instance) \ - ((range / value) + ((instance % MAX_CORES_PER_PARTITION) < (range%value) ? 1 : 0)) - -typedef enum { - CNAT_DEBUG_FLAGS_DUMP = 0, - CNAT_DEBUG_FLAG_UDP_INSIDE_CHECKSUM_DISABLE, - CNAT_DEBUG_FLAG_UDP_OUTSIDE_CHECKSUM_DISABLE, - CNAT_DEBUG_FLAG_UDP_OUTSIDE_PKT_DUMP_ENABLE, - CNAT_DEBUG_FLAG_UDP_INSIDE_PKT_DUMP_ENABLE, - CNAT_DEBUG_FLAG_ICMP_PKT_DUMP_ENABLE, - CNAT_DEBUG_FLAG_FRAG_PKT_DUMP_ENABLE, - CNAT_DEBUG_FLAG_CONFIG_DEBUG_ENABLE, - CNAT_DEBUG_FLAG_GLOBAL_DEBUG_ALL_ENABLE, - CNAT_DEBUG_FLAG_SUMMARY_STATS_DEBUG_ENABLE, - CNAT_DEBUG_FLAG_SHOW_DEBUG_ENABLE, - CNAT_DEBUG_FLAG_XLAT_CONFIG_DEBUG_ENABLE, - CNAT_DEBUG_FLAG_XLAT_DATA_PATH_DEBUG_ENABLE, - CNAT_DEBUG_FLAG_TCP_LOGGING_ENABLE, - CNAT_DEBUG_FLAG_NFV9_LOGGING_DUMP_ENABLE, - CNAT_DEBUG_FLAG_SYSLOG_LOGGING_DUMP_ENABLE, - CNAT_DEBUG_SET_STATIC_PORT_RANGE, - CNAT_DEBUG_FLAG_V6RD_DATA_PATH_DEBUG_ENABLE, - CNAT_DEBUG_FLAG_V6RD_CONFIG_DEBUG_ENABLE, - CNAT_DEBUG_FLAG_V6RD_DEFRAG_DEBUG_ENABLE, - CNAT_DEBUG_FLAG_NAT64_CONFIG_DEBUG_ENABLE, - CNAT_DEBUG_FLAG_NAT64_DATA_PATH_DEBUG_ENABLE, - CNAT_DEBUG_FLAG_DSLITE_DP_ENABLE, - CNAT_DEBUG_FLAG_DSLITE_CONFIG_DEBUG_ENABLE, - CNAT_DEBUG_FLAG_CONFIG_PPTP_ENABLE = 24, - CNAT_DEBUG_FLAG_CONFIG_PCP_ENABLE = 25, - CNAT_DEBUG_FLAG_MAPE_CONFIG_DEBUG_ENABLE, - CNAT_DEBUG_FLAG_MAPE_DATA_PATH_DEBUG_ENABLE, - CNAT_DEBUG_FLAG_MAX, -} cnat_debug_variable_value; - -/* - * Don't use too small values for PATH MTU - */ -#define MIN_NFV9_PATH_MTU 100 - -extern u32 global_debug_flag; -extern u16 debug_i_vrf; -extern u32 debug_i_flag; -extern u32 debug_i_addr_start; -extern u32 debug_i_addr_end; -extern u16 debug_o_vrf; -extern u32 debug_o_flag; -extern u32 debug_o_addr_start; -extern u32 debug_o_addr_end; -extern u32 tcp_logging_enable_flag; -extern u32 nfv9_logging_debug_flag; - -extern u32 udp_inside_checksum_disable; -extern u32 udp_outside_checksum_disable; -extern u32 udp_inside_packet_dump_enable; -extern u32 udp_outside_packet_dump_enable; - -extern u32 icmp_debug_flag; -extern u32 frag_debug_flag; - -extern u32 summary_stats_debug_flag; - -extern u32 config_debug_level; -extern u32 show_debug_level; - - -/* CLI API prototypes called from vcgn_classify.c */ -extern void cnat_nat44_add_vrf_map_t_handler(spp_api_cnat_v4_add_vrf_map_t *mp, - vlib_main_t *vm); -extern void cnat_nat44_handle_show_stats(vlib_main_t *vm); -extern void cnat_nat44_handle_show_config(vlib_main_t *vm); -extern void cnat_nat44_set_protocol_timeout_value(u16 active, - u16 init, u8 *proto, u8 reset, vlib_main_t *vm); -extern void cnat_v4_show_inside_entry_req_t_handler -(spp_api_cnat_v4_show_inside_entry_req_t *mp, vlib_main_t *vm); - -#endif /* __CNAT_CLI_H__ */ diff --git a/plugins/plugins/vcgn/cnat_cli_handler.c b/plugins/plugins/vcgn/cnat_cli_handler.c deleted file mode 100644 index a4010349..00000000 --- a/plugins/plugins/vcgn/cnat_cli_handler.c +++ /dev/null @@ -1,961 +0,0 @@ -/* *------------------------------------------------------------------ - * cnat_cli_handler.c - CLI handler definitions - * - * Copyright (c) 2007-2015 Cisco and/or its affiliates. - * 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 -#include -#include -#include -#include -#include -#include -#include - -#include "cnat_db.h" -#include "cnat_config.h" -#include "cnat_global.h" -#include "cnat_cli.h" -#include "cnat_logging.h" -#include "cnat_syslog.h" -#include "cnat_config_api.h" -#include "cnat_show_api.h" -#include "cnat_show_response.h" - -#include - -#if DPDK -#include -#endif - -u32 show_debug_level = 0; - -u32 -cnat_get_vrfmap_nfv9_logging_index (u32 i_vrf_id) -{ - cnat_nfv9_logging_info_t *my_nfv9_logging_info = 0; - u32 logging_index = EMPTY; - - /* - * Start with global logging index if available - */ - if (cnat_nfv9_global_info.cnat_nfv9_init_done) { - logging_index = cnat_nfv9_global_info.cnat_nfv9_global_collector_index; - - pool_foreach (my_nfv9_logging_info, cnat_nfv9_logging_info_pool, ({ - if (my_nfv9_logging_info->i_vrf_id == i_vrf_id) { - logging_index = my_nfv9_logging_info - - cnat_nfv9_logging_info_pool; - break; - } - })); - } - return (logging_index); -} - -u32 -cnat_get_vrfmap_syslog_logging_index (u32 i_vrf_id) -{ - cnat_syslog_logging_info_t *my_syslog_info = NULL; - u32 logging_index = EMPTY; - - /* - * Start with global logging index if available - */ - if(PREDICT_TRUE(cnat_syslog_global_info.cnat_syslog_init_done)) { - - pool_foreach (my_syslog_info, cnat_syslog_logging_info_pool, ({ - if (my_syslog_info->i_vrf_id == i_vrf_id) { - logging_index = my_syslog_info - - cnat_syslog_logging_info_pool; - break; - } - })); - } - return (logging_index); -} - -void -cnat_set_vrf_params_with_default(cnat_vrfmap_t *my_vrfmap, u32 i_vrf, u32 i_vrf_id) -{ - - my_vrfmap->status = S_WAO; - - my_vrfmap->i_vrf = i_vrf; - my_vrfmap->i_vrf_id = i_vrf_id; - - my_vrfmap->o_vrf = INVALID_UIDX; - my_vrfmap->o_vrf_id = INVALID_VRFID; - -#ifndef NO_BULK_LOGGING - BULKSIZE_FROM_VRFMAP(my_vrfmap) = BULK_ALLOC_SIZE_NONE; -#endif /* #ifndef NO_BULK_LOGGING */ - my_vrfmap->tcp_mss = V4_TCP_MSS_NOT_CONFIGURED_VALUE; - my_vrfmap->frag_tout = CNAT_IPV4_FRAG_TIMEOUT_DEF; - my_vrfmap->port_limit = V4_DEF_VRF_MAX_PORTS; - my_vrfmap->nfv9_logging_index = - cnat_get_vrfmap_nfv9_logging_index(i_vrf_id); - my_vrfmap->syslog_logging_index = - cnat_get_vrfmap_syslog_logging_index(i_vrf_id); - - /* Copy logging policy from nfv9 info. */ - if(my_vrfmap->nfv9_logging_index != EMPTY) { - cnat_nfv9_logging_info_t *nfv9_logging_info = - cnat_nfv9_logging_info_pool + my_vrfmap->nfv9_logging_index; - my_vrfmap->nf_logging_policy = nfv9_logging_info->logging_policy; - } - if(my_vrfmap->syslog_logging_index != EMPTY) { - cnat_syslog_logging_info_t *syslog_logging_info = - cnat_syslog_logging_info_pool + my_vrfmap->syslog_logging_index; - my_vrfmap->syslog_logging_policy = syslog_logging_info->logging_policy; - } - #if 0 - printf("Initializing params in cnat_set_vrf_params_with_default\n" - "my_vrfmap->status = %u\n" - "my_vrfmap->tcp_mss = %u\n" - "my_vrfmap->i_vrf = %u\n" - "my_vrfmap->i_vrf_id = %u\n" - "my_vrfmap->o_vrf = %u\n" - "my_vrfmap->o_vrf_id = %u\n" - "my_vrfmap->bulk_size = %u\n" - "my_vrfmap->nfv9_logging_index = %u\n" - "my_vrfmap->syslog_logging_index = %u\n" - "my_vrfmap->frag_tout = %u\n" - "my_vrfmap->port_limit = %u\n" - "my_vrfmap->nf_logging_policy = %u\n" - "my_vrfmap->syslog_logging_policy = %u\n", - my_vrfmap->status, - my_vrfmap->tcp_mss, - my_vrfmap->i_vrf, - my_vrfmap->i_vrf_id, - my_vrfmap->o_vrf, - my_vrfmap->o_vrf_id, - my_vrfmap->bulk_size, - my_vrfmap->nfv9_logging_index, - my_vrfmap->syslog_logging_index, - my_vrfmap->frag_tout, - my_vrfmap->port_limit, - my_vrfmap->nf_logging_policy, - my_vrfmap->syslog_logging_policy); - #endif /* if 0 */ -} - -/* config command handlers */ -void cnat_nat44_add_vrf_map_t_handler(spp_api_cnat_v4_add_vrf_map_t *mp, - vlib_main_t *vm) -{ - void cnat_table_entry_fill_map(u32 start_addr, u32 end_addr, - cnat_portmap_v2_t **port_map_holder); - u32 start_addr, end_addr; - u32 pm_len __attribute__((unused)); - cnat_vrfmap_t *my_vrfmap = 0; - cnat_portmap_v2_t *pm = 0; - u16 i_vrf, o_vrf; - u32 ivrf_id, ovrf_id; - u16 my_vrfmap_index; - u8 i = 0; - - start_addr = mp->start_addr[0]; - end_addr = mp->end_addr[0]; - i_vrf = mp->i_vrf; - o_vrf = mp->o_vrf; - ovrf_id = mp->o_vrf_id; - ivrf_id = mp->i_vrf_id; - -#if DEBUG_NOT_COMMENTED - vlib_cli_output(vm, "%s: saddr[0x%x], eaddr[0x%x], i_vrf[0x%x], o_vrf[0x%x], " - "ovrf_id[0x%x], ivrf_id[0x%x]\n", __func__, start_addr, end_addr, - i_vrf, o_vrf, ovrf_id, ivrf_id); -#endif - if (start_addr > end_addr) { - vlib_cli_output(vm, "Add VRF Map failed start addr 0x%x > end addr 0x%x\n", - start_addr, end_addr); - return; - } - if ((end_addr - start_addr) > CNAT_MAX_ADDR_POOL_SIZE) { - vlib_cli_output(vm, "Add VRF Map failed start addr 0x%x - end addr " - "0x%x range > 65536\n", start_addr, end_addr); - return; - } - my_vrfmap_index = vrf_map_array[i_vrf]; - - if (my_vrfmap_index != VRF_MAP_ENTRY_EMPTY) { - - my_vrfmap = cnat_map_by_vrf + my_vrfmap_index; - - my_vrfmap->o_vrf = o_vrf; - my_vrfmap->i_vrf_id = ivrf_id; - my_vrfmap->o_vrf_id = ovrf_id; - } else { - /* - * first time add - */ - pool_get(cnat_map_by_vrf, my_vrfmap); - memset(my_vrfmap, 0, sizeof(*my_vrfmap)); - /* waiting for outside vrf */ - cnat_set_vrf_params_with_default(my_vrfmap, i_vrf, ivrf_id); - my_vrfmap->i_vrf = i_vrf; - my_vrfmap->o_vrf = o_vrf; - my_vrfmap->i_vrf_id = ivrf_id; - my_vrfmap->o_vrf_id = ovrf_id; -#ifndef NO_BULK_LOGGING - BULKSIZE_FROM_VRFMAP(my_vrfmap) = BULK_ALLOC_SIZE_NONE; -#endif /* #ifndef NO_BULK_LOGGING */ - - my_vrfmap->tcp_mss = V4_TCP_MSS_NOT_CONFIGURED_VALUE; - my_vrfmap->status = S_WA; - my_vrfmap->frag_tout = 0; /* currently setting it to 0 */ - my_vrfmap->port_limit = V4_DEF_VRF_MAX_PORTS; - vrf_map_array[i_vrf] = (my_vrfmap - cnat_map_by_vrf); - } - pm = my_vrfmap->portmap_list; - pm_len = vec_len(pm); - for(i=0; i < 1 ; i++) { - start_addr = mp->start_addr[i]; - end_addr = mp->end_addr[i]; - if((start_addr == 0) || (end_addr == 0)) - break; - - cnat_table_entry_fill_map(start_addr, end_addr, - &(my_vrfmap->portmap_list)); - } - my_vrfmap->status = S_RUN; - vlib_cli_output(vm, "Address Pool Config Successful !!\n"); - return; -} - -void cnat_nat44_set_protocol_timeout_value(u16 active, - u16 init, u8 *proto, u8 reset, vlib_main_t *vm) -{ - if (!strncmp((char *) proto, "tcp", 3)) { - tcp_initial_setup_timeout = (reset) ? V4_DEF_TCP_IS_TO : init; - tcp_active_timeout = (reset) ? V4_DEF_TCP_AS_TO : active; - - } else if (!strncmp((char *) proto, "udp", 3)) { - udp_init_session_timeout = (reset) ? V4_DEF_UDP_IS_TO : init; - udp_act_session_timeout = (reset) ? V4_DEF_UDP_AS_TO : active; - - } else if (!strncmp((char *) proto, "icmp", 4)) { - icmp_session_timeout = (reset) ? V4_DEF_ICMP_S_TO : active; - - } else { - vlib_cli_output(vm, "Error !! Unsupported protocol %s\n", proto); - } - return; -} - - - - -/* Show command handlers */ -void cnat_nat44_handle_show_stats(vlib_main_t *vm) -{ - pool_header_t *h; - u32 used, free; - cnat_vrfmap_t *my_vrfmap =0; - cnat_portmap_v2_t *pm =0, *my_pm = 0; - u32 i, pm_len; - struct in_addr ip; - void cnat_nfv9_show_collector - (vlib_main_t *vm, cnat_nfv9_logging_info_t *my_nfv9_logging_info); - - /* active translations */ - h = pool_header(cnat_main_db); - free = vec_len(h->free_indices); - used = vec_len(cnat_main_db) - free; - - vlib_cli_output(vm, "vCGN NAT44 Statistics :\n"); - vlib_cli_output(vm, "\tActive Translations : %u\n", - NAT44_COMMON_STATS.active_translations); - vlib_cli_output(vm, "\tTotal free translation entries : %u\n", free); - vlib_cli_output(vm, "\tTotal used translation entries : %u\n", used); - vlib_cli_output(vm, "\ti2o drops due to port limit exceeded : %lu\n", - in2out_drops_port_limit_exceeded); - vlib_cli_output(vm, "\ti2o drops due to system limit reached : %lu\n", - in2out_drops_system_limit_reached); - vlib_cli_output(vm, "\ti2o drops due to resource depletion : %lu\n", - in2out_drops_resource_depletion); - vlib_cli_output(vm, "\to2i drops due to no translations : %lu\n", - NAT44_COMMON_STATS.no_translation_entry_drops); - - vlib_cli_output(vm, "\tPool address usage:\n"); - vlib_cli_output(vm, "\t-------------------------------------------------\n"); - vlib_cli_output(vm, "\tExternal Address \tPorts Used\n"); - vlib_cli_output(vm, "\t-------------------------------------------------\n"); - - used = 0; - pool_foreach (my_vrfmap, cnat_map_by_vrf, ({ - pm = my_vrfmap->portmap_list; - pm_len = vec_len(pm); - for (i = 0; i < pm_len; i++) { - my_pm = pm + i; - if (my_pm->inuse) { - used++; - /* maximum of 200 addresses to be returned */ - if (used <= 200) { - ip.s_addr = ntohl(my_pm->ipv4_address); - vlib_cli_output(vm, "\t%s \t\t%u\n", inet_ntoa(ip), my_pm->inuse); - } - } - } - })); - return; -} - -void cnat_nat44_handle_show_config(vlib_main_t *vm) -{ - cnat_vrfmap_t * my_vrfmap; - cnat_portmap_v2_t *pm = 0; - cnat_portmap_v2_t *my_pm = 0; - u32 pm_len; - struct in_addr ip_addr; - u8 status_str[20]; - cnat_nfv9_logging_info_t *my_nfv9_logging_info, - *global_nfv9_logging_info = 0; - - vnet_hw_interface_t * hw; - vnet_main_t * vnm = vnet_get_main(); - - void cnat_nfv9_show_collector - (vlib_main_t *vm, cnat_nfv9_logging_info_t *my_nfv9_logging_info); - - vlib_cli_output(vm, "vCGN NAT44 Config:\n"); - vlib_cli_output(vm, "\tPort Limit : %u\n", cnat_main_db_max_ports_per_user); - vlib_cli_output(vm, "\ttotal address pool : %u\n", total_address_pool_allocated); - vlib_cli_output(vm, "\tdynamic port start range : %u\n", cnat_static_port_range); - - pool_foreach(my_vrfmap, cnat_map_by_vrf, ({ - hw = vnet_get_hw_interface (vnm, my_vrfmap->i_vrf); - vlib_cli_output(vm, "\tInside Interface : %v\n", hw->name); - hw = vnet_get_hw_interface (vnm, my_vrfmap->o_vrf); - vlib_cli_output(vm, "\tOutside Interface : %v\n", hw->name); - - memset(status_str, 0x00, sizeof(status_str)); - switch(my_vrfmap->status) { - case S_WAO: clib_memcpy(status_str, "S_WAO", 5); break; - case S_WA: clib_memcpy(status_str, "S_WA", 4); break; - case S_WO: clib_memcpy(status_str, "S_WO", 4); break; - case S_RUN: clib_memcpy(status_str, "ONLINE", 6); break; - case S_DEL: clib_memcpy(status_str, "S_DEL", 5); break; - default: clib_memcpy(status_str, "Invalid state", 13); - - } - vlib_cli_output(vm, - "\tAddress pool map table status : %s\n", status_str); - - pm = my_vrfmap->portmap_list; - pm_len = vec_len(pm); - my_pm = pm; - ip_addr.s_addr = clib_net_to_host_u32(my_pm->ipv4_address); - vlib_cli_output(vm, - "\tStart Address : %s\n", inet_ntoa(ip_addr)); - my_pm = pm + (pm_len - 1); - ip_addr.s_addr = clib_net_to_host_u32(my_pm->ipv4_address); - vlib_cli_output(vm, - "\tEnd Address : %s\n", inet_ntoa(ip_addr)); - - })); - vlib_cli_output(vm, - "\ttcp init timeout : %u sec\n", tcp_initial_setup_timeout); - vlib_cli_output(vm, - "\ttcp active timeout : %u sec\n", tcp_active_timeout); - vlib_cli_output(vm, - "\tudp init timeout : %u sec\n", udp_init_session_timeout); - vlib_cli_output(vm, - "\tudp active timeout : %u sec\n", udp_act_session_timeout); - vlib_cli_output(vm, - "\ticmp session timeout: %u sec\n", icmp_session_timeout); - -#if 0 - if (cnat_nfv9_global_info.cnat_nfv9_global_collector_index != EMPTY) { - vlib_cli_output(vm,"\nGloabal NFV9 Collector :"); - global_nfv9_logging_info = cnat_nfv9_logging_info_pool + - cnat_nfv9_global_info.cnat_nfv9_global_collector_index; - cnat_nfv9_show_collector(vm, global_nfv9_logging_info); - } -#endif - - vlib_cli_output(vm, "\nNFV9 Collector :"); - if (cnat_nfv9_logging_info_pool !=NULL) { - pool_foreach (my_nfv9_logging_info, cnat_nfv9_logging_info_pool, ({ - if (my_nfv9_logging_info != global_nfv9_logging_info) { - cnat_nfv9_show_collector(vm, my_nfv9_logging_info); - vlib_cli_output(vm, "\n"); - } - })); - } else { - vlib_cli_output(vm, "\n"); - } - - return; -} - -/* - * Check if the request flag matches the entry flags and - * if so return "1" - * - * entry_flag_ptr is an output parameter - it returns the flags - * corresponding to the translation entry - */ -static u8 cnat_v4_show_verify_display_entry ( - u16 request_flag, - cnat_main_db_entry_t *db, - u16 *entry_flag_ptr) -{ - u8 display_entry = 0; - - /* - * This should never happen - */ - if (!entry_flag_ptr) { - return (display_entry); - } - - *entry_flag_ptr = 0; - - if ((db->flags & CNAT_DB_FLAG_STATIC_PORT) - &&(db->flags & CNAT_DB_FLAG_ALG_ENTRY)) { - *entry_flag_ptr |= CNAT_TRANSLATION_ENTRY_STATIC; - *entry_flag_ptr |= CNAT_TRANSLATION_ENTRY_ALG; - } else if (db->flags & CNAT_DB_FLAG_STATIC_PORT) { - *entry_flag_ptr |= CNAT_TRANSLATION_ENTRY_STATIC; - } else if ((db->flags & CNAT_DB_FLAG_ALG_ENTRY) || - (db->flags & CNAT_DB_FLAG_PPTP_GRE_ENTRY)) { - *entry_flag_ptr |= CNAT_TRANSLATION_ENTRY_ALG; - } else if (db->flags & CNAT_DB_FLAG_PCPI) { - *entry_flag_ptr |= CNAT_TRANSLATION_ENTRY_PCPI_DYNAMIC; - } else if (db->flags & CNAT_DB_FLAG_PCPE) { - *entry_flag_ptr |= CNAT_TRANSLATION_ENTRY_PCPE_DYNAMIC; - } else { - *entry_flag_ptr |= CNAT_TRANSLATION_ENTRY_DYNAMIC; - } - - if (request_flag == CNAT_TRANSLATION_ENTRY_ALL) { - display_entry = 1; - } else { - /* - * Check if the request_flag is STATIC or ALG - * and the entry is STATIC or ALG as well - */ - if ((request_flag & CNAT_TRANSLATION_ENTRY_STATIC) && - (*entry_flag_ptr & CNAT_TRANSLATION_ENTRY_STATIC)) { - display_entry = 1; - } - - if ((request_flag & CNAT_TRANSLATION_ENTRY_ALG) && - (*entry_flag_ptr & CNAT_TRANSLATION_ENTRY_ALG)) { - display_entry = 1; - } - - if ((request_flag & CNAT_TRANSLATION_ENTRY_PCPI_DYNAMIC) && - (*entry_flag_ptr & CNAT_TRANSLATION_ENTRY_PCPI_DYNAMIC)) { - display_entry = 1; - } - - if ((request_flag & CNAT_TRANSLATION_ENTRY_PCPE_DYNAMIC) && - (*entry_flag_ptr & CNAT_TRANSLATION_ENTRY_PCPE_DYNAMIC)) { - display_entry = 1; - } - - /* - * For dynamic entry case, check if flags field is 0 - */ - if ((request_flag & CNAT_TRANSLATION_ENTRY_DYNAMIC) && - (*entry_flag_ptr & CNAT_TRANSLATION_ENTRY_DYNAMIC)) { - display_entry = 1; - } - } - - if (PREDICT_FALSE(show_debug_level > 2)) { - PLATFORM_DEBUG_PRINT("Entry (0x%x, %d) -> (0x%x, %d) request_flag 0x%x, entry_flag 0x%x, display_entry %d\n", db->in2out_key.k.ipv4, db->in2out_key.k.port, db->out2in_key.k.ipv4, db->out2in_key.k.port, request_flag, *entry_flag_ptr, display_entry); - } - - return (display_entry); -} -void cnat_v4_show_inside_entry_req_t_handler -(spp_api_cnat_v4_show_inside_entry_req_t *mp, vlib_main_t * vm) -{ - cnat_user_db_entry_t *udb = NULL; - cnat_main_db_entry_t *db = NULL; - cnat_db_key_bucket_t u_ki, ki; - u64 a, b, c; - u32 index; - u16 start_port, end_port, port; - u16 request_flag = 0; - u16 entry_flag = 0; - u8 num_entries = 0; - u8 proto, all; - u8 done = 0; - cnat_v4_show_translation_entry *entry_list; - cnat_v4_show_translation_entry entry[PLATFORM_MAX_TRANSLATION_ENTRIES]; - u8 display_entry; - u8 flag_str[11]; - vnet_hw_interface_t * hw; - vnet_main_t * vnm = vnet_get_main(); - - ki.k.k.ipv4 = mp->ipv4_addr; - ki.k.k.vrf = mp->vrf_id; - start_port = mp->start_port; - end_port = mp->end_port; -#if DEBUG - vlib_cli_output(vm, "## proto %d, inside-addr 0x%x, start_port %u, " - "end_port %u, vrf 0x%x, flag 0x%x\n", - mp->protocol, - mp->ipv4_addr, - mp->start_port, - mp->end_port, - mp->vrf_id, - mp->flags); -#endif - - proto = mp->protocol; - ki.k.k.vrf |= ((u16)proto << CNAT_PRO_SHIFT); - - all = mp->all_entries; /* for no port range case */ - request_flag = mp->flags; /* for all, alg, static entries case */ - entry_list = entry; - - /* - * check if the address is belonging to this core - */ - - - /* - * first we check if the user exists in the udb, if he is not then - * it does not make sense to check the main db for translations - */ - u_ki.k.k.vrf = ki.k.k.vrf & CNAT_VRF_MASK; - u_ki.k.k.ipv4 = ki.k.k.ipv4; - u_ki.k.k.port = 0; - - if (PREDICT_FALSE(show_debug_level > 0)) { - vlib_cli_output(vm, "\nI_TRANS_CORE %d: IPv4 0x%x, VRF 0x%x, " - "start_port %d, end_port %d", - my_instance_number, ki.k.k.ipv4, - ki.k.k.vrf, start_port, end_port); - } - - udb = cnat_user_db_lookup_entry(&u_ki); - if (!udb) { - if (PREDICT_FALSE(show_debug_level > 0)) { - vlib_cli_output(vm, "\nReturning %d entries", - num_entries); - } - return; - } - - if (all) { - #if 0 - if (PREDICT_FALSE(show_debug_level > 0)) { - PLATFORM_DEBUG_PRINT("\nI_TRANS: Printing ALL\n"); - } - - /* - * get the head of list of translation entries for that user - * from the user db - */ - head = udb->translation_list_head_index; - db = cnat_main_db + head; - - while (num_entries < PLATFORM_MAX_TRANSLATION_ENTRIES) { - - if (((db->in2out_key.k.vrf & CNAT_PRO_MASK) >> CNAT_PRO_SHIFT) - != proto) { - goto next_entry; - } - - display_entry = - spp_api_cnat_v4_show_verify_display_entry(request_flag, db, - &entry_flag); - - if (display_entry) { - entry_list->ipv4_addr = - spp_host_to_net_byte_order_32(db->out2in_key.k.ipv4); - entry_list->cnat_port = - spp_host_to_net_byte_order_16(db->out2in_key.k.port); - entry_list->src_port = - spp_host_to_net_byte_order_16(db->in2out_key.k.port); - - entry_list->protocol = proto; - - /* incase of gre - in2out is not accounted */ - if(proto != CNAT_PPTP) { - - entry_list->in2out_packets = - spp_host_to_net_byte_order_32(db->in2out_pkts); - } else { - entry_list->in2out_packets = 0; - } - entry_list->out2in_packets = - spp_host_to_net_byte_order_32(db->out2in_pkts); - - entry_list->flags = - spp_host_to_net_byte_order_16(entry_flag); - - num_entries++; - entry_list = entry_list + 1; - } -next_entry: - db = cnat_main_db + db->user_ports.next; - /* - * its a circular list, so if we have reached the head again - * all the entries for that user have been read - */ - if (db == (cnat_main_db + head)) { - break; - } - } - resp->num_entries = num_entries; - #endif /* if 0 */ - } else { - if (PREDICT_FALSE(show_debug_level > 0)) { - vlib_cli_output(vm, "\nI_TRANS: Printing range %d .. %d\n", - start_port, end_port); - } - /* - * port range is specified so for each port calculate the hash and - * check if the entry is present in main db - */ - port = start_port; - done = 0; - while ((!done) && (num_entries < PLATFORM_MAX_TRANSLATION_ENTRIES)) { - - ki.k.k.port = port; - if (port >= end_port) { - done = 1; - } else { - port++; - } - CNAT_V4_GET_HASH(ki.k.key64, - ki.bucket, - CNAT_MAIN_HASH_MASK); - index = cnat_in2out_hash[ki.bucket].next; - if (PREDICT_TRUE(index == EMPTY)) { - continue; - } - - do { - db = cnat_main_db + index; - if (db->in2out_key.key64 == ki.k.key64) { - break; - } - index = db->in2out_hash.next; - } while (index != EMPTY); - - if (index == EMPTY) { - continue; - } else { - - display_entry = - cnat_v4_show_verify_display_entry(request_flag, db, - &entry_flag); - if (display_entry) { - - entry_list->ipv4_addr = - clib_host_to_net_u32(db->out2in_key.k.ipv4); - entry_list->cnat_port = - clib_host_to_net_u16(db->out2in_key.k.port); - entry_list->src_port = - clib_host_to_net_u16(db->in2out_key.k.port); - - entry_list->protocol = proto; - entry_list->nsessions = db->nsessions; - entry_list->flags = ((db->flags & CNAT_DB_FLAG_TCP_ACTIVE) || - (db->flags & CNAT_DB_FLAG_UDP_ACTIVE)) ? 1:0; - /* incase of gre - in2out is not accounted */ - if(proto != CNAT_PPTP) { - entry_list->in2out_packets = - clib_host_to_net_u32(db->in2out_pkts); - } else { - entry_list->in2out_packets = 0; - } - - entry_list->out2in_packets = - clib_host_to_net_u32(db->out2in_pkts); - - if (PREDICT_FALSE(show_debug_level > 3)) { - vlib_cli_output(vm, "\n1. Entry: Addr 0x%x, port %d, num_entries %d", - clib_net_to_host_u32(entry_list->ipv4_addr), - clib_net_to_host_u16(entry_list->cnat_port), - num_entries); - } - - entry_list = entry_list + 1; - num_entries++; - } - } /* if (index == EMPTY) */ - } /* while() */ - } - - if (PREDICT_FALSE(show_debug_level > 0)) { - if (num_entries) { - vlib_cli_output(vm, "\nReturning %d entries\n", - num_entries); - } - } - - entry_list = entry; - u8 i = 0; - struct in_addr ip; - u8 proto_str[10]; - u8 transl_str[10]; - memset(proto_str, 0x00, 10); - memset(transl_str, 0x00, 10); - - if (proto == 1) strncpy((char *)proto_str, "udp", 3); - else if (proto == 2) strncpy((char *)proto_str, "tcp", 3); - else if (proto == 3) strncpy((char *)proto_str, "icmp", 4); - else strncpy((char *)proto_str, "unknown", 7); - - if (request_flag == 0x04) strncpy((char *)transl_str, "Dynamic", 7); - else strncpy((char *)transl_str, "Unknown", 7); /* currently we are not supporting static/alg entries */ - - ip.s_addr = clib_net_to_host_u32(u_ki.k.k.ipv4); - hw = vnet_get_hw_interface (vnm, u_ki.k.k.vrf); - - vlib_cli_output (vm, "Inside-translation details\n"); - vlib_cli_output (vm, "--------------------------\n"); - - vlib_cli_output (vm, "Inside interface : %s\n", hw->name); - vlib_cli_output (vm, "Inside address : %s\n", inet_ntoa(ip)); - vlib_cli_output (vm, "Start port : %u\n", start_port); - vlib_cli_output (vm, "End port : %u\n", end_port); - - vlib_cli_output (vm, "--------------------------------------------------------------------------------------" - "-----------------------\n"); - vlib_cli_output (vm, "Outside Protocol Inside Outside Translation" - " I2O O2I Flag Num\n"); - vlib_cli_output (vm, "Address Src Port Src Port Type " - " Pkts Pkts Sessions\n"); - vlib_cli_output (vm, "--------------------------------------------------------------------------------------" - "-----------------------\n"); - - while ((num_entries) && (entry_list) && (i < 50)) { - - ip.s_addr = entry_list->ipv4_addr; - memset(flag_str,0x00,11); - if((proto == 1) || (proto == 2)) { - if(entry_list->flags == 1) { - strncpy((char *)flag_str,"Active",6); - } - else { - strncpy((char *) flag_str,"Non Active",10); - } - } else { - strncpy((char *) flag_str, "NA", 2); - } - vlib_cli_output(vm, "%s %10s %11u %12u %13s %10u %10u %14s %6u\n", - inet_ntoa(ip), proto_str, - clib_net_to_host_u16(entry_list->src_port), - clib_net_to_host_u16(entry_list->cnat_port), - transl_str, - clib_net_to_host_u32(entry_list->in2out_packets), - clib_net_to_host_u32(entry_list->out2in_packets), - flag_str, - entry_list->nsessions); - entry_list++; - num_entries--; i++; - } - - return; -} - -void cnat_v4_show_outside_entry_req_t_handler -(spp_api_cnat_v4_show_outside_entry_req_t *mp, vlib_main_t *vm) -{ - cnat_main_db_entry_t *db = NULL; - cnat_db_key_bucket_t ko; - u64 a, b, c; - u32 index; - u16 start_port, end_port, port; - u16 request_flag = 0; - u16 entry_flag = 0; - u8 num_entries = 0; - u8 proto; - cnat_v4_show_translation_entry *entry_list; - cnat_v4_show_translation_entry entry[PLATFORM_MAX_TRANSLATION_ENTRIES]; - u8 done = 0; - u8 display_entry; - u8 flag_str[11]; - vnet_hw_interface_t * hw; - vnet_main_t * vnm = vnet_get_main(); - - ko.k.k.ipv4 = mp->ipv4_addr; - ko.k.k.vrf = mp->vrf_id; - start_port = mp->start_port; - end_port = mp->end_port; - - proto = mp->protocol; - request_flag = mp->flags; - - ko.k.k.vrf |= ((u16)proto << CNAT_PRO_SHIFT); - - entry_list = entry; - - if (PREDICT_FALSE(show_debug_level > 0)) { - vlib_cli_output(vm, "\nO_TRANS_CORE %d: IPv4 0x%x, VRF 0x%x, " - "start_port %d, end_port %d", my_instance_number, - ko.k.k.ipv4, ko.k.k.vrf, start_port, end_port); - } - - /* - * for each ip and port combination we need to scan the main db - * and check if the entry is present in main db - */ - port = start_port; - done = 0; - while ((!done) && (num_entries < PLATFORM_MAX_TRANSLATION_ENTRIES)) { - ko.k.k.port = port; - - /* - * If we have reached the end_port, we are DONE - */ - if (port >= end_port) { - done = 1; - } else { - port++; - } - - CNAT_V4_GET_HASH(ko.k.key64, - ko.bucket, - CNAT_MAIN_HASH_MASK); - - index = cnat_out2in_hash[ko.bucket].next; - if (PREDICT_TRUE(index == EMPTY)) { - continue; - } - - do { - db = cnat_main_db + index; - if (db->out2in_key.key64 == ko.k.key64) { - break; - } - index = db->out2in_hash.next; - } while (index != EMPTY); - - if (index == EMPTY) { - continue; - } else { - display_entry = - cnat_v4_show_verify_display_entry(request_flag, db, - &entry_flag); - - if (display_entry) { - entry_list->ipv4_addr = - clib_host_to_net_u32(db->in2out_key.k.ipv4); - entry_list->cnat_port = - clib_host_to_net_u16(db->out2in_key.k.port); - entry_list->src_port = - clib_host_to_net_u16(db->in2out_key.k.port); - entry_list->protocol = proto; - entry_list->nsessions = db->nsessions; - entry_list->flags = ((db->flags & CNAT_DB_FLAG_TCP_ACTIVE) || - (db->flags & CNAT_DB_FLAG_UDP_ACTIVE)) ? 1:0; - /* incase of gre - in2out is not accounted */ - if(proto != CNAT_PPTP) { - entry_list->in2out_packets = - clib_host_to_net_u32(db->in2out_pkts); - } else { - entry_list->in2out_packets = 0 ; - } - entry_list->out2in_packets = - clib_host_to_net_u32(db->out2in_pkts); - #if 0 - entry_list->flags = - clib_host_to_net_u16(entry_flag); - #endif - entry_list = entry_list + 1; - num_entries++; - } - } - } - - if (num_entries == 0) { - /* No point proceeding further */ - return; - } - - if (PREDICT_FALSE(show_debug_level > 0)) { - if (num_entries) { - vlib_cli_output(vm, "\nO_TRANS: Core %d returning %d entries", - num_entries); - } - } - - entry_list = entry; - u8 i = 0; - struct in_addr ip; - u8 proto_str[10]; - u8 transl_str[10]; - memset(proto_str, 0x00, 10); - memset(transl_str, 0x00, 10); - - if (proto == 1) strncpy((char *) proto_str, "udp", 3); - else if (proto == 2) strncpy((char *) proto_str, "tcp", 3); - else if (proto == 3) strncpy((char *) proto_str, "icmp", 4); - else strncpy((char *) proto_str, "unknown", 7); - - if (request_flag == 0x04) strncpy((char *) transl_str, "Dynamic", 7); - else strncpy((char *)transl_str, "Unknown", 7); /* currently we are not supporting static/alg entries */ - - ip.s_addr = clib_net_to_host_u32(ko.k.k.ipv4); - hw = vnet_get_hw_interface (vnm, (ko.k.k.vrf & CNAT_VRF_MASK)); - - vlib_cli_output (vm, "Outside-translation details\n"); - vlib_cli_output (vm, "--------------------------\n"); - - vlib_cli_output (vm, "Outside interface : %s\n", hw->name); - vlib_cli_output (vm, "Outside address : %s\n", inet_ntoa(ip)); - vlib_cli_output (vm, "Start port : %u\n", start_port); - vlib_cli_output (vm, "End port : %u\n", end_port); - - vlib_cli_output (vm, "--------------------------------------------------------------------------------------" - "-----------------------\n"); - vlib_cli_output (vm, "Inside Protocol Outside Inside Translation" - " I2O O2I Flag Num\n"); - vlib_cli_output (vm, "Address Dst Port Dst Port Type " - " Pkts Pkts Sessions\n"); - vlib_cli_output (vm, "--------------------------------------------------------------------------------------" - "-----------------------\n"); - - while ((num_entries) && (entry_list) && (i < 50)) { - ip.s_addr = entry_list->ipv4_addr; - memset(flag_str,0x00,11); - if((proto == 1) || (proto == 2)) { - if(entry_list->flags == 1) { - strncpy((char *) flag_str,"Active",6); - } - else { - strncpy((char *) flag_str,"Non Active",10); - } - } else { - strncpy((char *) flag_str, "NA", 2); - } - vlib_cli_output(vm, "%s %10s %11u %12u %13s %10u %10u %14s %6u\n", - inet_ntoa(ip), proto_str, - clib_net_to_host_u16(entry_list->cnat_port), - clib_net_to_host_u16(entry_list->src_port), - transl_str, - clib_net_to_host_u32(entry_list->in2out_packets), - clib_net_to_host_u32(entry_list->out2in_packets), - flag_str, - entry_list->nsessions); - entry_list++; - num_entries--; i++; - - } - return; -} diff --git a/plugins/plugins/vcgn/cnat_common_api.h b/plugins/plugins/vcgn/cnat_common_api.h deleted file mode 100644 index a4eb7443..00000000 --- a/plugins/plugins/vcgn/cnat_common_api.h +++ /dev/null @@ -1,22 +0,0 @@ -/*--------------------------------------------------------------------------- - * Copyright (c) 2009-2014 Cisco and/or its affiliates. - * 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 __CNAT_COMMON_API_H__ -#define __CNAT_COMMON_API_H__ - -/* All common API prototypes */ -void cnat_scanner_db_process_turn_on(vlib_main_t *vm); - -#endif diff --git a/plugins/plugins/vcgn/cnat_config.c b/plugins/plugins/vcgn/cnat_config.c deleted file mode 100644 index 87183dfa..00000000 --- a/plugins/plugins/vcgn/cnat_config.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - *------------------------------------------------------------------ - * cnat_config.c - configuration definitions - * - * Copyright (c) 2007-2012 Cisco and/or its affiliates. - * 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 "cnat_config.h" -#include "cnat_cli.h" -#include "cnat_v4_pptp_alg.h" -#include "platform_common.h" - -/* session timeout */ - -u16 tcp_initial_setup_timeout = V4_DEF_TCP_IS_TO; /* sec */ -u16 tcp_active_timeout = V4_DEF_TCP_AS_TO; /* sec */ -u16 udp_init_session_timeout = V4_DEF_UDP_IS_TO; /* 30 sec */ -u16 udp_act_session_timeout = V4_DEF_UDP_AS_TO; /* 2 min */ -u16 icmp_session_timeout = V4_DEF_ICMP_S_TO; /* 60 sec */ - -cnat_pptp_config_t pptp_cfg = - { - .enable = PPTP_DISABLED, - .timeout = PPTP_GRE_TIMEOUT - } ; - -/* This flag is used as indication of timeout related config - * changes and hence db needs to be updated - */ -u8 timeout_dirty_flag = 0; - -/* mapping refresh direction, - * 1 inbound and outbound refresh - */ -u8 mapping_refresh_both_direction = V4_DEF_ENABLE; - -u16 cnat_main_db_max_ports_per_user = V4_DEF_MAX_PORTS; - -u32 cnat_main_db_icmp_rate_limit = DEF_RATE_LIMIT; -u32 cnat_main_db_icmp_rate_limit_core = DEF_RATE_LIMIT_CORE; -u32 crc_zero_udp_rate_limit_core = RATE_LIMIT_UDP_CORE; -u16 cnat_static_port_range = CNAT_DEF_STATIC_PORT_RANGE; - - -/* - * ftp alg enable - */ -u8 ftp_alg_enabled = V4_DEF_DISABLE; -u16 rtsp_alg_port_num = 0; - -/* - * load balancing debug mode - */ -u8 lb_debug_enable = V4_DEF_DISABLE; - - -/* good or evil mode - * 0 endpoint-independnet filter, good mode - * 1 address depedent filter, evil mode - */ -u8 address_dependent_filtering = V4_DEF_DISABLE; - -u16 per_user_icmp_msg_limit = ICMP_MSG_RATE_LIMIT; - -u16 config_delete_timeout = V4_CONFIG_DELETE_TO; - diff --git a/plugins/plugins/vcgn/cnat_config.h b/plugins/plugins/vcgn/cnat_config.h deleted file mode 100644 index f1042737..00000000 --- a/plugins/plugins/vcgn/cnat_config.h +++ /dev/null @@ -1,582 +0,0 @@ -/* - *------------------------------------------------------------------ - * cnat_config.h - configuration database definitions - * - * Copyright (c) 2007-2013 Cisco and/or its affiliates. - * 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 __CNAT_CONFIG_H__ -#define __CNAT_CONFIG_H__ - -#include -#include - -#include "cnat_bulk_port_defs.h" - -/* default policy value */ -#define V4_DEF_ICMP_S_TO 60 /*icmp session timeout */ -#define V4_DEF_UDP_IS_TO 30 /*udp init session timeout */ -#define V4_DEF_UDP_AS_TO 120 /*udp active session timeout */ -#define V4_DEF_TCP_IS_TO 120 /*tcp init session timeout */ -#define V4_DEF_TCP_AS_TO 1800 /*tcp active session timeout, 30 min */ -#define V4_DEF_TCP_MSS 1460 /*tcp mss */ -#define V4_DEF_MAX_PORTS 100 /*max port limit per user */ -#define DEF_RATE_LIMIT PLATFORM_MAX_CORES /* No of packets/sec icmp generated */ -#define DEF_RATE_LIMIT_CORE 1 /* No of packets/sec icmp generated (per core) */ -#define RATE_LIMIT_UDP_CORE 1000 /* Max allowed udp crc zero packets/sec/core */ - -#define NAT44_RESERVED_INST_ID 1 -#define DSLITE_START_ID (NAT44_RESERVED_INST_ID + 1) -#define V4_DEF_VRF_MAX_PORTS 0 /*max port limit per vrf user; - 0 means use the global port limit for user*/ -/*Hardcoded . TBD - can be made configurable */ - -#define V4_DEF_ENABLE 1 /* feature enable */ -#define V4_DEF_DISABLE 0 /* feature disable */ - -#define CNAT_DEF_STATIC_PORT_RANGE 1024 /* Default range for static ports */ -/* - * If TCP MSS is not configured, store the maximum possible value - */ -#define V4_TCP_MSS_NOT_CONFIGURED_VALUE 0xffff - -/* default timeout for fragments in seconds set to 2 - * in case its not configured - */ -#define CNAT_IPV4_FRAG_TIMEOUT_DEF 2 -/* other */ -/* max db entries to be scaned */ -#define MAX_DB_ENTRY_PER_SCAN PLATFORM_MAX_DB_ENTRY_PER_SCAN -/* max db entries selected per scan */ -#define MAX_DB_ENTRY_SELECTED_PER_SCAN PLATFORM_MAX_DB_ENTRY_SELECTED_PER_SCAN - -#define ICMP_MSG_RATE_LIMIT 3 /* rate limit for icmp message */ -#define V4_CONFIG_DELETE_TO 600 /* timeout for entry to be deleted */ - -/* session timeout */ - -extern u16 tcp_initial_setup_timeout; -extern u16 tcp_active_timeout; -extern u16 udp_init_session_timeout; -extern u16 udp_act_session_timeout; -extern u16 icmp_session_timeout; - -extern u8 timeout_dirty_flag; - -/* mapping refresh direction, - * 0 outbound only refresh, - * 1 inbound and outbound refresh - */ -extern u8 mapping_refresh_both_direction; - - -extern u16 cnat_main_db_max_ports_per_user; -extern u32 cnat_main_db_icmp_rate_limit; -extern u32 cnat_main_db_icmp_rate_limit_core; -extern u32 crc_zero_udp_rate_limit_core; - -extern u16 cnat_static_port_range; - -typedef enum { - LOG_FORMAT_UNDEFINED =0, - LOG_FORMAT_COMPACT, - LOG_FORMAT_NF9, - LOG_FORMAT_MAX, /* keep this as last */ -} log_format_t; - -typedef enum { - CNAT_CONFIG_DEL_OP = 0, - CNAT_CONFIG_ADD_OP, -} cnat_op_flag_t; - -extern u8 ftp_alg_enabled; -extern u16 rtsp_alg_port_num; - -/* - * load balancing debug mode - */ -extern u8 lb_debug_enable; - -/* good or evil mode - * 0 endpoint-independnet filter, good mode - * 1 address depedent filter, evil mode - */ -extern u8 address_dependent_filtering; - -extern u16 per_user_icmp_msg_limit; - -/* vrfmap or portmap holding time - * after delete - */ -extern u16 config_delete_timeout; - -/* - * Bit map for various configuration in the POLICY KNOB case - */ -#define BIDIR_REFRESH_ENABLE 0x01 -#define BIDIR_REFRESH_DISABLE 0x02 -#define FTP_ALG_ENABLE 0x04 -#define FTP_ALG_DISABLE 0x08 -#define DEFAULT_NFV9_LOGGING_SERVER_ENABLE 0x10 -#define DEFAULT_NFV9_LOGGING_SERVER_DISABLE 0x20 - - -/* - * This structure contains a single VRF map configuration - * from a bulk message. This structure is in conformanace - * with the following structures defined in cnat_config_api.h - * - spp_api_cnat_v4_bulk_vrf_map_t - * - * Any change in the above structures should be propagated here - */ -typedef struct _spp_api_cnat_v4_single_vrf_map_req { - u32 i_vrf_id; - u32 o_vrf_id; - - u16 i_vrf; - u16 o_vrf; - - u32 start_addr; - u32 end_addr; - - u16 vrf_policy_enable; -#define TCP_MSS_ENABLE 0x0001 -#define TCP_MSS_DISABLE 0x0002 -#define NFV9_LOGGING_ENABLE 0x0004 -#define NFV9_LOGGING_DISABLE 0x0008 -#define VRF_MAP_DELETE 0x0010 -#define VRF_MAP_ADD 0x0020 -#define BULK_ALLOC_CHANGE 0x0040 - - u16 tcp_mss_value; - u32 vrf_nfv9_logging_ipv4_address; - u16 vrf_nfv9_logging_udp_port; - u16 vrf_nfv9_refresh_rate; - u16 vrf_nfv9_timeout_rate; - u16 vrf_nfv9_path_mtu; -#ifndef NO_BULK_LOGGING - bulk_alloc_size_t bulk_size; -#endif /* NO_BULK_LOGGING */ -} spp_api_cnat_v4_single_vrf_map_req; - -typedef struct _spp_api_cnat_v4_single_vrf_map_rc { - u8 vrf_map_rc; - u8 tcp_mss_rc; - u8 nfv9_logging_rc; - u8 pad; -} spp_api_cnat_v4_single_vrf_map_rc; - -/* - * Bulk Response for the VRF map request - */ -typedef struct _spp_api_cnat_v4_bulk_vrf_map_resp { - u16 _spp_msg_id; - u8 bulk_rc; - u8 pad; - - u32 num_vrfmap_entries; - - spp_api_cnat_v4_single_vrf_map_rc vrf_map_rc; - -} spp_api_cnat_v4_bulk_vrf_map_resp; - -/* - * Bulk Response for the Policy Knob request - */ -typedef struct _spp_api_cnat_v4_bulk_policy_knob_resp { - u16 _spp_msg_id; - u8 bulk_rc; /* Global rc code */ - u8 pad; - - u8 port_limit_rc; - u8 icmp_timeout_rc; - u8 udp_init_timeout_rc; - u8 udp_act_timeout_rc; - - u8 tcp_init_timeout_rc; - u8 tcp_act_timeout_rc; - u8 nfv9_logging_rc; - u8 pad2; -} spp_api_cnat_v4_bulk_policy_knob_resp; - - -/* PPTP ALG defs and structures */ - -/* dont change the order.. - maintened at offset mapped to msg ids */ - -typedef struct pptp_ctrl_msg_ctrs_t { - u64 dummy; - u64 sccr; - u64 sccrp; - u64 stccrq; - u64 stccrp; - u64 erq; - u64 erp; - u64 ocrq; - u64 ocrp; - u64 icrq; - u64 icrp; - u64 iccn; - u64 cclr; - u64 cdn; - u64 wen; - u64 sli; -}pptp_ctrl_msg_ctrs_t; - -#define PPTP_INCR(ctr) pptp_cfg.counters.pptp_##ctr++ -#define PPTP_DECR(ctr) pptp_cfg.counters.pptp_##ctr-- - -typedef struct pptp_counters_t { - - u64 pptp_ctrl_msg_drops; - u64 pptp_active_tunnels; - u64 pptp_active_channels; - u64 pptp_in2out_gre_drops; - u64 pptp_out2in_gre_drops; - u64 pptp_in2out_gre_fwds; - u64 pptp_out2in_gre_fwds; - pptp_ctrl_msg_ctrs_t ctrl_ctrs; - -} pptp_counters_t; - -#define CNAT_PPTP_ENABLE 1 -#define CNAT_PPTP_DEF_TIMEOUT 60 /* secs */ - -typedef struct cnat_pptp_config_t { - u8 enable; - u16 timeout; - pptp_counters_t counters; - -} cnat_pptp_config_t; - - -#define CNAT_PPTP_ENABLE_FLAG 0x01 -#define CNAT_PPTP_TIMEOUT_FLAG 0x02 - -/* pptp config msg resp */ -typedef struct _spp_api_cnat_v4_config_pptp_alg_resp { - u16 _spp_msg_id; - u8 bulk_rc; - u8 pad; - -} spp_api_cnat_v4_config_pptp_alg_resp_t; - -typedef struct { - u16 msg_id; - u8 rc; - u8 pad[5]; - - /* better to have a group structures rather than individual - variables, any change in counters is will automatically - reflect here */ - pptp_counters_t counters; -} pptp_show_counters_resp_t ; - - -extern cnat_pptp_config_t pptp_cfg; - - -/* ========= 6RD declarations =============================== */ - -#define V6RD_ENTRY_DELETE 0x00 -#define IPV4_TUNNEL_SRC_CONFIG 0x04 -#define TUNNEL_MTU_CONFIG 0x08 -#define IPV4_PREFIXMASK_LEN_CONFIG 0x10 -#define IPV4_SUFFIXMASK_LEN_CONFIG 0x20 -#define TTL_CONFIG 0x40 -#define TOS_CONFIG 0x80 -#define V6RD_IPV6_PREFIX_CONFIG 0x100 -#define V6RD_RESET_DF_BIT_CONFIG 0x200 -#define V6RD_UNICAST_ADDR_CONFIG 0x400 -#define V6RD_REASSEMB_CONFIG 0x800 - -#define TTL_ENABLE 0x1 -#define TOS_ENABLE 0x2 -#define RESET_DF_BIT 0x4 -#define REASSEMBLY_ENABLE 0x8 - -/* ========= 6RD declarations =============================== */ - -/* - * Single Request for XLAT config - */ -typedef struct _spp_api_cnat_v4_single_xlat_config_req { - - /* - * Indicates the xlat instance id - How big will this value be - * Can we restrict it between 0..255, that way the APP code - * can use an array to store the xlat instances. - */ - u32 xlat_id; - -#define XLAT_ENTRY_DELETE 0x0000 -#define IPV6_SVI_IF_NUM_CONFIG 0x0001 -#define IPV4_SVI_IF_NUM_CONFIG 0x0002 -#define IPV4_TO_IPV6_TCP_MSS_CONFIG 0x0004 -#define IPV6_TO_IPV4_TCP_MSS_CONFIG 0x0008 -#define IPV6_PREFIX_CONFIG 0x0010 -#define IPV6_UBIT_ON_CONFIG 0x0020 -#define IPV6_NON_TRANSLATABLE_PREFIX_MAP_CONFIG 0x0040 -#define IPV4_TOS_SETTING_CONFIG 0x0080 -#define IPV6_TOS_SETTING_CONFIG 0x0100 -#define IPV4_DFBIT_CLEAR_CONFIG 0x0200 -#define ICMPV6_PTB_MTU_SET_CONFIG 0x0400 -#define IPV6_NON_TRANSLATABLE_PREFIX_MAP_ALG_CONFIG 0x0800 -#define CPE_V4_PREFIX_CONFIG 0x1000 /* for map-t */ -#define CPE_V6_PREFIX_CONFIG 0x2000 /* for map-t */ -#define EXTERNAL_V6_PREFIX_CONFIG 0x4000 /* for map-t */ -#define PORT_SHARING_RATIO_CONFIG 0x8000 /* for map-t */ -#define CONSECUTIVE_PORTS_CONFIG 0x10000 /* for map-t */ - - u32 xlat_config_fields_enable; - - /* - * If numbers of the IPv6 and IPv4 SVI interfaces - */ - u32 ipv6_svi_if_num; - u32 ipv4_svi_if_num; - - /* - * TCP MSS values for the 2 XLAT directions - */ - u16 v4_to_v6_tcp_mss; - u16 v6_to_v4_tcp_mss; - - /* - * XLAT IPv6 prefix - */ - u32 v6_prefix[4]; - - /* - * XLAT IPv6 prefix mask - */ - u8 v6_prefix_mask_len; - - /* - * Set to non-zero if UBITs are reserved - */ -#define UBITS_ON 0x01 -#define IPV4_DF_BIT_CLEAR 0x02 -#define ICMPV6_MTU_SET 0x04 -#define IPV4_TOS_SET_ENABLED 0x08 -#define IPV6_TC_SET_ENABLED 0x10 - - u8 feature_enable_bits; - - u8 v4_prefix_mask_len; - -#define IPV6_NON_TRANSLATABLE_PREFIX_MAP_ALG_HASH 0x1 -#define IPV6_NON_TRANSLATABLE_PREFIX_MAP_ALG_TTL 0x2 -#define IPV6_NON_TRANSLATABLE_PREFIX_MAP_ALG_RANDOM 0x3 - u8 non_translatable_v6_prefix_v4_map_prefix_alg; - - u8 ipv6_tos_value; - - u8 ipv4_tos_value; - - u8 pad2; - - u8 pad3; - - u32 v4_prefix; - - /* - * MAP-T/MAP-E specific parameters - */ - u8 xlat_type; - - u32 cpe_domain_v6_prefix[4]; - u8 cpe_domain_v6_prefix_len; - - u32 cpe_domain_v4_prefix; - u8 cpe_domain_v4_prefix_len; - - u32 external_domain_v6_prefix[4]; - u8 external_domain_v6_prefix_len; - - u8 port_sharing_ratio_bits; - u8 consecutive_ports_bits; - -} spp_api_cnat_v4_single_xlat_config_req; - -/* - * Single Response for the xlat config request - */ -typedef struct _spp_api_cnat_v4_single_xlat_config_resp { - u8 v4_if_num_rc; - u8 v6_if_num_rc; - u8 v4_to_v6_tcp_mss_rc; - u8 v6_to_v4_tcp_mss_rc; - - u8 v6_prefix_rc; - u8 ubit_on_rc; - u8 v4_prefix_rc; - u8 xlat_id_rc; - - u8 non_translatable_v6_prefix_v4_map_alg_rc; - u8 ipv4_dfbit_clear_rc; - u8 icmpv6_ptb_mtu_set_rc; - u8 ipv4_tos_set_rc; - - u8 ipv6_tos_set_rc; - u8 pad1; - u8 pad2; - u8 pad3; -} spp_api_cnat_v4_single_xlat_config_resp; - -/* - * Bulk Response for the xlat config request - */ -typedef struct _spp_api_cnat_v4_bulk_xlat_config_resp { - u16 _spp_msg_id; - u16 pad; - - u32 bulk_rc; - - u32 num_xlat_entries; - - spp_api_cnat_v4_single_xlat_config_resp xlat_config_resp; - -} spp_api_cnat_v4_bulk_xlat_config_resp; - -typedef struct _spp_api_v6rd_v4_single_v6rd_config_resp { - u8 v6rd_id_rc; - u8 v4_if_num_rc; - u8 v6_if_num_rc; - u8 tunnel_source_rc; - u8 tunnel_mtu_rc; - u8 ipv4masklen_prefix_rc; - u8 ipv4masklen_suffix_rc; - u8 ttl_rc; - u8 tos_rc; - u8 anycast_rc; - u8 v6_prefix_rc; - u8 v6_br_unicast_rc; - u8 reassembly_rc; - u8 pad1; - u8 pad2; - u8 pad3; -} spp_api_v6rd_v4_single_v6rd_config_resp_t; - -typedef struct _spp_api_v6rd_v4_bulk_v6rd_config_resp { - u16 _spp_msg_id; - u16 pad; - u32 bulk_rc; - u32 num_v6rd_entries; - spp_api_v6rd_v4_single_v6rd_config_resp_t v6rd_config_resp[0]; -} spp_api_v6rd_v4_bulk_v6rd_config_resp_t; - -/* - * Single Request for MAPE config - */ -typedef struct _spp_api_mape_single_config_req { - - /* - * Indicates the mape instance id - How big will this value be - * Can we restrict it between 0..255, that way the APP code - * can use an array to store the xlat instances. - */ - u32 mape_id; - -#define MAPE_ENTRY_DELETE 0x0000 -#define MAPE_IPV4_SVI_IF_NUM_CONFIG 0x0001 -#define MAPE_IPV6_SVI_IF_NUM_CONFIG 0x0002 -#define MAPE_IPV4_TO_IPV6_TCP_MSS_CONFIG 0x0004 -#define MAPE_IPV6_TO_IPV4_TCP_MSS_CONFIG 0x0008 -#define MAPE_CPE_V4_PREFIX_CONFIG 0x0010 -#define MAPE_CPE_V6_PREFIX_CONFIG 0x0020 -#define MAPE_PORT_SHARING_RATIO_CONFIG 0x0040 -#define MAPE_CONSECUTIVE_PORTS_CONFIG 0x0080 -#define MAPE_PATH_MTU 0x0100 -#define MAPE_TUNNEL_ENDPOINT_V6_CONFIG 0x0200 - - u32 mape_config_fields_enable; - - /* - * If numbers of the IPv6 and IPv4 SVI interfaces - */ - u32 ipv6_svi_if_num; - u32 ipv4_svi_if_num; - - /* - * TCP MSS values for the 2 XLAT directions - */ - u16 v4_to_v6_tcp_mss; - u16 v6_to_v4_tcp_mss; - - /* - * Path v6 MTU. - */ - u32 path_mtu; - - /* - * CPE IPv6 prefix and mask len. - */ - u32 cpe_domain_v6_prefix[4]; - u8 cpe_domain_v6_prefix_len; - - /* - * CPE IPv4 prefix and mask len. - */ - u32 cpe_domain_v4_prefix; - u8 cpe_domain_v4_prefix_len; - - /* - * BR IPv6 tunnel end point V6 prefix and mask len. - */ - u32 aftr_tunnel_endpoint_address_v6[4]; - u8 aftr_tunnel_endpoint_address_v6_len; - - /* - * BR IPv6 tunnel end point V6 prefix and mask len. - */ - u8 port_sharing_ratio_bits; - u8 consecutive_ports_bits; - -} spp_api_mape_single_config_req; - - -/* - * Single Response for the mape config response - */ -typedef struct _spp_api_mape_single_config_resp { - u8 v4_if_num_rc; - u8 v6_if_num_rc; - u8 v4_to_v6_tcp_mss_rc; - u8 v6_to_v4_tcp_mss_rc; - u8 mape_id_rc; - u8 path_mtu_rc; - u8 cpe_v6_prefix_rc; - u8 cpe_v4_prefix_rc; - u8 tunnel_endpoint_prefix_rc; - u8 port_sharing_ratio_rc; - u8 port_contiguous_rc; - u8 pad1; -} spp_api_mape_single_config_resp; - -/* - * Bulk Response for the mape config request - */ -typedef struct _spp_api_mape_bulk_config_resp { - u16 _spp_msg_id; - u16 pad; - u32 bulk_rc; - u32 num_mape_entries; - spp_api_mape_single_config_resp mape_config_resp; -} spp_api_mape_bulk_config_resp; - - -#endif /* __CNAT_CONFIG_H__ */ diff --git a/plugins/plugins/vcgn/cnat_config_api.h b/plugins/plugins/vcgn/cnat_config_api.h deleted file mode 100644 index 0789d6a9..00000000 --- a/plugins/plugins/vcgn/cnat_config_api.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * 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 __CNAT_CONFIG_API_H__ -#define __CNAT_CONFIG_API_H__ - -typedef struct _spp_api_cnat_v4_add_vrf_map { - u16 _spp_msg_id; - u8 rc; - u8 pad; - u32 i_vrf_id; - u32 o_vrf_id; - u16 i_vrf; - u16 o_vrf; - u32 start_addr[8]; - u32 end_addr[8]; -} spp_api_cnat_v4_add_vrf_map_t; - -typedef struct _spp_api_cnat_v4_config_nfv9_logging { - u16 _spp_msg_id; - u8 rc; - u8 enable; - u32 ipv4_address; - u32 i_vrf_id; - u16 i_vrf; - u16 port; - u16 refresh_rate; - u16 timeout_rate; - u16 path_mtu; - u8 nfv9_global_collector; - u8 session_logging; -} spp_api_cnat_v4_config_nfv9_logging_t; - - -#endif diff --git a/plugins/plugins/vcgn/cnat_db.h b/plugins/plugins/vcgn/cnat_db.h deleted file mode 100644 index 3596e238..00000000 --- a/plugins/plugins/vcgn/cnat_db.h +++ /dev/null @@ -1,701 +0,0 @@ -/* - *------------------------------------------------------------------ - * cnat_db.h - translation database definitions - * - * Copyright (c) 2007-2013 Cisco and/or its affiliates. - * 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 __CNAT_DB_H__ -#define __CNAT_DB_H__ - -#include "cnat_cli.h" -#include "cnat_ports.h" -#include "index_list.h" - -#define VRF_NAME_LEN_STORED 12 -#define MAX_VRFID 400 -typedef struct _cnat_svi_params_entry { - u16 svi_type; - u16 pad; - - u32 vrf_id; - u16 if_num; - - u32 ipv6_addr[4]; - u32 ipv4_addr; - - u8 direction; - u32 tbl_id; /* vrf */ - u32 vrf_override_id; /* tbl_id for override vrf */ - u8 vrf_override_flag; - u8 partition_id; -} cnat_svi_params_entry; - -typedef struct _cnat_ingress_vrfid_name_entry { - u32 vrf_id; - u16 ref_count; /*no# of serviceApps under a single vrf*/ - u8 vrf_name[VRF_NAME_LEN_STORED]; - u16 pad1; -} cnat_ingress_vrfid_name_entry; -#define HASH_ENHANCE 4 - -#define CNAT_DB_SIZE (PLATFORM_MAX_NAT_ENTRIES / PLATFORM_CNAT_INSTS) -#define CNAT_MAIN_HASH_SIZE (HASH_ENHANCE * PLATFORM_CNAT_MAIN_PRELIM_HASH_SIZE) -#define CNAT_MAIN_HASH_MASK (CNAT_MAIN_HASH_SIZE-1) - -#define CNAT_USER_DB_SIZE (PLATFORM_MAX_USER_ENTRIES / PLATFORM_CNAT_INSTS) -#define CNAT_USER_HASH_SIZE (HASH_ENHANCE * PLATFORM_CNAT_USER_PRELIM_HASH_SIZE) -#define CNAT_USER_HASH_MASK (CNAT_USER_HASH_SIZE-1) - -#define CNAT_SESSION_DB_SIZE (PLATFORM_MAX_NAT_ENTRIES / PLATFORM_CNAT_INSTS) -#define CNAT_SESSION_HASH_SIZE (HASH_ENHANCE * PLATFORM_CNAT_MAIN_PRELIM_HASH_SIZE) -#define CNAT_SESSION_HASH_MASK (CNAT_SESSION_HASH_SIZE-1) - - -#define CNAT_MAX_SESSIONS_PER_BIB 0xFFFF - -#define NUM_BITS_IN_UWORD (8*sizeof(uword)) - -/* No. of per ip/port config will be limited to 1024 */ -#define CNAT_TIMEOUT_HASH_SIZE 1024 -#define CNAT_TIMEOUT_HASH_MASK (CNAT_TIMEOUT_HASH_SIZE - 1) -#define CNAT_TIMEOUT_FULL_MASK 0xFFFFFFFFFFFFFFFF -#define CNAT_TIMEOUT_IPPROT_MASK PLATFORM_CNAT_TIMEOUT_IPPROT_MASK -#define CNAT_TIMEOUT_PORTPROT_MASK PLATFORM_CNAT_TIMEOUT_PORTPROT_MASK - -#define TRUE 1 -#define FALSE 0 - -/* - * The key structure. All fields are in NETWORK byte order! - */ -typedef struct { - u32 ipv4; - u16 port; - u16 vrf; //bit0-12:vrf, bit13:unused, bit14-15:protocol -} cnat_db_key_t; - -/* bit14-15:protocol in cnat_db_key_t */ -#define CNAT_INVALID_PROTO 0x0000 -#define CNAT_PPTP 0x0000 -#define CNAT_UDP 0x4000 -#define CNAT_TCP 0x8000 -#define CNAT_ICMP 0xc000 -#define CNAT_VRF_MASK 0x3fff -#define CNAT_PRO_MASK 0xc000 -#define CNAT_PRO_SHIFT 14 - -/* - * Maximum number of VRF entries supported - */ -#define CNAT_MAX_VRFMAP_ENTRIES (CNAT_VRF_MASK + 1) -/* - * for hashing purposes, fetch the key in one instr. - */ -typedef union { - cnat_db_key_t k; - u64 key64; -} cnat_key_t; - -typedef struct { - cnat_key_t k; - u32 bucket; -} cnat_db_key_bucket_t; - -typedef struct { - u32 ipv6[4]; - cnat_key_t ipv4_key; -} dslite_key_t; - -typedef struct { -/* - cnat_db_key_bucket_t ck; - u32 ipv6[4]; -*/ - dslite_key_t dk; - u32 bucket; -} dslite_db_key_bucket_t; - - -/* Per port/ip timeout related strucutres */ -extern index_slist_t *cnat_timeout_hash; - -typedef struct { - cnat_key_t timeout_key; - u16 timeout_value; -} cnat_timeout_t; - -typedef struct { - cnat_timeout_t t_key; - index_slist_t t_hash; -} cnat_timeout_db_entry_t; - -extern cnat_timeout_db_entry_t *cnat_timeout_db; - -/* - * Main translation database entries. Currently 0x5A = 90 bytes in length. - * Given 20,000,000 entries, it saves nearly 1gb of SDRAM to pack the entries - * and pay the extra prefetch. So, that's what we do. - */ - -typedef struct { - /* 0x00 */ - index_slist_t out2in_hash; /* hash-and-chain, x2 */ - index_slist_t in2out_hash; - - /* 0x08 */ - u16 flags; /* Always need flags... */ -#define CNAT_DB_FLAG_PORT_PAIR (1<<0) -#define CNAT_DB_FLAG_TCP_ACTIVE (1<<1) -#define CNAT_DB_FLAG_ENTRY_FREE (1<<2) -#define CNAT_DB_FLAG_UDP_ACTIVE (1<<3) -#define CNAT_DB_FLAG_STATIC_PORT (1<<4) -/* This alg entry is set for FTP data connection */ -#define CNAT_DB_FLAG_ALG_ENTRY (1<<5) - -/* Will be set for TCP connection with destination port - 1723 - * note - here CNAT_DB_FLAG_TCP_ACTIVE is also set */ -#define CNAT_DB_FLAG_PPTP_TUNNEL_INIT (1<<6) -#define CNAT_DB_FLAG_PPTP_TUNNEL_ACTIVE (1<<7) - -/* for PPTP GRE packtes */ -#define CNAT_DB_FLAG_PPTP_GRE_ENTRY (1<<8) - -/* for PCP support */ -#define CNAT_DB_FLAG_PCPI (1<<9) -#define CNAT_DB_FLAG_PCPE (1<<10) -#define CNAT_PCP_FLAG (CNAT_DB_FLAG_PCPI | CNAT_DB_FLAG_PCPE) - -#define CNAT_TAC_SEQ_MISMATCH (1<<11) -/* This alg entry is set for ftp control connection */ -#define CNAT_DB_FLAG_ALG_CTRL_FLOW (1<<12) - -/* This is for marking the state where connection is closing */ -#define CNAT_DB_FLAG_TCP_CLOSING (1<<13) - -#define CNAT_DB_DSLITE_FLAG (1<<14) -#define CNAT_DB_NAT64_FLAG (1<<15) - - /* 0x0A */ - u16 vrfmap_index; /* index of vrfmap */ - - /* 0x0C */ - u32 user_index; /* index of user that owns this entry */ - - /* 0x10 */ - cnat_key_t out2in_key; /* network-to-user, outside-to-inside key */ - - /* 0x18 */ - cnat_key_t in2out_key; /* user-to-network, inside-to-outside key */ - - /* 0x20 */ - index_dlist_t user_ports; /* per-user translation list */ - - /* 0x28 */ - u32 out2in_pkts; /* pkt counters */ - - /* 0x2C */ - u32 in2out_pkts; - - /* 0x30 */ - u32 entry_expires; /* timestamp used to expire translations */ - - /* 0x34 */ - union { /* used by FTP ALG, pkt len delta due to FTP PORT cmd */ - u16 delta; - i8 alg_dlt[2]; /* two delta values, 0 for previous, 1 for current */ - u16 il; /* Used to indicate if interleaved mode is used - in case of RTSP ALG */ - } alg; - - /* 0x36 */ - u16 timeout; - - /* 0x38 */ - union { - struct seq_pcp_t { - u32 tcp_seq_num; /* last tcp (FTP) seq # that has pkt len change due to PORT */ - u32 pcp_lifetime; /* peer and map life time value sent in reply*/ - } seq_pcp; - - /* This is for TCP seq check */ - struct tcp_seq_chk_t { - u32 seq_no; - u32 ack_no; - } tcp_seq_chk; - - /* used for pptp alg entries - 1. only tunnel : prev and next = 0xFFFFFFFF - 2. first gre entry : prev = tunnel db, next = next gre db - 3. last gre entry : prev = previous gre/tunnel db, next= 0xFFFFFFFF; - - *while adding gre entry- updated at the begining of head - *while deleting gre entry - hash look up will be done and prev and next are adjusted - * while deleting need not traverse throufgh the list, as done in index_dlist_remelem - - */ - index_dlist_t pptp_list; - - } proto_data; - - /* 0x40 */ - u32 dst_ipv4; /* pointer to ipv4 dst list, used in evil mode */ - - /* 0x44 */ - u16 dst_port; - - /* 0x46 */ - u16 dslite_nat44_inst_id; - - /* 0x48 */ - u32 session_head_index; - - /* 0x4C */ - u16 nsessions; - - /* 0x4E */ - u8 unused; - - /* 0x4F */ - u8 scale; - - /* 0x50 */ - u32 diff_window; - - /* Sizeof cnat_main_db_entry_t = 0x54 */ -} cnat_main_db_entry_t; - -/* Caution ... - * 1. The size of this structure should be same as that of - * nat64_bib_user_entry_t - * 2. Do not alter the position of first four fields - */ -typedef struct { - /* 0x00 */ - index_slist_t user_hash; /* hash 'n chain bucket chain */ - - /* 0x04 */ - u16 ntranslations; /* translations hold by this user */ - - /* 0x06 */ - u8 icmp_msg_count; /* use to rate limit imcp send to this user */ - - /* 0x07 */ - u8 flags; /* To identfiy whether it is NAT64 or NAT44 etc */ -#define CNAT_USER_DB_NAT44_FLAG 0 -#define CNAT_USER_DB_NAT64_FLAG 1 -#define CNAT_USER_DB_DSLITE_FLAG 2 -#define CNAT_USER_DB_PORT_LIMIT_EXCEEDED 0X80 - - /* 0x08 */ - u32 translation_list_head_index; - - /* 0x0C */ - u32 portmap_index; /* index of bound port-map */ - - /* 0x10 */ - cnat_key_t key; /* For dslite this should store IPv6 address */ - u32 ipv6[4]; // B4 ipv6 address - /* 0x18 */ -#if 0 - u32 temp1; - u32 temp2; - u32 temp3; -#endif - /* 0x28 same as nat64_user_db */ -#ifndef NO_BULK_LOGGING - /* Now adding 8 more bytes for bulk allocation.. This makes it - * 0x30 (48). Added the same to nat64_bib_user_entry_t make the - * the sizes equal. For nat64 stful, we may support bulk allocation - * later. - */ - /* Indicates the currently used bulk port range */ - i16 bulk_port_range_cache[BULK_RANGE_CACHE_SIZE]; -#endif /* #ifndef NO_BULK_LOGGING */ -} cnat_user_db_entry_t; - -/* - * cnat_session_entry_t - * This structure represents the cnat session table. It maintains the - * information about the destination of a given translation (main db) - * There would be entry here only if packets are send to more than 1 destn - * from the same source. - */ -typedef struct { - - /* 0x00 */ - index_slist_t cnat_session_hash; - - /* 0x04 */ - u32 main_db_index; /* would point to v4 src transport address */ - - /* 0x08 */ - cnat_key_t v4_dest_key; - - /* 0x10 */ - u16 flags; /* Same as cnat_main_db_t */ - - /* 0x12 */ - u16 timeout; - - /* 0x14 */ - u32 entry_expires; - /* 0x18 */ - index_dlist_t main_list; - /* 0x20 = 32 B */ - - union { /* alg same as cnat_main_db_t */ - u16 delta; - i8 alg_dlt[2]; - u16 il; - } alg; - - /* 0x22 */ - u16 tcp_flags; - - /* 0x24 */ - u32 tcp_seq_num; - - /* 0x28 */ - u32 ack_no; - - /* 0x2C */ - u32 window; - - /* 0x30 */ - u8 scale; - - /* 0x31 */ - u8 pad; - - /* 0x32 */ -} cnat_session_entry_t; - - - -/* - * out2in and in2out hash bucket arrays are simply arrays of index_slist_t's - */ - -typedef enum { - CNAT_DB_CREATE_DEFAULT=0, /* honor cnat_main_db_max_ports_per_user */ - CNAT_DB_CREATE_OVERRIDE, /* just do it. */ -} cnat_db_create_policy_t; - -typedef struct { - cnat_key_t in2out_key; - cnat_key_t out2in_key; - u32 dst_ipv4; /* evil for mode only */ - u16 cnat_instance; - cnat_portmap_t *portmap; - u16 *portmap_inuse; - cnat_main_db_entry_t *db; - cnat_db_create_policy_t policy; - port_pair_t pair_of_ports; -} cnat_db_create_args_t; - -extern cnat_main_db_entry_t *cnat_main_db; -extern cnat_user_db_entry_t *cnat_user_db; -extern cnat_session_entry_t *cnat_session_db; - -#define S_WAO 0 -#define S_WA 1 /* waiting for address pool */ -#define S_WO 2 /* waiting for outside vrf */ -#define S_RUN 3 /* got everything */ -#define S_DEL 4 /* just delete */ - -#define INVALID_UIDX 0xffff /*invalid svi app uidb index */ -#define INVALID_VRFID 0xffffffff /*invalid vrf id */ - -typedef struct { - u16 status; - u16 tcp_mss; //tcp max segment size for this inside vrf */ - u32 delete_time; - u16 i_vrf; //inside SVI uidx - u16 o_vrf; //outside SVI uidx - u32 i_vrf_id; //inside vrf id - u32 o_vrf_id; //outside vrf id - cnat_portmap_v2_t *portmap_list; - u32 nfv9_logging_index; - u32 syslog_logging_index; - u16 ip_n_to_1; -#ifndef NO_BULK_LOGGING - bulk_alloc_size_t bulk_size; -#endif /* #ifndef NO_BULK_LOGGING */ - u32 pcp_server_addr; - u32 pcp_server_port; - - u8 nf_logging_policy; - u8 syslog_logging_policy; - u8 frag_tout; - u32 rseed_ip; - u16 port_limit; - u8 tcp_seq_check_enable; - u8 pad; - u32 tcp_seq_user_window; - u8 filter_policy; - u8 ignore_port; -} cnat_vrfmap_t; - -/* - * When creating cnat_vrfmap entry, ensure that any already - * configured logging info is taken into account - */ -#define CNAT_SET_VRFMAP_NFV9_LOGGING_INDEX(logging_index, i_vrf) \ -do { \ - cnat_nfv9_logging_info_t *my_nfv9_logging_info = 0; \ - pool_foreach (my_nfv9_logging_info, cnat_nfv9_logging_info, ({ \ - if (my_nfv9_logging_info->i_vrf == i_vrf) { \ - logging_index = my_nfv9_logging_info - cnat_nfv9_logging_info; \ - break; \ - } \ - })); \ -while (0) - - -typedef struct { - /* - * spp_ctx_alloc() call failed - */ - u64 nfv9_logging_context_creation_fail_count; - - /* - * Cannot send the existing logging pkt, so cannot create - * any additional packets for logging purposes - */ - u64 nfv9_logging_context_creation_deferred_count; - - /* - * Cannot send the existing logging pkt due to cnat_rewrite_output - * superframe being full. - */ - u64 nfv9_downstream_constipation_count; - - /* - * buffer for spp_ctx_alloc() call failed - */ - u64 nfv9_logging_context_buffer_allocation_fail_count; - -} cnat_global_counters_t; - - -extern cnat_global_counters_t cnat_global_counters; - -extern u16 *cnat_portmap_indices_by_vrf; -extern cnat_vrfmap_t *cnat_portmap_by_vrf; -extern cnat_portmap_t **cnat_portmaps; -extern u16 **cnat_portmaps_inuse; - -extern cnat_vrfmap_t *cnat_map_by_vrf; - -/* - * Special define to indicate that the VRF map index entry is empty - */ -#define VRF_MAP_ENTRY_EMPTY 0xffff -extern u16 vrf_map_array[CNAT_MAX_VRFMAP_ENTRIES]; - -extern cnat_svi_params_entry svi_params_array[CNAT_MAX_VRFMAP_ENTRIES]; -extern cnat_ingress_vrfid_name_entry vrfid_name_map[MAX_VRFID]; - -extern index_slist_t *cnat_out2in_hash; -extern index_slist_t *cnat_in2out_hash; -extern index_slist_t *cnat_user_hash; -extern index_slist_t *cnat_session_hash; - -typedef enum { - CNAT_DB_IN2OUT = 0, - CNAT_DB_OUT2IN, -} cnat_db_which_t; - -typedef enum { - CNAT_NO_ICMP_MSG =0, - CNAT_ICMP_MSG, -} cnat_icmp_msg_t; - -typedef struct { - cnat_errno_t error; - cnat_icmp_msg_t gen_icmp_msg; - u32 svi_addr; -} cnat_gen_icmp_info; - -typedef cnat_vrfmap_t nat64_vrfmap_t; -typedef cnat_portmap_v2_t nat64_portmap_v2_t; - -#define CNAT_V4_GET_HASH(key64, hash, mask) \ - a = key64; \ - b = c = 0x9e3779b97f4a7c13LL; \ - /* Jenkins hash, arbitrarily use c as the "answer" */ \ - hash_mix64(a, b, c); \ - hash = c & mask; - -#define CNAT_V4_GET_SESSION_HASH(main_index, in_addr, port, vrf, hash, mask) \ - a = main_index ^ in_addr ^ port ^ vrf; \ - b = c = 0x9e3779b9; \ - /* Jenkins hash, arbitrarily use c as the "answer" */ \ - hash_mix32(a, b, c); \ - hash = c & mask; - -#define CNAT_V4_GET_FRAG_HASH(key64, key32, hash, mask) \ - a = key64; \ - b = key32; \ - c = 0x9e3779b97f4a7c13LL; \ - hash_mix64(a, b, c); \ - hash = c % mask; - -#define CNAT_DB_UPDATE_IN2OUT_TIMER \ - db->entry_expires = cnat_current_time; \ - db->in2out_pkts++; - -#define CNAT_DB_TIMEOUT_RST(db) \ - if(PREDICT_TRUE(db->entry_expires != 0 )) \ - db->entry_expires = cnat_current_time; - -#define DEBUG_I2O_DROP(debug_flag) \ -if (debug_i_flag & debug_flag) { \ - cnat_db_debug_i2o_drop(&ki); \ -} - - -cnat_main_db_entry_t *cnat_main_db_create (cnat_db_create_args_t *a); -void cnat_main_db_entry_delete(cnat_main_db_entry_t *ep); - -void cnat_delete_main_db_entry(cnat_main_db_entry_t *ep); -void cnat_delete_main_db_entry_v2(cnat_main_db_entry_t *ep); - - -cnat_main_db_entry_t* -cnat_get_main_db_entry(cnat_db_key_bucket_t *ki, - port_pair_t port_type, - cnat_errno_t *error, - cnat_user_db_entry_t ** user_db_entry); - -cnat_main_db_entry_t* -cnat_get_main_db_entry_v2(cnat_db_key_bucket_t *ki, - port_pair_t port_pair_type, - port_type_t port_type, - cnat_gen_icmp_info *info, - cnat_key_t *dest_info); - -cnat_main_db_entry_t* -cnat_create_static_main_db_entry_v2(cnat_db_key_bucket_t *ki, - cnat_db_key_bucket_t *ko, - cnat_vrfmap_t *my_vrfmap, - cnat_gen_icmp_info *info); - -cnat_main_db_entry_t* -cnat_create_main_db_entry_and_hash(cnat_db_key_bucket_t *ki, - cnat_db_key_bucket_t *ko, - cnat_user_db_entry_t *udb); - -cnat_user_db_entry_t* -cnat_user_db_create_entry(cnat_db_key_bucket_t *uki, - u32 portmap_index); - -cnat_user_db_entry_t* -cnat_user_db_lookup_entry(cnat_db_key_bucket_t *uki); - -cnat_main_db_entry_t* -cnat_main_db_lookup_entry(cnat_db_key_bucket_t *ki); - -cnat_main_db_entry_t* -cnat_main_db_lookup_entry_out2in (cnat_db_key_bucket_t *ko); - -void cnat_main_db_entry_dump (cnat_main_db_entry_t *db); -void cnat_db_in2out_hash_delete (cnat_main_db_entry_t *ep, cnat_user_db_entry_t *up); -void cnat_db_out2in_hash_delete (cnat_main_db_entry_t *ep); -void cnat_user_db_delete (cnat_user_db_entry_t *up); -void cnat_db_debug_i2o_drop(cnat_db_key_bucket_t *ki); - -/* - * Function to dump the Hash Table that maps if_num to uidb_index - */ -extern void cnat_if_num_hash_table_dump(void); - -#define MAIN_DB_TYPE 0 -#define SESSION_DB_TYPE 1 -u16 query_and_update_db_timeout(void *db, u8 db_type); - -u16 cnat_timeout_db_create (cnat_timeout_t t_entry); -void cnat_timeout_db_delete(cnat_key_t t_key); - -cnat_session_entry_t * -cnat_create_session_db_entry(cnat_key_t *ko, - cnat_main_db_entry_t *bdb, u8 log); - -void cnat_dest_update_main2session(cnat_main_db_entry_t *mdb, - cnat_session_entry_t *sdb); - -cnat_session_entry_t *cnat_handle_1to2_session( - cnat_main_db_entry_t *mdb, - cnat_key_t *dest_info); - -void cnat_add_dest_n_log( - cnat_main_db_entry_t *mdb, - cnat_key_t *dest_info); - -cnat_session_entry_t * - cnat_session_db_lookup_entry(cnat_key_t *ko,u32 main_db_index); - -cnat_session_entry_t * - cnat_session_db_edm_lookup_entry(cnat_key_t *ko, - u32 session_head_index, - u32 main_db_index); - - -typedef struct{ - u32 sessions; - u32 active_translations; - u32 num_dynamic_translations; - u32 num_static_translations; - u64 in2out_drops_port_limit_exceeded; - u64 in2out_drops_system_limit_reached; - u64 in2out_drops_resource_depletion; - u64 no_translation_entry_drops; - u32 num_subscribers; - u32 dummy; - u64 drops_sessiondb_limit_exceeded; -} nat44_dslite_common_stats_t; - -typedef struct { - u32 translation_delete_count; - u32 translation_create_count; - u32 out2in_forwarding_count; -} nat44_dslite_global_stats_t; - -typedef struct { - u64 v4_to_v6_tcp_seq_mismatch_drop_count; - u64 v4_to_v6_tcp_seq_mismatch_count; - u64 v4_to_v6_out2in_session_create_count; - u64 v4_to_v6_end_point_filter_drop_count; -} nat44_counters_stats_t; - -#define NAT44_STATS 0 -#define DSLITE_STATS 1 -extern nat44_dslite_common_stats_t nat44_dslite_common_stats[255]; /* 0 is for nat44 */ -extern nat44_dslite_global_stats_t nat44_dslite_global_stats[2]; /* 0 for nat44 and 1 for dslite */ -extern nat44_counters_stats_t nat44_counters_stats[CNAT_MAX_VRFMAP_ENTRIES];/*For displaying show cgn inside-vrf counters */ - -#define NAT44_COMMON_STATS nat44_dslite_common_stats[NAT44_RESERVED_INST_ID] -#define NAT44_GLOBAL_STATS nat44_dslite_global_stats[NAT44_STATS] -#define DSLITE_GLOBAL_STATS nat44_dslite_global_stats[DSLITE_STATS] -#define SESSION_LOG_ENABLE 1 -#define ALG_ENABLED_DB(db) \ - ((db->flags & CNAT_PCP_FLAG) || \ - (db->flags & CNAT_DB_FLAG_ALG_CTRL_FLOW) || \ - (db->flags & (CNAT_DB_FLAG_PPTP_TUNNEL_INIT | \ - CNAT_DB_FLAG_PPTP_TUNNEL_ACTIVE))) - - -#endif /* __CNAT_DB_H__ */ diff --git a/plugins/plugins/vcgn/cnat_db_scanner.c b/plugins/plugins/vcgn/cnat_db_scanner.c deleted file mode 100644 index 6e536d84..00000000 --- a/plugins/plugins/vcgn/cnat_db_scanner.c +++ /dev/null @@ -1,493 +0,0 @@ -/* - *--------------------------------------------------------------------------- - * cnat_db_scanner.c - cnat_db_scanner dispatch function and initialization - * - * Copyright (c) 2009-2014 Cisco and/or its affiliates. - * 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 -#include -#include -#include -#include -#include -#include -#include -#include - - -#include "cnat_db.h" -#include "cnat_logging.h" -#include "cnat_global.h" -#include "cnat_ipv4_udp.h" -#include "cnat_common_api.h" - -u32 translation_create_count, translation_delete_count; -u32 translation_create_rate, translation_delete_rate; - -u32 in2out_forwarding_count, out2in_forwarding_count; -u32 in2out_forwarding_rate, out2in_forwarding_rate; - -u32 nat44_active_translations; -u32 num_entries; -uword check_these_pool_indices[2*MAX_DB_ENTRY_SELECTED_PER_SCAN]; - -#define CNAT_DB_SCANNER_TURN_ON 5 /* just an arbitary number for easier debugging */ - -//extern u32 pcp_throttle_count; - -typedef struct { - u32 cached_next_index; - /* $$$$ add data here */ - - /* convenience variables */ - vlib_main_t * vlib_main; - vnet_main_t * vnet_main; -} cnat_db_scanner_main_t; - -cnat_db_scanner_main_t cnat_db_scanner_main; - - -static inline void check_session_for_expiry( - cnat_session_entry_t * sdb, u8 timeout_dirty - /*,dslite_table_entry_t *dslite_entry_ptr*/) -{ - void cnat_delete_session_db_entry (cnat_session_entry_t *ep, u8 log); - /* Tasks - - * 1. Check for expiry for this entry - * 2. Delete if expired - */ - u32 timeout = 0; - - switch(sdb->v4_dest_key.k.vrf & CNAT_PRO_MASK) { - case CNAT_TCP: - if (sdb->flags & CNAT_DB_FLAG_TCP_ACTIVE) { - timeout = sdb->timeout; - if(PREDICT_FALSE(timeout_dirty)) { - timeout = query_and_update_db_timeout( - (void *)sdb, SESSION_DB_TYPE); - } - if(PREDICT_TRUE(timeout == 0)) { - timeout = tcp_active_timeout; - //dslite_entry_ptr->timeout_info.tcp_active_timeout; - } - } else { - timeout = tcp_initial_setup_timeout; - //dslite_entry_ptr->timeout_info.tcp_initial_setup_timeout; - } - break; - case CNAT_UDP: - if (sdb->flags & CNAT_DB_FLAG_UDP_ACTIVE) { - timeout = sdb->timeout; - if(PREDICT_FALSE(timeout_dirty)) { - timeout = query_and_update_db_timeout( - (void *)sdb, SESSION_DB_TYPE); - } - - if(PREDICT_TRUE(timeout == 0)) { - timeout = udp_act_session_timeout; - //dslite_entry_ptr->timeout_info.udp_act_session_timeout; - } - } else { - timeout = udp_init_session_timeout; - //dslite_entry_ptr->timeout_info.udp_init_session_timeout; - } - break; - case CNAT_ICMP: - timeout = icmp_session_timeout; - //dslite_entry_ptr->timeout_info.icmp_session_timeout; - break; - case CNAT_PPTP: - timeout = pptp_cfg.timeout; - break; - default: - return; - } - /* Changes required for clearing sessions */ - if (PREDICT_FALSE((sdb->entry_expires == 0) || - (sdb->entry_expires + timeout < cnat_current_time))) { - cnat_delete_session_db_entry(sdb, TRUE); - } -} - -static u8 handle_db_scan_for_sessions( - cnat_main_db_entry_t *db, int *dirty_index, uword db_index - /* ,dslite_table_entry_t *dslite_entry_ptr */) -{ - /* Tasks - - * 1. Traverse through the sessions and check for timeouts - * 2. Delete sessions that have exipred - * 3. Check if the db has only one session remaining.. if so, - * the details of the session has to be moved to main db - * and session db entry needs to be freed - * 4. If db does not have any sessions left, the db itself - * needs to be deleted. - */ - u32 nsessions, session_index_head, session_index; - cnat_session_entry_t *sdb; - u8 timeout_dirty = FALSE; - - if(PREDICT_FALSE(*dirty_index == db_index)) { - *dirty_index = -1; - } - if(PREDICT_FALSE(timeout_dirty_flag == 1)) { - timeout_dirty_flag = 0; - *dirty_index = db_index; - timeout_dirty = TRUE; - } - - session_index_head = session_index = db->session_head_index; - nsessions = db->nsessions; - - do { - sdb = cnat_session_db + session_index; - if(PREDICT_FALSE(!sdb)) { - //TO DO: Debug msg? - return FALSE; - } - session_index = sdb->main_list.next; - check_session_for_expiry(sdb, timeout_dirty /*,dslite_entry_ptr*/); - nsessions--; /* To ensure that we do not get in to an infinite loop */ - } while(session_index != session_index_head - && db->session_head_index != EMPTY && - nsessions); - - /* Note.. the code below assumes that while deleting the - * sessions, we do not delete the main db entry if it does - * not have any sessions anymore - */ - if(PREDICT_FALSE((!db->nsessions) && - (!(db->flags & CNAT_DB_FLAG_STATIC_PORT)))) { - cnat_delete_main_db_entry_v2(db); - return TRUE; /* to indicate that main db was deleted */ - } - return FALSE; -} - -static void cnat_db_scanner(void) -{ - cnat_main_db_entry_t * db; - u32 timeout; - cnat_vrfmap_t *my_vrfmap __attribute__((unused)) = 0; - static int dirty_index = -1; - u16 instance __attribute__((unused)); - //dslite_table_entry_t *dslite_entry_ptr; - u32 i; - uword db_index; - //pcp_throttle_count = 0; - - for (i = 0; i < num_entries; i++) { - db_index = check_these_pool_indices[i]; - db = cnat_main_db + db_index; - timeout=0; - my_vrfmap = 0; - -#if 0 - if(PREDICT_FALSE(db->flags & CNAT_PCP_FLAG)) { - - if(db->proto_data.seq_pcp.pcp_lifetime < cnat_current_time) { - /* mark as implicit */ - db->flags &= ~CNAT_PCP_FLAG; - } - continue; - } - -#endif - if(PREDICT_FALSE(db->nsessions > 1)) { - if(PREDICT_FALSE( - handle_db_scan_for_sessions(db, &dirty_index, db_index /*,dslite_entry_ptr */))) { - continue; - } else if(PREDICT_TRUE(db->nsessions > 1)) { - continue; - } - /* if there is exactly one dest left.. let it fall through - * and check if that needs to be deleted as well - */ - } - -#if 0 - if (PREDICT_FALSE(db->flags & CNAT_DB_FLAG_STATIC_PORT)) { - if (PREDICT_FALSE(db->flags & CNAT_DB_DSLITE_FLAG)) { - if(PREDICT_FALSE( - ((dslite_entry_ptr->nf_logging_policy != SESSION_LOG_ENABLE) && - (dslite_entry_ptr->syslog_logging_policy != SESSION_LOG_ENABLE)) - || (db->nsessions !=1))) { - continue; - } - } else { - my_vrfmap = cnat_map_by_vrf + db->vrfmap_index; - if(PREDICT_FALSE( - ((my_vrfmap->nf_logging_policy != SESSION_LOG_ENABLE) && - (my_vrfmap->syslog_logging_policy != SESSION_LOG_ENABLE)) || - (db->nsessions !=1))) { - continue; - } - } - } -#endif - - switch(db->in2out_key.k.vrf & CNAT_PRO_MASK) { - case CNAT_TCP: - if (db->flags & CNAT_DB_FLAG_TCP_ACTIVE) { - timeout = db->timeout; - if(PREDICT_FALSE(dirty_index == db_index)) { - dirty_index = -1; - } - if(PREDICT_FALSE(timeout_dirty_flag == 1)) { - timeout_dirty_flag = 0; - dirty_index = db_index; - } - if(PREDICT_FALSE(dirty_index != -1)) { - timeout = query_and_update_db_timeout( - (void *)db, MAIN_DB_TYPE); - } - if(PREDICT_TRUE(timeout == 0)) { - timeout = tcp_active_timeout; - } - } else { - timeout = tcp_initial_setup_timeout; - } - break; - case CNAT_UDP: - if (db->flags & CNAT_DB_FLAG_UDP_ACTIVE) { - timeout = db->timeout; - if(PREDICT_FALSE(dirty_index == db_index)) { - dirty_index = -1; - } - if(PREDICT_FALSE(timeout_dirty_flag == 1)) { - timeout_dirty_flag = 0; - dirty_index = db_index; - } - if(PREDICT_FALSE(dirty_index != -1)) { - timeout = query_and_update_db_timeout( - (void *)db, MAIN_DB_TYPE); - } - if(PREDICT_TRUE(timeout == 0)) { - timeout = udp_act_session_timeout; - } - } else { - timeout = udp_init_session_timeout; - } - break; - case CNAT_ICMP: - timeout = icmp_session_timeout; - break; - case CNAT_PPTP: - timeout = pptp_cfg.timeout; - break; - default: - continue; - } - - - /* Ref: CSCtu97536 */ - if (PREDICT_FALSE((db->entry_expires == 0) || - (db->entry_expires + timeout < cnat_current_time))) { -#if 0 - if (PREDICT_FALSE(db->flags & CNAT_DB_FLAG_STATIC_PORT)) { - if (PREDICT_FALSE(db->flags & CNAT_DB_DSLITE_FLAG)) { - instance = db->dslite_nat44_inst_id; - } else { - instance = NAT44_RESERVED_INST_ID; - cnat_session_log_nat44_mapping_delete(db, 0, my_vrfmap); - } - - /* Reset the session details */ - db->nsessions = 0; - db->dst_ipv4 = 0; - db->dst_port = 0; - db->flags &= ~(CNAT_DB_FLAG_TCP_ACTIVE | CNAT_DB_FLAG_UDP_ACTIVE - | CNAT_DB_FLAG_ALG_ENTRY); - db->timeout = 0; - db->entry_expires = 0; - db->alg.delta = 0; - db->proto_data.seq_pcp.tcp_seq_num = 0; - continue; - } -#endif - //printf("DELETING DB ENTRY FOR 0x%x\n", db->in2out_key.k.ipv4); - cnat_delete_main_db_entry_v2(db); - } - //free(check_these_pool_indices[i]); - } -} - -static void walk_the_db (void) -{ - pool_header_t *h = pool_header(cnat_main_db); - u32 db_uword_len; - static u32 base_index = 0, free_bitmap_index = 0; - int bits_scanned = 0, i; - uword inuse_bitmap; - - num_entries=0; - - /* Across all db entries... */ - db_uword_len = vec_len(cnat_main_db) / NUM_BITS_IN_UWORD; - if (PREDICT_FALSE(vec_len(cnat_main_db) % NUM_BITS_IN_UWORD)) { - /* - * It should not come here as in cnat_db_init_v2() - * it is made multiple of NUM_BITS_IN_UWORD - */ - ASSERT(0); - return ; - } - - if (PREDICT_FALSE(! db_uword_len)) - return ; - - while (bits_scanned < MAX_DB_ENTRY_PER_SCAN) { - - if (PREDICT_FALSE(free_bitmap_index < vec_len(h->free_bitmap))) { - - /* free_bitmap exists and it is not all 0 */ - - inuse_bitmap = ~(h->free_bitmap[free_bitmap_index]); - i = 0; - while (inuse_bitmap) { - - /* Check to see if the index is in use */ - if (PREDICT_FALSE((inuse_bitmap >> i) & 1)) { - check_these_pool_indices[num_entries] = base_index + i; - inuse_bitmap &= ~((uword) 1 << i); - num_entries++; - } - i++; - } // while (inuse_bitmap) - } else { - - /* - * 64-bit entry is 0, means all 64 entries are allocated. - * So, simply add all 64 entries here. - * No need to form inuse_bitmap, check and reset bits - */ - for (i=0; ifree_bitmap)) - - /* Update free_bitmap_index and base_index for next run */ - if (PREDICT_FALSE(free_bitmap_index == db_uword_len - 1)) { - /* wrap-around for next run */ - free_bitmap_index = 0; - base_index = 0; - } else { - free_bitmap_index ++; - base_index += NUM_BITS_IN_UWORD; - } - - /* increment # of bits scanned */ - bits_scanned += NUM_BITS_IN_UWORD; - - /* Found enough entries to check ? */ - if (PREDICT_FALSE(num_entries >= MAX_DB_ENTRY_SELECTED_PER_SCAN)) - { - /* This check is introduced to keep fixed MAX scan entry value */ - /* This is very much required when we do scanning for NAT64 */ - /* please check comments in cnat_db_scanner() & - * handler_nat64_db_scanner() */ - if (num_entries >= MAX_COMBINED_DB_ENTRIES_PER_SCAN) { - num_entries = MAX_COMBINED_DB_ENTRIES_PER_SCAN; - } - break; - } - - } // while (bits_scanned < MAX_DB_ENTRY_PER_SCAN) - - if (PREDICT_FALSE(num_entries > 0)) { - //printf("%s: num_entries [%d]\n", __func__, num_entries); - cnat_db_scanner(); - } - return ; -} - -static uword cnat_db_scanner_fn (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - f64 timeout = 0.01; /* timeout value in sec (10 ms) */ - static u8 timeout_count = 0; - - uword event_type; - uword * event_data = 0; - /* Wait until vCGN is configured */ - while (1) { - /* Assigning a huge timeout value, vCGN may or - * may not get configured within this timeout */ - vlib_process_wait_for_event_or_clock (vm, 1e9); - event_type = vlib_process_get_events (vm, &event_data); - - /* check whether the process is waken up by correct guy, - * otherwise continue waiting for the vCGN config */ - if (event_type == CNAT_DB_SCANNER_TURN_ON) { - break; - } - } - - while(1) { - vlib_process_suspend(vm, timeout); - - /* Above suspend API should serve the purpose, no need to invoke wait API */ - /* vlib_process_wait_for_event_or_clock (vm, timeout); */ - - /* Lets make use of this timeout for netflow packet sent */ - if (timeout_count < 100) { /* 100*10 ms = 1 sec */ - timeout_count++; - } else { - if (nfv9_configured) { - handle_pending_nfv9_pkts(); - } - timeout_count = 0; - } - /* Do we need this ? */ - //event_type = vlib_process_get_events (vm, &event_data); - cnat_current_time = (u32)vlib_time_now (vm); - if (cnat_db_init_done) { - walk_the_db(); - } - } - - return 0; -} - - -VLIB_REGISTER_NODE (cnat_db_scanner_node) = { - .function = cnat_db_scanner_fn, - .type = VLIB_NODE_TYPE_PROCESS, - .name = "cnat-db-scanner", - .process_log2_n_stack_bytes = 18, -}; - -clib_error_t *cnat_db_scanner_init (vlib_main_t *vm) -{ - cnat_db_scanner_main_t *mp = &cnat_db_scanner_main; - - mp->vlib_main = vm; - mp->vnet_main = vnet_get_main(); - - return 0; -} - -void cnat_scanner_db_process_turn_on(vlib_main_t *vm) -{ - vlib_process_signal_event (vm, cnat_db_scanner_node.index, - CNAT_DB_SCANNER_TURN_ON, 0); - return; -} - -VLIB_INIT_FUNCTION (cnat_db_scanner_init); - diff --git a/plugins/plugins/vcgn/cnat_db_v2.c b/plugins/plugins/vcgn/cnat_db_v2.c deleted file mode 100644 index 2b43849d..00000000 --- a/plugins/plugins/vcgn/cnat_db_v2.c +++ /dev/null @@ -1,3802 +0,0 @@ -/* - *------------------------------------------------------------------ - * cnat_db_v2.c - translation database definitions - * - * Copyright (c) 2007-2013 Cisco and/or its affiliates. - * 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 -#include -#include -#include -#include -#include -#include -#include - -#include "cnat_db.h" -#include "cnat_config.h" -#include "cnat_global.h" -#include "cnat_v4_functions.h" -#include "cnat_log_api.h" -#include "cnat_cli.h" -#include "spp_platform_trace_log.h" -#include "cnat_bulk_port.h" -#include "nat64_db.h" -#include "dslite_db.h" -#include "cnat_config_api.h" - -#define HASH_TABLE_SIZE 8192 // hash table size -#define THROTTLE_TIME 180 // throttle time value for out of port msg/user - -u8 cnat_db_init_done = 0; - -typedef struct { - /* Locks for multi thread support */ - CLIB_CACHE_LINE_ALIGN_MARK(cacheline0); - pthread_spinlock_t *main_db_lockp; - pthread_spinlock_t *user_db_lockp; - pthread_spinlock_t *session_db_lockp; - - u32 cached_next_index; - /* $$$$ add data here */ - - /* convenience variables */ - vlib_main_t * vlib_main; - vnet_main_t * vnet_main; -} cnat_db_v2_main_t; - -cnat_db_v2_main_t cnat_db_v2_main; - -#if 1 -/* TOBE_PORTED : Remove the following once fixed */ -#undef PREDICT_TRUE -#undef PREDICT_FALSE -#define PREDICT_TRUE(x) (x) -#define PREDICT_FALSE(x) (x) -#endif - -#define foreach_cnat_db_v2_error \ -_(DROP, "error-drop packets") - -typedef enum { -#define _(sym,str) CNAT_DB_V2_##sym, - foreach_cnat_db_v2_error -#undef _ - CNAT_DB_V2_N_ERROR, -} cnat_db_v2_error_t; - -static char * cnat_db_v2_error_strings[] __attribute__((unused)) = { -#define _(sym,string) string, - foreach_cnat_db_v2_error -#undef _ -}; - - -void cnat_table_entry_fill_map(u32 start_addr, u32 end_addr, - cnat_portmap_v2_t **port_map_holder) -{ - u32 this_start_addr, this_end_addr, this_addr, new; - u32 loop_count; - u32 pm_len, i; - cnat_portmap_v2_t *my_pm =0; - cnat_portmap_v2_t *pm = 0; - - my_instance_number = 0; - - this_start_addr = start_addr; - this_end_addr = end_addr; - - /* - * How many new addresses are getting added ?? - */ - /* commenting this. Right now end - start will be for this vCGN instance */ - //new = ((this_end_addr - this_start_addr) / MAX_CORES_PER_PARTITION) + 1; - new = (this_end_addr - this_start_addr) + 1; - - pm = *port_map_holder; - pm_len = vec_len(pm); -#if DEBUG_NOT_COMMENTED - printf("this_start_addr = 0x%08X, this_end_addr = 0x%08X, Num Addr = %d\n", - this_start_addr, this_end_addr, new); - printf("pm_len = %d\n", pm_len); -#endif - /* Check whether the address pool add requested already exists */ - my_pm = pm; - for(i = 0; i< pm_len; i++) { - if(my_pm->ipv4_address == this_start_addr) { - printf("address pool with addr 0x%08X exists\n", this_start_addr); - return; - } - my_pm++; - } - - /* - * For now give a warning message only.... - */ -#if 0 - if ((total_address_pool_allocated + new) > - CNAT_MAX_ADDR_POOL_SIZE_PER_CORE) { - printf("address pool size (%d) would cross permissible limit (%u) \n", - (total_address_pool_allocated + new), - CNAT_MAX_ADDR_POOL_SIZE_PER_CORE); - } -#endif - - total_address_pool_allocated += new; - vec_add2(pm, my_pm, new); - -#if DEBUG_NOT_COMMENTED - printf("total_address_pool_allocated changed from %d to %d (added %d)", - (total_address_pool_allocated - new), - total_address_pool_allocated, new); - printf("vec add is ok\n"); -#endif - - memset(my_pm, 0, new*sizeof(*my_pm)); - this_addr = this_start_addr; - loop_count = 0; /* Sanity counter */ - - while (this_addr <= this_end_addr) { -#if DEBUG_NOT_COMMENTED - printf("loop %d: this addr = 0x%08X\n", loop_count+1, this_addr); -#endif - my_pm->ipv4_address = this_addr; - /* - * Set all bits to "1" indicating all ports are free - */ - memset(my_pm->bm, 0xff, - (((BITS_PER_INST + BITS(uword)-1)/BITS(uword))*(sizeof(uword)))); - //this_addr += MAX_CORES_PER_PARTITION; - this_addr += 1; - my_pm++; - loop_count++; - } - /* - * We should have loop_count same as the new value - */ - if (loop_count != new) { - printf("Mismatch in loop_count (%d) != new (%d)\n", - loop_count, new); - } - - *port_map_holder = pm; - -#if DEBUG_NOT_COMMENTED - printf("revised pm len %d\n", vec_len(*port_map_holder)); -#endif - - return; -} - - -void cnat_delete_session_db_entry (cnat_session_entry_t *ep, u8 log); -void handle_cnat_port_exceeded_logging( - cnat_user_db_entry_t *udb, - cnat_key_t * key, - cnat_vrfmap_t *vrfmap); - -cnat_global_counters_t cnat_global_counters; -u32 last_log_timestamp = 0; -u32 last_user_dyn_port_exc_timestamp = 0; -u32 last_user_stat_port_exc_timestamp = 0; - -index_slist_t *cnat_out2in_hash; -index_slist_t *cnat_in2out_hash; -index_slist_t *cnat_user_hash; -index_slist_t *cnat_timeout_hash; -index_slist_t *cnat_session_hash; - -cnat_main_db_entry_t *cnat_main_db; -cnat_user_db_entry_t *cnat_user_db; -cnat_session_entry_t *cnat_session_db; -cnat_timeout_db_entry_t *cnat_timeout_db; - -cgse_nat_db_entry_t *cgse_nat_db; -cgse_nat_user_db_entry_t *cgse_user_db; -cgse_nat_session_db_entry_t *cgse_session_db; - -nat44_dslite_common_stats_t nat44_dslite_common_stats[255]; /* 0 is for nat44 */ -nat44_dslite_global_stats_t nat44_dslite_global_stats[2]; /* 0 for nat44 and 1 for dslite */ -nat44_counters_stats_t nat44_counters_stats[CNAT_MAX_VRFMAP_ENTRIES]; -/*For displaying show cgn inside-vrf counters */ - -/* - * This is the pool of vrf map structures used by latest main-db functions - */ -cnat_vrfmap_t *cnat_map_by_vrf; - -/* - * Have a mapping table of vrf_id-->vrf_map_index - * This helps in easily getting the vrf_map structure during - * main-db create paths - */ -u16 vrf_map_array[CNAT_MAX_VRFMAP_ENTRIES]; -cnat_svi_params_entry svi_params_array[CNAT_MAX_VRFMAP_ENTRIES]; -cnat_ingress_vrfid_name_entry vrfid_name_map[MAX_VRFID] = {{0}}; -u64 in2out_drops_port_limit_exceeded; -u64 in2out_drops_system_limit_reached; -u64 in2out_drops_resource_depletion; -u64 no_translation_entry_drops; -u32 no_sessions; - -#define CNAT_SET_ICMP_MSG_INFO \ -if (PREDICT_TRUE((my_vrfmap->i_vrf < CNAT_MAX_VRFMAP_ENTRIES) && \ - (svi_params_array[my_vrfmap->i_vrf].ipv4_addr))) { \ - info->gen_icmp_msg = icmp_msg_gen_allowed(); \ - info->svi_addr = svi_params_array[my_vrfmap->i_vrf].ipv4_addr; \ -} - -#define CNAT_DEBUG_INSIDE_ERR(err) \ -if (((protocol == CNAT_UDP) && \ - (debug_i_flag & CNAT_DEBUG_ERR_UDP)) || \ - ((protocol == CNAT_TCP) && \ - (debug_i_flag & CNAT_DEBUG_ERR_TCP)) || \ - ((protocol == CNAT_ICMP) && \ - (debug_i_flag & CNAT_DEBUG_ERR_ICMP))) { \ - cnat_db_debug_error(&u_ki, err); \ -} - -#define DSLITE_DEBUG_INSIDE_ERR(err) \ -if (((protocol == CNAT_UDP) && \ - (debug_i_flag & CNAT_DEBUG_ERR_UDP)) || \ - ((protocol == CNAT_TCP) && \ - (debug_i_flag & CNAT_DEBUG_ERR_TCP)) || \ - ((protocol == CNAT_ICMP) && \ - (debug_i_flag & CNAT_DEBUG_ERR_ICMP))) { \ - dslite_db_debug_error(&u_ki, err); \ -} - -#define PORT_LIMIT_LOW_THRESHOLD_FOR_SYSLOG 7 -/* If the max_limit is less than 10, no meaningful throttling can be - * done.. so, log only once per user and never clear the flag - * once the user exceeds limit - */ -#define CHECK_CLEAR_PORT_LIMIT_EXCEED_FLAG(udb, max_limit) \ - if(PREDICT_FALSE(udb->flags & CNAT_USER_DB_PORT_LIMIT_EXCEEDED)) { \ - if(udb->ntranslations < \ - ((max_limit/10)*PORT_LIMIT_LOW_THRESHOLD_FOR_SYSLOG) && \ - max_limit >= 10) { \ - udb->flags = udb->flags & (~CNAT_USER_DB_PORT_LIMIT_EXCEEDED); \ - } \ - } - -#ifdef TOBE_PORTED -/* Commented to remove unused variable warning */ -static char *debug_db_error[] = { - "no error", /* CNAT_SUCCESS */ - "no config", /*CNAT_NO_CONFIG*/ - "not in run state", /*CNAT_NO_VRF_RUN*/ - "no pool for any", /*CNAT_NO_POOL_ANY*/ - "no port for any", /*CNAT_NO_PORT_ANY*/ - "bad in use for any", /*CNAT_BAD_INUSE_ANY*/ - "not found for any", /*CNAT_NOT_FOUND_ANY*/ - "invalid index for direct", /*CNAT_INV_PORT_DIRECT*/ - "deleted addr for direct", /*CNAT_DEL_PORT_DIRECT*/ - "bad in use for direct",/*CNAT_BAD_INUSE_DIRECT*/ - "not found for direct",/*CNAT_NOT_FOUND_DIRECT*/ - "out of port limit", /*CNAT_OUT_LIMIT*/ - "main db limit", /*CNAT_MAIN_DB_LIMIT*/ - "user db limit", /*CNAT_USER_DB_LIMIT*/ - "not static port", /*CNAT_NOT_STATIC_PORT*/ - "bad static port request", /*CNAT_BAD_STATIC_PORT_REQ*/ - "not this core", /*CNAT_NOT_THIS_CORE*/ - "parser error", /*CNAT_ERR_PARSER*/ - "invalid msg id", /*CNAT_ERR_INVALID_MSG_ID*/ - "invalid msg size", /*CNAT_ERR_INVALID_MSG_SIZE*/ - "invalid payload size", /*CNAT_ERR_INVALID_PAYLOAD_SIZE*/ - "bad tcp udp port", /*CNAT_ERR_BAD_TCP_UDP_PORT*/ - "bulk single failure", /*CNAT_ERR_BULK_SINGLE_FAILURE*/ - "xlat id invalid", /*CNAT_ERR_XLAT_ID_INVALID*/ - "xlat v6 prefix invalid", /*CNAT_ERR_XLAT_V6_PREFIX_INVALID*/ - "xlat v4 prefix invalid", /*CNAT_ERR_XLAT_V4_PREFIX_INVALID*/ - "xlat tcp mss invalid", /*CNAT_ERR_XLAT_TCP_MSS_INVALID*/ - "6rd id invalid", /*CNAT_ERR_6RD_ID_INVALID*/ - "6rd v4 tunnel src invalid", /*CNAT_ERR_6RD_V4_TUNNEL_SRC_INVALID*/ - "6rd v6 prefix invalid", /*CNAT_ERR_6RD_V6_PREFIX_INVALID*/ - "6rd v6 BR unicast invalid", /*CNAT_ERR_6RD_V6_BR_UNICAST_INVALID*/ - "6rd v4 prefix masklen invalid", /*CNAT_ERR_6RD_V4_PREFIX_MASK_LEN_INVALID*/ - "6rd v4 suffix masklen invalid", /*CNAT_ERR_6RD_V4_SUFFIX_MASK_LEN_INVALID*/ - "6rd v4 combo masklen invalid", /*CNAT_ERR_6RD_V4_COMBO_MASK_LEN_INVALID*/ - "6rd tunnel mtu invalid", /*CNAT_ERR_6RD_TUNNEL_MTU_INVALID*/ - "6rd tunnel ttl invalid", /*CNAT_ERR_6RD_TUNNEL_TTL_INVALID*/ - "6rd tunnel tos invalid", /*CNAT_ERR_6RD_TUNNEL_TOS_INVALID*/ -}; -#endif - -f64 port_log_timestamps[HASH_TABLE_SIZE]; /* 32 KB array per core */ - -void port_exceeded_msg_log (u32 src_addr, u16 i_vrf) -{ - u32 hash_value; - f64 current_timestamp; - vlib_main_t *vlib_main; - - vlib_main = vlib_get_main(); - current_timestamp = vlib_time_now((vlib_main_t *) vlib_main); - - hash_value = ((src_addr >> 16) ^ ((src_addr & 0xffff) ^ i_vrf)) % (1024*8); - - if (PREDICT_FALSE((current_timestamp - port_log_timestamps[hash_value]) > THROTTLE_TIME)) { - u32 arg[2] = {i_vrf, src_addr}; - /* update timestamp */ - port_log_timestamps[hash_value] = current_timestamp; - spp_printf(CNAT_USER_OUT_OF_PORTS, 2, arg); - } - - return ; -} - -static void log_port_alloc_error(cnat_errno_t error, cnat_key_t *k) -{ - u32 error_code; - u32 arr[] = {k->k.vrf, k->k.ipv4, k->k.port}; - switch (error) - { - case CNAT_NO_POOL_ANY: - error_code = CNAT_NO_POOL_FOR_ANY_ERROR; - break; - case CNAT_NO_PORT_ANY: - error_code = CNAT_NO_PORT_FOR_ANY_ERROR; - break; - case CNAT_ERR_PARSER: - error_code = CNAT_WRONG_PORT_ALLOC_TYPE; - break; - case CNAT_BAD_INUSE_ANY: - error_code = CNAT_BAD_INUSE_ANY_ERROR; - break; - case CNAT_BAD_INUSE_DIRECT: - error_code = CNAT_BAD_INUSE_DIRECT_ERROR; - break; - case CNAT_NOT_FOUND_ANY: - error_code = CNAT_NOT_FOUND_ANY_ERROR; - break; - case CNAT_NOT_FOUND_DIRECT: - error_code = CNAT_NOT_FOUND_DIRECT_ERROR; - break; - case CNAT_INV_PORT_DIRECT: - error_code = CNAT_INV_PORT_FOR_DIRECT_ERROR; - break; - default: - error_code = CNAT_NEW_PORT_ALLOC_ERROR; /* If this code is seen in the log, - it means, new error codes are to be added here */ - break; - } - spp_printf(error_code, 3, arr); -} - -void cnat_db_debug_error(cnat_db_key_bucket_t *u_ki, - cnat_errno_t error) -{ - if (PREDICT_FALSE((u_ki->k.k.vrf == debug_i_vrf) && - ((u_ki->k.k.ipv4 >= debug_i_addr_start) && - (u_ki->k.k.ipv4 <= debug_i_addr_end)))) { -#ifdef DEBUG_PRINTF_ENABLED - PLATFORM_DEBUG_PRINT("failed to allocate port due to %s " - "for i-vrf 0x%x addr 0x%x port 0x%x\n", - debug_db_error[error], u_ki->k.k.vrf, - u_ki->k.k.ipv4, u_ki->k.k.port); -#endif - { - u32 arg[] = {u_ki->k.k.vrf, u_ki->k.k.ipv4, u_ki->k.k.port}; - spp_printf(error, 3, arg); - } - } -} - -void dslite_db_debug_error(dslite_db_key_bucket_t *u_ki, - cnat_errno_t error) -{ - if (PREDICT_FALSE((u_ki->dk.ipv4_key.k.vrf == debug_i_vrf) && - ((u_ki->dk.ipv4_key.k.ipv4 >= debug_i_addr_start) && - (u_ki->dk.ipv4_key.k.ipv4 <= debug_i_addr_end)))) { -#ifdef DEBUG_PRINTF_ENABLED - PLATFORM_DEBUG_PRINT("failed to allocate port due to %s " - "for i-vrf 0x%x addr 0x%x port 0x%x\n", - debug_db_error[error], u_ki->dk.ipv4_key.k.vrf, - u_ki->dk.ipv4_key.k.ipv4, u_ki->dk.ipv4_key.k.port); -#endif - { - u32 arg[] = {u_ki->dk.ipv4_key.k.vrf, u_ki->dk.ipv4_key.k.ipv4, u_ki->dk.ipv4_key.k.port}; - spp_printf(error, 3, arg); - } - } -} - -void cnat_db_debug_i2o_drop(cnat_db_key_bucket_t *ki) -{ - if (PREDICT_FALSE(((ki->k.k.vrf & CNAT_VRF_MASK) == debug_i_vrf) && - ((ki->k.k.ipv4 >= debug_i_addr_start) && - (ki->k.k.ipv4 <= debug_i_addr_end)))) { -#ifdef DEBUG_PRINTF_ENABLED - PLATFORM_DEBUG_PRINT("pakcet[i-vrf 0x%x addr 0x%x port 0x%x] dropped\n", - ki->k.k.vrf, ki->k.k.ipv4, ki->k.k.port); -#endif - { - u32 arg[] = {ki->k.k.vrf, ki->k.k.ipv4, ki->k.k.port}; - spp_printf(CNAT_PACKET_DROP_ERROR, 3, arg); - } - } -} - -void cnat_db_in2out_hash_delete (cnat_main_db_entry_t *ep, cnat_user_db_entry_t *up) -{ - u64 a, b, c; - u32 index, bucket; - cnat_main_db_entry_t *this, *prev; - -#ifdef DSLITE_DEF - if (PREDICT_FALSE(ep->flags & CNAT_DB_DSLITE_FLAG)) { - dslite_key_t dk = { - {up->ipv6[0], up->ipv6[1], up->ipv6[2], up->ipv6[3]} , - {ep->in2out_key.k.ipv4, ep->in2out_key.k.port, ep->in2out_key.k.vrf} - }; - DSLITE_V6_GET_HASH((&dk), - bucket, - CNAT_MAIN_HASH_MASK); - DSLITE_PRINTF(1, "Delete1 DSL main hash bucket ..%u\n", bucket); - } else { - CNAT_V4_GET_HASH(ep->in2out_key.key64, - bucket, CNAT_MAIN_HASH_MASK) - DSLITE_PRINTF(1, "Delete1 NAT44 main hash bucket ..%u\n", bucket); - } -#else - CNAT_V4_GET_HASH(ep->in2out_key.key64, - bucket, CNAT_MAIN_HASH_MASK) -#endif - - index = cnat_in2out_hash[bucket].next; - - ASSERT(index != EMPTY); - - prev = 0; - do { - this = cnat_main_db + index; - if (PREDICT_TRUE(this == ep)) { - if (prev == 0) { - cnat_in2out_hash[bucket].next = ep->in2out_hash.next; - return; - } else { - prev->in2out_hash.next = ep->in2out_hash.next; - return; - } - } - prev = this; - index = this->in2out_hash.next; - } while (index != EMPTY); - - ASSERT(0); -} - -void cnat_db_out2in_hash_delete (cnat_main_db_entry_t *ep) -{ - u64 a, b, c; - u32 index, bucket; - cnat_main_db_entry_t *this, *prev; - - CNAT_V4_GET_HASH(ep->out2in_key.key64, - bucket, CNAT_MAIN_HASH_MASK) - - index = cnat_out2in_hash[bucket].next; - - ASSERT(index != EMPTY); - - prev = 0; - do { - this = cnat_main_db + index; - if (PREDICT_TRUE(this == ep)) { - if (prev == 0) { - cnat_out2in_hash[bucket].next = ep->out2in_hash.next; - return; - } else { - prev->out2in_hash.next = ep->out2in_hash.next; - return; - } - } - prev = this; - index = this->out2in_hash.next; - } while (index != EMPTY); - - ASSERT(0); -} - -cnat_main_db_entry_t* -cnat_main_db_lookup_entry(cnat_db_key_bucket_t *ki) -{ - u64 a, b, c; - u32 index; - cnat_main_db_entry_t *db; - - CNAT_V4_GET_HASH(ki->k.key64, - ki->bucket, - CNAT_MAIN_HASH_MASK); - - index = cnat_in2out_hash[ki->bucket].next; - if (PREDICT_TRUE(index == EMPTY)) { - return (NULL); - } - - do { - db = cnat_main_db + index; - if (PREDICT_TRUE(db->in2out_key.key64 == ki->k.key64)) { - return db; - } - index = db->in2out_hash.next; - } while (index != EMPTY); - - return (NULL); -} - -void cnat_user_db_delete (cnat_user_db_entry_t *up) -{ - u64 a, b, c; - u32 index, bucket; - cnat_user_db_entry_t *this, *prev; - - if (PREDICT_FALSE(up->flags & CNAT_USER_DB_NAT64_FLAG) != 0) { - /* Preventive check - Not a NAT44 entry */ - return; - } - - pthread_spin_lock(cnat_db_v2_main.user_db_lockp); -#if 1 - if(PREDICT_FALSE(up->flags & CNAT_USER_DB_DSLITE_FLAG)) { - dslite_key_t dk = { - {up->ipv6[0], up->ipv6[1], up->ipv6[2], up->ipv6[3]} , - {{up->key.k.ipv4, up->key.k.port, up->key.k.vrf}} - }; - - DSLITE_V6_GET_HASH((&dk), - bucket, - CNAT_USER_HASH_MASK); - DSLITE_PRINTF(1, "Delete1 DSL user hash bucket ..%u\n", bucket); - } else { - CNAT_V4_GET_HASH(up->key.key64, - bucket, CNAT_USER_HASH_MASK) - DSLITE_PRINTF(1, "Delete1 NAT44 user hash bucket ..%u\n", bucket); - } -#else - CNAT_V4_GET_HASH(up->key.key64, - bucket, CNAT_USER_HASH_MASK) - DSLITE_PRINTF(1, "Delete2 NAT44 user hash bucket ..%u\n", bucket); -#endif - - index = cnat_user_hash[bucket].next; - - ASSERT(index != EMPTY); - - prev = 0; - do { - this = cnat_user_db + index; - if (PREDICT_TRUE(this == up)) { - if (prev == 0) { - cnat_user_hash[bucket].next = up->user_hash.next; - goto found; - } else { - prev->user_hash.next = up->user_hash.next; - goto found; - } - } - prev = this; - index = this->user_hash.next; - } while (index != EMPTY); - - ASSERT(0); - - found: - pool_put(cnat_user_db, up); - pthread_spin_unlock(cnat_db_v2_main.user_db_lockp); -} - -cnat_user_db_entry_t* -cnat_user_db_lookup_entry(cnat_db_key_bucket_t *uki) -{ - u64 a, b, c; - u32 index; - cnat_user_db_entry_t *udb=NULL; - - CNAT_V4_GET_HASH(uki->k.key64, - uki->bucket, - CNAT_USER_HASH_MASK) - - /* now: index in user vector */ - index = cnat_user_hash[uki->bucket].next; - if (PREDICT_TRUE(index != EMPTY)) { - do { - udb = cnat_user_db + index; - if (PREDICT_FALSE(udb->key.key64 == uki->k.key64)) { - return udb; - } - index = udb->user_hash.next; - } while (index != EMPTY); - } - return (NULL); -} - -cnat_user_db_entry_t* -cnat_user_db_create_entry(cnat_db_key_bucket_t *uki, - u32 portmap_index) -{ - cnat_user_db_entry_t *udb = NULL; - - pthread_spin_lock(cnat_db_v2_main.user_db_lockp); - pool_get(cnat_user_db, udb); - memset(udb, 0, sizeof(*udb)); - - udb->ntranslations = 1; - udb->portmap_index = portmap_index; - udb->key.key64 = uki->k.key64; - /* Add this user to the head of the bucket chain */ - udb->user_hash.next = - cnat_user_hash[uki->bucket].next; - cnat_user_hash[uki->bucket].next = udb - cnat_user_db; - -#ifndef NO_BULK_LOGGING - INIT_BULK_CACHE(udb) -#endif /* NO_BULK_LOGGING */ - pthread_spin_unlock(cnat_db_v2_main.user_db_lockp); - return udb; -} - -cnat_main_db_entry_t* -cnat_create_main_db_entry_and_hash(cnat_db_key_bucket_t *ki, - cnat_db_key_bucket_t *ko, - cnat_user_db_entry_t *udb) -{ - u64 a, b, c; - u32 db_index; - cnat_main_db_entry_t *db = NULL; - - pool_get(cnat_main_db, db); - memset(db, 0, sizeof(*db)); - - db_index = db - cnat_main_db; - db->in2out_key.k.ipv4 = ki->k.k.ipv4; - db->in2out_key.k.port = ki->k.k.port; - db->in2out_key.k.vrf = ki->k.k.vrf; - db->out2in_key.k.ipv4 = ko->k.k.ipv4; - db->out2in_key.k.port = ko->k.k.port; - db->out2in_key.k.vrf = ko->k.k.vrf; - - db->user_ports.next = db_index; - db->user_ports.prev = db_index; - db->user_index = udb - cnat_user_db; - //db->portmap_index = udb->portmap_index; - db->flags &= ~(CNAT_DB_DSLITE_FLAG); // Mark that it is not dslite - if (PREDICT_FALSE(udb->ntranslations == 1)) { - /* - * first port for this src vrf/src ip addr - */ - udb->translation_list_head_index = db_index; - } else { - index_dlist_addtail(udb->translation_list_head_index, - (u8 *)cnat_main_db, sizeof(cnat_main_db[0]), - STRUCT_OFFSET_OF(cnat_main_db_entry_t, user_ports), - db_index); - } - - /* - * setup o2i hash key - */ - CNAT_V4_GET_HASH(ko->k.key64, - ko->bucket, - CNAT_MAIN_HASH_MASK) - db->out2in_hash.next = cnat_out2in_hash[ko->bucket].next; - cnat_out2in_hash[ko->bucket].next = db_index; - /* - * setup i2o hash key, bucket is already calculate - */ - db->in2out_hash.next = cnat_in2out_hash[ki->bucket].next; - cnat_in2out_hash[ki->bucket].next = db_index; - -#if DEBUG > 1 - printf("\nMy_Instance_Number %d: Bucket %d, Db_Index %d", - my_instance_number, ki->bucket, db_index); - printf("\nInside (VRF 0x%x, IP 0x%x, PORT 0x%x)", - db->in2out_key.k.vrf, db->in2out_key.k.ipv4, db->in2out_key.k.port); - printf("\nOutside (VRF 0x%x, IP 0x%x, PORT 0x%x)", - db->out2in_key.k.vrf, db->out2in_key.k.ipv4, db->out2in_key.k.port); - printf("\nUser Index %d, IP 0x%x", - db->user_index, udb->key.k.ipv4); -#endif - - NAT44_COMMON_STATS.active_translations++; - - return db; -} - -static inline void pptp_clear_all_channels( - cnat_main_db_entry_t *db) -{ - u32 db_index, current_db_index; - cnat_main_db_entry_t *temp_db; - - /* clear all channels */ - - db_index = db->proto_data.pptp_list.next; - current_db_index = db - cnat_main_db; - - while( db_index != EMPTY) { - temp_db = cnat_main_db + db_index; - db_index = temp_db->proto_data.pptp_list.next; - temp_db->entry_expires = 0; - if(PREDICT_FALSE(temp_db->proto_data.pptp_list.prev - == current_db_index)) { // Decouple child GREs from parent - temp_db->proto_data.pptp_list.prev = EMPTY; - } - } - - db->proto_data.pptp_list.next = EMPTY; -} - -void pptp_remove_channel_from_tunnel(cnat_main_db_entry_t *db) { - - cnat_main_db_entry_t *prev_db, *next_db; - - prev_db = cnat_main_db + db->proto_data.pptp_list.prev; - next_db = cnat_main_db + db->proto_data.pptp_list.next; - - /* remove entry from the tunnel list */ - if(PREDICT_TRUE(db->proto_data.pptp_list.prev != EMPTY)) { - prev_db->proto_data.pptp_list.next = - db->proto_data.pptp_list.next ; - } - - if(db->proto_data.pptp_list.next != EMPTY) { - next_db->proto_data.pptp_list.prev - = db->proto_data.pptp_list.prev; - } - -} - -void cnat_delete_main_db_entry_v2 (cnat_main_db_entry_t *ep) -{ - u32 main_db_index; - u32 vrfmap_len, udb_len; - cnat_user_db_entry_t *up =0; - cnat_portmap_v2_t *pm =0; - cnat_portmap_v2_t *my_pm =0; - cnat_vrfmap_t *my_vrfmap =0; - u16 static_port_range; -#ifndef NO_BULK_LOGGING - bulk_alloc_size_t bulk_size; - int nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED; -#endif - pool_header_t *h = pool_header(cnat_user_db); - u16 instance = 0; - u32 my_index; - - - if (PREDICT_FALSE(ep->flags & CNAT_DB_NAT64_FLAG) != 0) { - /* Preventive check - Not a NAT44 entry */ - return; - } - - pthread_spin_lock(cnat_db_v2_main.main_db_lockp); - if(PREDICT_FALSE(ep->flags & - CNAT_DB_FLAG_PPTP_TUNNEL_ACTIVE)) { - pptp_clear_all_channels(ep); - PPTP_DECR(active_tunnels); - } - - if(PREDICT_FALSE(ep->flags & - CNAT_DB_FLAG_PPTP_GRE_ENTRY)) { - pptp_remove_channel_from_tunnel(ep); - PPTP_DECR(active_channels); - } - - /* This function gets called from various locations.. - * many times from config handler.. so we - * to ensure that multiple sessions if any are - * released - */ - - if(PREDICT_FALSE(ep->nsessions > 1)) { - cnat_session_entry_t *sdb; - while(ep->nsessions > 1 && - ep->session_head_index != EMPTY) { - sdb = cnat_session_db + ep->session_head_index; - cnat_delete_session_db_entry(sdb, TRUE); - } - } - - /* Find the set of portmaps for the outside vrf */ - vrfmap_len = vec_len(cnat_map_by_vrf); - udb_len = vec_len(cnat_user_db); - - /* In case of invalid user just return, deleting only main db - * is not a good idea, since some valid user db entry might be pointing - * to that main db and hence leave the dbs in a inconsistent state - */ - if (PREDICT_FALSE((ep->user_index >= udb_len) || - (clib_bitmap_get(h->free_bitmap, ep->user_index)))) { -#ifdef DEBUG_PRINTF_ENABLED - printf("invalid/unused user index in db %d\n", ep->user_index); -#endif - spp_printf(CNAT_INV_UNUSED_USR_INDEX, 1, (u32 *) &(ep->user_index)); - cnat_main_db_entry_dump(ep); - goto unlock; - } - - up = cnat_user_db + ep->user_index; - -/* Point to the right portmap list */ -if (PREDICT_FALSE(ep->flags & CNAT_DB_DSLITE_FLAG)) { - instance = ep->dslite_nat44_inst_id; - pm = dslite_table_db_ptr[instance].portmap_list; - if(PREDICT_FALSE((pm == NULL))) { - DSLITE_PRINTF(3, "NULL portmap list for dslite_id %u, state %u\n", - instance, dslite_table_db_ptr[instance].state); - cnat_main_db_entry_dump(ep); - goto delete_entry; - } - static_port_range = - STAT_PORT_RANGE_FROM_INST_PTR(&(dslite_table_db_ptr[instance])); - /* - * Netflow logging API for delete event - */ - bulk_size = - BULKSIZE_FROM_VRFMAP(&(dslite_table_db_ptr[instance])); -} else { - if (PREDICT_FALSE(ep->vrfmap_index >= vrfmap_len)) { -#ifdef DEBUG_PRINTF_ENABLED - printf("invalid vrfmap index in db\n"); -#endif - spp_printf(CNAT_INVALID_VRFMAP_INDEX, 0, NULL); - cnat_main_db_entry_dump(ep); - goto delete_entry; - } - instance = NAT44_RESERVED_INST_ID; - my_vrfmap = cnat_map_by_vrf + ep->vrfmap_index; - pm = my_vrfmap->portmap_list; - static_port_range = cnat_static_port_range; - bulk_size = BULKSIZE_FROM_VRFMAP(my_vrfmap); -} - - if (PREDICT_FALSE(ep->flags & CNAT_DB_FLAG_PORT_PAIR)) { - /* Give back the port(s) */ - cnat_port_free_v2_bulk(pm, up->portmap_index, - PORT_PAIR, ep->out2in_key.k.port, up, static_port_range -#ifndef NO_BULK_LOGGING - , bulk_size, &nfv9_log_req -#endif - ); - } else { - /* Give back the port(s) */ - cnat_port_free_v2_bulk (pm, up->portmap_index, - PORT_SINGLE, ep->out2in_key.k.port, up, static_port_range -#ifndef NO_BULK_LOGGING - , bulk_size, &nfv9_log_req -#endif - ); - } - - if (PREDICT_TRUE(!(ep->flags & CNAT_DB_DSLITE_FLAG))) { - if(PREDICT_FALSE(nfv9_log_req != CACHE_ALLOC_NO_LOG_REQUIRED)) { - if(PREDICT_FALSE(my_vrfmap->nf_logging_policy == SESSION_LOG_ENABLE)) { - if(ep->nsessions != 0) { - cnat_nfv9_nat44_log_session_delete(ep, NULL, my_vrfmap); - } - } else { - cnat_nfv9_log_mapping_delete(ep, my_vrfmap -#ifndef NO_BULK_LOGGING - , nfv9_log_req -#endif - ); - } - if(PREDICT_TRUE((my_vrfmap->syslog_logging_policy != SESSION_LOG_ENABLE) || - (ep->nsessions != 0))) { - cnat_syslog_nat44_mapping_delete(ep, my_vrfmap, NULL -#ifndef NO_BULK_LOGGING - , nfv9_log_req -#endif - ); - } - } - } else { - if(PREDICT_FALSE(nfv9_log_req != CACHE_ALLOC_NO_LOG_REQUIRED)) { - if(PREDICT_FALSE( dslite_table_db_ptr[instance].nf_logging_policy == - SESSION_LOG_ENABLE)) { - cnat_nfv9_ds_lite_log_session_delete(ep, - (dslite_table_db_ptr + instance),NULL); - } else { - cnat_nfv9_ds_lite_mapping_delete(ep, - (dslite_table_db_ptr + instance) -#ifndef NO_BULK_LOGGING - , nfv9_log_req -#endif - ); - } -#ifdef TOBE_PORTED - cnat_syslog_ds_lite_mapping_delete(ep, - (dslite_table_db_ptr + instance), NULL -#ifndef NO_BULK_LOGGING - , nfv9_log_req -#endif - ); -#endif /* TOBE_PORTED */ - } - } - -delete_entry: - - main_db_index = ep - cnat_main_db; - - pthread_spin_lock(cnat_db_v2_main.user_db_lockp); - up->ntranslations--; - pthread_spin_unlock(cnat_db_v2_main.user_db_lockp); - - /* - * when user reaches max allowed port limit - * we generate icmp msg and inc the counter - * when counter reach the icmp msg rate limit - * we stop icmp msg gen - * when a user port is freed - * that means we need to clear the msg gen counter - * so that next time - * reach max port limit, we can generate new icmp msg again - */ - up->icmp_msg_count = 0; - - up->translation_list_head_index = index_dlist_remelem ( - up->translation_list_head_index, (u8 *)cnat_main_db, - sizeof (cnat_main_db[0]), - STRUCT_OFFSET_OF(cnat_main_db_entry_t, user_ports), - main_db_index); - - cnat_db_in2out_hash_delete(ep, up); - - if (PREDICT_FALSE(up->ntranslations == 0)) { - ASSERT(up->translation_list_head_index == EMPTY); - nat44_dslite_common_stats[instance].num_subscribers--; - my_index = up->portmap_index; - my_pm = pm + my_index; - if(PREDICT_TRUE(my_pm->private_ip_users_count)) { - my_pm->private_ip_users_count--; -#ifdef DEBUG_PRINTF_IP_N_TO_1_ENABLED - PLATFORM_DEBUG_PRINT("\n cnat_delete_main_db_entry_v2 " - "private_ip_users_count = %d", - my_pm->private_ip_users_count); -#endif - - } - cnat_user_db_delete(up); - - } - - /* Remove from main DB hashes */ - //cnat_db_in2out_hash_delete(ep); - cnat_db_out2in_hash_delete(ep); - - pool_put(cnat_main_db, ep); - - if(PREDICT_FALSE(ep->flags & CNAT_DB_FLAG_STATIC_PORT)) { - nat44_dslite_common_stats[instance].num_static_translations--; - } else { - nat44_dslite_common_stats[instance].num_dynamic_translations--; - } - nat44_dslite_common_stats[instance].active_translations--; - nat44_dslite_global_stats[!!(instance - 1)].translation_delete_count ++; -unlock: - pthread_spin_unlock(cnat_db_v2_main.main_db_lockp); -} - -cnat_main_db_entry_t* -cnat_main_db_lookup_entry_out2in (cnat_db_key_bucket_t *ko) -{ - u64 a, b, c; - u32 index; - cnat_main_db_entry_t *db; - - CNAT_V4_GET_HASH(ko->k.key64, - ko->bucket, - CNAT_MAIN_HASH_MASK); - - index = cnat_out2in_hash[ko->bucket].next; - if (PREDICT_TRUE(index == EMPTY)) { - return (NULL); - } - - do { - db = cnat_main_db + index; - if (PREDICT_TRUE(db->out2in_key.key64 == ko->k.key64)) { - return db; - } - index = db->out2in_hash.next; - } while (index != EMPTY); - - return (NULL); -} - -/* Creates 2 sessions. - * Moves the default dest info from mdb to first session - * Fills the dest_info details in to second session and - * returns the pointer to second session - */ -cnat_session_entry_t *cnat_handle_1to2_session( - cnat_main_db_entry_t *mdb, - cnat_key_t *dest_info) -{ - cnat_key_t old_dest_info; - pool_header_t *h; - u32 free_session = 0; - u16 instance; - cnat_session_entry_t *session_db1 = NULL, *session_db2 = NULL; - - h = pool_header(cnat_session_db); - free_session = vec_len(h->free_indices) - 1; - - if (PREDICT_FALSE(free_session < 2)) { - if (mdb->flags & CNAT_DB_DSLITE_FLAG) { - instance = mdb->dslite_nat44_inst_id; - } else { - instance = NAT44_RESERVED_INST_ID; - } - - /* we need 2 sessions here, return NULL */ - nat44_dslite_common_stats[instance].drops_sessiondb_limit_exceeded++; - return NULL; - } - - old_dest_info.k.ipv4 = mdb->dst_ipv4; - old_dest_info.k.port = mdb->dst_port; - old_dest_info.k.vrf = mdb->in2out_key.k.vrf; - - /* create 2 new sessions */ - session_db1 = cnat_create_session_db_entry(&old_dest_info, - mdb, FALSE); - - if(PREDICT_FALSE(session_db1 == NULL)) { - return NULL; - } - - /* update pkt info to session 2 */ - session_db2 = cnat_create_session_db_entry(dest_info, - mdb, TRUE); - - if(PREDICT_FALSE(session_db2 == NULL)) { - cnat_delete_session_db_entry(session_db1, FALSE); - return NULL; - } - /* update main db info to session 1 */ - cnat_dest_update_main2session(mdb, session_db1); - - return session_db2; -} - -/* The below function shold be called only - * when a NAT44 STATIC entry received traffic - * for the first time. This is to ensure - * the destination is noted and logged - */ -void cnat_add_dest_n_log( - cnat_main_db_entry_t *mdb, - cnat_key_t *dest_info) -{ - - if(PREDICT_FALSE(mdb->nsessions != 0)) { - return; /* Should not have been called */ - } - - mdb->dst_ipv4 = dest_info->k.ipv4; - mdb->dst_port = dest_info->k.port; - mdb->nsessions = 1; - mdb->entry_expires = cnat_current_time; - u16 instance; - - if (mdb->flags & CNAT_DB_DSLITE_FLAG) { - instance = mdb->dslite_nat44_inst_id; - cnat_session_log_ds_lite_mapping_create(mdb, - (dslite_table_db_ptr + instance),NULL); - } else { - instance = NAT44_RESERVED_INST_ID; - cnat_vrfmap_t *my_vrfmap = cnat_map_by_vrf + mdb->vrfmap_index; - cnat_session_log_nat44_mapping_create(mdb, 0, my_vrfmap); - } -} - -/* - * this function is called by exception node - * when lookup is fialed in i2o node - * - * if reash per user port limit, - * set user_db_entry pointer, and error == CNAT_OUT_LIMIT - */ -static cnat_main_db_entry_t* -_cnat_get_main_db_entry_v2(cnat_db_key_bucket_t *ki, - port_pair_t port_pair_type, - port_type_t port_type, - cnat_gen_icmp_info *info, - cnat_key_t *dest_info) -{ - u16 protocol; - cnat_errno_t rv; - cnat_db_key_bucket_t u_ki, ko; - u32 my_index, free_main, free_user; - u32 current_timestamp; - u16 my_vrfmap_index; - u16 my_vrfmap_entry_found = 0; - cnat_vrfmap_t *my_vrfmap =0; - cnat_portmap_v2_t *pm =0; - cnat_user_db_entry_t *udb = 0; - cnat_main_db_entry_t *db = 0; - pool_header_t *h; - u16 port_limit; - cnat_portmap_v2_t *my_pm = 0; - -#ifndef NO_BULK_LOGGING - int nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED; -#endif - - - /* - * need to try lookup again because - * second pkt may come here before the entry is created - * by receiving first pkt due to high line rate. - */ - info->gen_icmp_msg = CNAT_NO_ICMP_MSG; - info->error = CNAT_SUCCESS; - db = cnat_main_db_lookup_entry(ki); - if (PREDICT_TRUE(db)) { - /* what if the source is talking to a - * new dest now? We will have to handle this case and - * take care of - creating session db and logging - */ - if(PREDICT_FALSE((!dest_info->k.ipv4) && (!dest_info->k.port))) { - return db; /* if dest_info is null don't create session */ - } - if(PREDICT_TRUE((db->dst_ipv4 == dest_info->k.ipv4) && - (db->dst_port == dest_info->k.port))) { - return db; - } - dest_info->k.vrf = db->in2out_key.k.vrf; - /* Src is indeed talking to a different dest */ - cnat_session_entry_t *session_db2 = NULL; - if(PREDICT_TRUE(db->nsessions == 1)) { - session_db2 = cnat_handle_1to2_session(db, dest_info); - if(PREDICT_TRUE(session_db2 != NULL)) { - CNAT_DB_TIMEOUT_RST(session_db2); - return db; - } else { - info->error = CNAT_ERR_NO_SESSION_DB; - return NULL; - } - } else if(PREDICT_FALSE(db->nsessions == 0)) { - /* Should be static entry.. should never happen - */ - if(PREDICT_TRUE(dest_info->k.ipv4 != 0)) { - cnat_add_dest_n_log(db, dest_info); - } - return db; - } else { - /* The src has already created multiple sessions.. very rare - */ - session_db2 = cnat_create_session_db_entry(dest_info, - db, TRUE); - if(PREDICT_TRUE(session_db2 != NULL)) { - CNAT_DB_TIMEOUT_RST(session_db2); - return db; - } else { - info->error = CNAT_ERR_NO_SESSION_DB; - return NULL; - } - } - - } - - /* - * step 1. check if outside vrf is configured or not - * and Find the set of portmaps for the outside vrf - * insider vrf is one to one mappted to outside vrf - * key is vrf and ip only - * ki.k.k.vrf has protocol bits, mask out - */ - protocol = ki->k.k.vrf & CNAT_PRO_MASK; - u_ki.k.k.vrf = ki->k.k.vrf & CNAT_VRF_MASK; - u_ki.k.k.ipv4 = ki->k.k.ipv4; - u_ki.k.k.port = 0; - - my_vrfmap_index = vrf_map_array[u_ki.k.k.vrf]; - my_vrfmap = cnat_map_by_vrf + my_vrfmap_index; - - my_vrfmap_entry_found = ((my_vrfmap_index != VRF_MAP_ENTRY_EMPTY) && - (my_vrfmap->status == S_RUN) && - (my_vrfmap->i_vrf == u_ki.k.k.vrf)); - - if (PREDICT_FALSE(!my_vrfmap_entry_found)) { - u32 arr[] = {ki->k.k.vrf, ki->k.k.ipv4, ki->k.k.port}; - if ((my_vrfmap_index == VRF_MAP_ENTRY_EMPTY) || - (my_vrfmap->i_vrf == u_ki.k.k.vrf)) { - info->error = CNAT_NO_CONFIG; - CNAT_DEBUG_INSIDE_ERR(CNAT_NO_CONFIG) - spp_printf(CNAT_NO_CONFIG_ERROR, 3, arr); - } else { - info->error = CNAT_NO_VRF_RUN; - CNAT_DEBUG_INSIDE_ERR(CNAT_NO_VRF_RUN) - spp_printf(CNAT_NO_VRF_RUN_ERROR, 3, arr); - } - - return (NULL); - } - - pm = my_vrfmap->portmap_list; - - port_limit = my_vrfmap->port_limit; - if(PREDICT_FALSE(!port_limit)) { - port_limit = cnat_main_db_max_ports_per_user; - } - /* - * set o2i key with protocl bits - */ - ko.k.k.vrf = my_vrfmap->o_vrf | protocol; - - /* - * step 2. check if src vrf, src ip addr is alreay - * in the user db - * if yes, use PORT_ALLOC_DIRECTED - * if no, use PORT_ALLOC_ANY since it is first time - */ - udb = cnat_user_db_lookup_entry(&u_ki); - if (PREDICT_TRUE(udb)) { - /* - * not first time allocate port for this user - * check limit - */ - if (PREDICT_FALSE(udb->ntranslations >= - port_limit)) { - /* Check for the port type here. If we are getting - * a STATIC PORT, allow the config. - */ - if (PREDICT_TRUE(port_type != PORT_TYPE_STATIC)) { - info->error = CNAT_OUT_LIMIT; - CNAT_SET_ICMP_MSG_INFO - CNAT_DEBUG_INSIDE_ERR(CNAT_OUT_LIMIT) - port_exceeded_msg_log(u_ki.k.k.ipv4, u_ki.k.k.vrf); - in2out_drops_port_limit_exceeded ++; - u_ki.k.k.port = ki->k.k.port; - u_ki.k.k.vrf = ki->k.k.vrf; - handle_cnat_port_exceeded_logging(udb, &u_ki.k, my_vrfmap); - return (NULL); - } - } - CHECK_CLEAR_PORT_LIMIT_EXCEED_FLAG(udb, - port_limit) - - /* - * check if main db has space to accomodate new entry - */ - h = pool_header(cnat_main_db); - - free_main = vec_len(h->free_indices) - 1; - if (PREDICT_FALSE(!free_main)) { - info->error = CNAT_MAIN_DB_LIMIT; - CNAT_SET_ICMP_MSG_INFO - in2out_drops_system_limit_reached ++; - CNAT_DEBUG_INSIDE_ERR(CNAT_MAIN_DB_LIMIT) - - current_timestamp = spp_trace_log_get_unix_time_in_seconds(); - if (PREDICT_FALSE((current_timestamp - last_log_timestamp) > - 1800)) { - spp_printf(CNAT_SESSION_THRESH_EXCEEDED, 0, NULL); - last_log_timestamp = current_timestamp; - } - -#ifdef UT_TEST_CODE - printf("Limit reached : OLD USER"); -#endif - return NULL; - } - - /* - * allocate port, from existing mapping - */ - my_index = udb->portmap_index; - - if (PREDICT_FALSE(port_type == PORT_TYPE_STATIC)) { - rv = cnat_static_port_alloc_v2_bulk(pm, - PORT_ALLOC_DIRECTED, - port_pair_type, - ki->k.k.ipv4, - ki->k.k.port, - &my_index, - &(ko.k.k.ipv4), - &(ko.k.k.port), - cnat_static_port_range -#ifndef NO_BULK_LOGGING - , - udb, BULKSIZE_FROM_VRFMAP(my_vrfmap), - &nfv9_log_req -#endif - , my_vrfmap->ip_n_to_1 - ); - - } else if (PREDICT_TRUE(port_type != PORT_TYPE_RTSP) ) { - - rv = cnat_dynamic_port_alloc_v2_bulk(pm, - PORT_ALLOC_DIRECTED, - port_pair_type, - &my_index, - &(ko.k.k.ipv4), - &(ko.k.k.port), - cnat_static_port_range -#ifndef NO_BULK_LOGGING - , - udb, BULKSIZE_FROM_VRFMAP(my_vrfmap), - &nfv9_log_req -#endif - , my_vrfmap->ip_n_to_1, - &(my_vrfmap->rseed_ip) - ); - - } else { - /* - * For RTSP, two translation entries are created, - * check if main db has space to accomodate two new entry - */ - free_main = free_main - 1; - if (PREDICT_FALSE(!free_main)) { - info->error = CNAT_MAIN_DB_LIMIT; - CNAT_SET_ICMP_MSG_INFO - in2out_drops_system_limit_reached ++; - CNAT_DEBUG_INSIDE_ERR(CNAT_MAIN_DB_LIMIT) - - return NULL; - } else { - rv = cnat_dynamic_port_alloc_rtsp_bulk(pm, - PORT_ALLOC_DIRECTED, - port_pair_type, - ki->k.k.port, - &my_index, - &(ko.k.k.ipv4), - &(ko.k.k.port), - cnat_static_port_range -#ifndef NO_BULK_LOGGING - , - udb, BULKSIZE_FROM_VRFMAP(my_vrfmap), - &nfv9_log_req -#endif - , &(my_vrfmap->rseed_ip) - ); - } - } - - - if (PREDICT_FALSE(rv != CNAT_SUCCESS)) { - info->error = rv; - CNAT_SET_ICMP_MSG_INFO - CNAT_DEBUG_INSIDE_ERR(rv) - in2out_drops_resource_depletion++; - log_port_alloc_error(rv, &(ki->k)); - return (NULL); - } - /* - * increment port in use for this user - */ - pthread_spin_lock(cnat_db_v2_main.user_db_lockp); - udb->ntranslations += 1; - pthread_spin_unlock(cnat_db_v2_main.user_db_lockp); - - } else { - /* - * first time allocate port for this user - */ - - /* - * Do not create entry if port limit is invalid - */ - - if (PREDICT_FALSE(!port_limit)) { - if (PREDICT_TRUE(port_type != PORT_TYPE_STATIC)) { - info->error = CNAT_OUT_LIMIT; - in2out_drops_port_limit_exceeded ++; - port_exceeded_msg_log(u_ki.k.k.ipv4, u_ki.k.k.vrf); - CNAT_SET_ICMP_MSG_INFO - CNAT_DEBUG_INSIDE_ERR(CNAT_OUT_LIMIT) - return (NULL); - } - } - - /* - * Check if main db has space for new entry - * Allowing a user db entry to be created if main db is not free - * will cause a port to be allocated to that user, which results in - * wastage of that port, hence the check is done here. - */ - h = pool_header(cnat_main_db); - free_main = vec_len(h->free_indices) - 1; - h = pool_header(cnat_user_db); - free_user = vec_len(h->free_indices) - 1; - - /* - * If either main_db or user_db does not have entries - * bail out, with appropriate error - */ - if (PREDICT_FALSE(!(free_main && free_user))) { - u32 log_error; - if(free_main) { - info->error = CNAT_USER_DB_LIMIT; - log_error = CNAT_USER_DB_LIMIT_ERROR; - } else { - info->error = CNAT_MAIN_DB_LIMIT; - log_error = CNAT_MAIN_DB_LIMIT_ERROR; - } - in2out_drops_system_limit_reached ++; - CNAT_SET_ICMP_MSG_INFO - CNAT_DEBUG_INSIDE_ERR(info->error) - spp_printf(log_error, 0, 0); - return NULL; - } - - if (PREDICT_FALSE(port_type == PORT_TYPE_STATIC)) { - rv = cnat_static_port_alloc_v2_bulk(pm, - PORT_ALLOC_ANY, - port_pair_type, - ki->k.k.ipv4, - ki->k.k.port, - &my_index, - &(ko.k.k.ipv4), - &(ko.k.k.port), - cnat_static_port_range -#ifndef NO_BULK_LOGGING - , - udb, BULKSIZE_FROM_VRFMAP(my_vrfmap), - &nfv9_log_req -#endif - , my_vrfmap->ip_n_to_1 - ); - - } else if (PREDICT_TRUE(port_type != PORT_TYPE_RTSP)) { - rv = cnat_dynamic_port_alloc_v2_bulk(pm, - PORT_ALLOC_ANY, - port_pair_type, - &my_index, - &(ko.k.k.ipv4), - &(ko.k.k.port), - cnat_static_port_range -#ifndef NO_BULK_LOGGING - , NULL, BULKSIZE_FROM_VRFMAP(my_vrfmap), - &nfv9_log_req -#endif - , my_vrfmap->ip_n_to_1, - &(my_vrfmap->rseed_ip) - ); - } else { - /* - * For RTSP, two translation entries are created, - * check if main db has space to accomodate two new entry - */ - free_main = free_main - 1; - if (PREDICT_FALSE(!free_main)) { - info->error = CNAT_MAIN_DB_LIMIT; - CNAT_SET_ICMP_MSG_INFO - in2out_drops_system_limit_reached ++; - CNAT_DEBUG_INSIDE_ERR(CNAT_MAIN_DB_LIMIT) - - return NULL; - } else { - - rv = cnat_dynamic_port_alloc_rtsp_bulk(pm, - PORT_ALLOC_ANY, - port_pair_type, - ki->k.k.port, - &my_index, - &(ko.k.k.ipv4), - &(ko.k.k.port), - cnat_static_port_range -#ifndef NO_BULK_LOGGING - , NULL, BULKSIZE_FROM_VRFMAP(my_vrfmap), - &nfv9_log_req -#endif - , &(my_vrfmap->rseed_ip) - ); - /* TODO: Add the port pair flag here */ - } - } - - - - if (PREDICT_FALSE(rv != CNAT_SUCCESS)) { - info->error = rv; - in2out_drops_resource_depletion ++; - CNAT_SET_ICMP_MSG_INFO - CNAT_DEBUG_INSIDE_ERR(rv) - log_port_alloc_error(rv, &(ki->k)); - return (NULL); - } - /* - * create entry in user db - */ - udb = cnat_user_db_create_entry(&u_ki, my_index); - NAT44_COMMON_STATS.num_subscribers++; - my_pm = pm + my_index; - if(PREDICT_TRUE(my_pm->private_ip_users_count < PORTS_PER_ADDR)) { - my_pm->private_ip_users_count++; -#ifdef DEBUG_PRINTF_IP_N_TO_1_ENABLED - PLATFORM_DEBUG_PRINT("\n cnat_get_main_db_entry_v2 " - "dynamic alloc private_ip_users_count = %d", - my_pm->private_ip_users_count); -#endif - } else { - PLATFORM_DEBUG_PRINT("\n ERROR: private_ip_users_count has " - "reached MAX PORTS_PER_ADDR"); - } -#ifndef NO_BULK_LOGGING - if(PREDICT_TRUE(udb && (BULK_ALLOC_NOT_ATTEMPTED != nfv9_log_req))) { - cnat_update_bulk_range_cache(udb, ko.k.k.port, - BULKSIZE_FROM_VRFMAP(my_vrfmap)); - } -#endif /* #ifndef NO_BULK_LOGGING */ - - } - - /* - * step 3: - * outside port is allocated for this src vrf/src ip addr - * 1)create a new entry in main db - * 2)setup cnat_out2in_hash key - * 3)setup cnat_in2out_hash key - */ - db = cnat_create_main_db_entry_and_hash(ki, &ko, udb); - - translation_create_count ++; -#ifdef DSLITE_DEF - db->dslite_nat44_inst_id = NAT44_RESERVED_INST_ID; -#endif - db->vrfmap_index = my_vrfmap - cnat_map_by_vrf; - - /* - * don't forget logging - * logging API is unconditional, - * logging configuration check is done inside the inline function - */ - - db->dst_ipv4 = dest_info->k.ipv4; - db->dst_port = dest_info->k.port; - if(PREDICT_TRUE(db->dst_ipv4 || db->dst_port)) { - db->nsessions++; - } - - if(PREDICT_FALSE(nfv9_log_req != CACHE_ALLOC_NO_LOG_REQUIRED)) { - if(PREDICT_FALSE(my_vrfmap->nf_logging_policy == SESSION_LOG_ENABLE)) { - /* do not log for static entries.. we will log when traffic flows */ - if(PREDICT_TRUE(db->dst_ipv4 || db->dst_port)) { - cnat_nfv9_nat44_log_session_create(db, 0, my_vrfmap); - } - } else { - cnat_nfv9_log_mapping_create(db, my_vrfmap -#ifndef NO_BULK_LOGGING - , nfv9_log_req -#endif - ); - } - if(PREDICT_TRUE((my_vrfmap->syslog_logging_policy != SESSION_LOG_ENABLE) || - (db->dst_ipv4 || db->dst_port))) { - cnat_syslog_nat44_mapping_create(db, my_vrfmap, 0 -#ifndef NO_BULK_LOGGING - , nfv9_log_req -#endif - ); - } - } - if (PREDICT_FALSE(port_pair_type == PORT_PAIR)) { - cnat_main_db_entry_t *db2 = 0; - cnat_db_key_bucket_t new_ki = *ki; - u64 a, b, c; - - new_ki.k.k.port += 1; - ko.k.k.port += 1; - - CNAT_V4_GET_HASH(new_ki.k.key64, new_ki.bucket, - CNAT_MAIN_HASH_MASK); - - db2 = cnat_create_main_db_entry_and_hash(&new_ki, &ko, udb); - - translation_create_count ++; -#ifdef DSLITE_DEF - db2->dslite_nat44_inst_id = NAT44_RESERVED_INST_ID; -#endif - db2->vrfmap_index = my_vrfmap - cnat_map_by_vrf; - db2->entry_expires = cnat_current_time; - db2->flags |= CNAT_DB_FLAG_ALG_ENTRY; - pthread_spin_lock(cnat_db_v2_main.user_db_lockp); - udb->ntranslations += 1; - pthread_spin_unlock(cnat_db_v2_main.user_db_lockp); - db2->dst_ipv4 = dest_info->k.ipv4; - db2->dst_port = dest_info->k.port; - db2->nsessions = 0; /* For ALG db, set sessions to 0 - CSCuf78420 */ - - if(PREDICT_FALSE(nfv9_log_req != CACHE_ALLOC_NO_LOG_REQUIRED)) { - if(PREDICT_FALSE(my_vrfmap->nf_logging_policy == SESSION_LOG_ENABLE)) { - /* do not log for static entries.. we will log when traffic flows */ - if(PREDICT_TRUE(db2->dst_ipv4 || db2->dst_port)) { - cnat_nfv9_nat44_log_session_create(db2, 0, my_vrfmap); - } - } else { - cnat_nfv9_log_mapping_create(db2, my_vrfmap -#ifndef NO_BULK_LOGGING - , nfv9_log_req -#endif - ); - } - if(PREDICT_TRUE((my_vrfmap->syslog_logging_policy != SESSION_LOG_ENABLE) || - (db2->dst_ipv4 || db2->dst_port))) { - cnat_syslog_nat44_mapping_create(db2, my_vrfmap, 0 -#ifndef NO_BULK_LOGGING - , nfv9_log_req -#endif - ); - } - } - } - - return db; -} - -cnat_main_db_entry_t* -cnat_get_main_db_entry_v2(cnat_db_key_bucket_t *ki, - port_pair_t port_pair_type, - port_type_t port_type, - cnat_gen_icmp_info *info, - cnat_key_t *dest_info) -{ - - cnat_main_db_entry_t *db; - pthread_spin_lock(cnat_db_v2_main.main_db_lockp); - db = _cnat_get_main_db_entry_v2(ki, port_pair_type, - port_type, info, dest_info); - pthread_spin_unlock(cnat_db_v2_main.main_db_lockp); - return db; -} - -/* - * this function is called from config handler only - * to allocate a static port based db entry - * - * the actual mapped address and port are already specified - */ -cnat_main_db_entry_t* -cnat_create_static_main_db_entry_v2 (cnat_db_key_bucket_t *ki, - cnat_db_key_bucket_t *ko, - cnat_vrfmap_t *my_vrfmap, - cnat_gen_icmp_info *info) -{ - u16 protocol; - u32 head; - cnat_errno_t rv; - cnat_db_key_bucket_t u_ki; - u32 my_index, free_main, free_user; - cnat_portmap_v2_t *pm =0; - cnat_portmap_v2_t *my_pm =0; - cnat_user_db_entry_t *udb = 0; - cnat_main_db_entry_t *db = 0; - pool_header_t *h; -#ifndef NO_BULK_LOGGING - int nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED; -#endif - - /* UNUSED. Therefore not ported to be multi-thread friendly */ - ASSERT(0); - - /* - * need to try lookup again because - * second pkt may come here before the entry is created - * by receiving first pkt due to high line rate. - */ - info->gen_icmp_msg = CNAT_NO_ICMP_MSG; - info->error = CNAT_SUCCESS; - db = cnat_main_db_lookup_entry(ki); - - /* - * If we already have an entry with this inside address, port - * check delete the entry and proceed further. This should - * If yes, something is terribly wrong. Bail out - */ - if (PREDICT_FALSE(db)) { - - if (db->flags & CNAT_DB_FLAG_STATIC_PORT) { - - if ((db->out2in_key.k.ipv4 == ko->k.k.ipv4) && - (db->out2in_key.k.port == ko->k.k.port) && - (db->out2in_key.k.vrf == ko->k.k.vrf)) { - -#ifdef DEBUG_PRINTF_ENABLED - printf("Same Static Port Exists ki 0x%16llx ko 0x%16llx", - ki->k, ko->k); -#endif - /* - * We have already programmed this, return - */ - return (db); - } - - /* - * We already have a static port with different mapping - * Return an error for this case. - */ - info->error = CNAT_ERR_PARSER; - -#ifdef DEBUG_PRINTF_ENABLED - printf("Static Port Existing and Diff ki 0x%16llx ko 0x%16llx", - ki, db->out2in_key); -#endif - { - u32 arr[] = {STAT_PORT_CONFIG_IN_USE, (ki->k.k.vrf & CNAT_VRF_MASK), - ki->k.k.ipv4, ki->k.k.port, (ki->k.k.vrf & CNAT_PRO_MASK) }; - spp_printf(CNAT_CONFIG_ERROR, 5, arr); - } - return (db); - } - -#ifdef DEBUG_PRINTF_ENABLED - printf("Deleting Dynamic entry ki 0x%16llx ko 0x%16llx", - ki, db->out2in_key); -#endif - - /* - * If for some reason we have dynamic entries, just delete them - * and proceed. - */ - cnat_delete_main_db_entry_v2(db); - - db = NULL; - } - - protocol = ki->k.k.vrf & CNAT_PRO_MASK; - u_ki.k.k.vrf = ki->k.k.vrf & CNAT_VRF_MASK; - u_ki.k.k.ipv4 = ki->k.k.ipv4; - u_ki.k.k.port = 0; - - pm = my_vrfmap->portmap_list; - - /* - * check if src vrf, src ip addr is already - * in the user db - * if yes, use PORT_ALLOC_DIRECTED - * if no, use PORT_ALLOC_ANY since it is first time - */ - udb = cnat_user_db_lookup_entry(&u_ki); - if (PREDICT_TRUE(udb)) { - /* - * check if main db has space to accomodate new entry - */ - h = pool_header(cnat_main_db); - - free_main = vec_len(h->free_indices) - 1; - if (PREDICT_FALSE(!free_main)) { - info->error = CNAT_MAIN_DB_LIMIT; - CNAT_SET_ICMP_MSG_INFO - in2out_drops_system_limit_reached ++; - CNAT_DEBUG_INSIDE_ERR(CNAT_MAIN_DB_LIMIT) -#ifdef UT_TEST_CODE - printf("Limit reached : OLD USER"); -#endif - spp_printf(CNAT_MAIN_DB_LIMIT_ERROR, 0, 0); - return NULL; - } - - /* - * allocate port, from existing mapping - */ - my_index = udb->portmap_index; - my_pm = pm + my_index; - /* It is quite possible that we hit the scenario of CSCtj17774. - * Delete all the main db entries and add the ipv4 address sent by - * CGN-MA as Static port alloc any - */ - - if (PREDICT_FALSE(my_pm->ipv4_address != ko->k.k.ipv4)) { - if (PREDICT_FALSE(global_debug_flag && CNAT_DEBUG_GLOBAL_ALL)) { - printf("Delete Main db entry and check for" - " ipv4 address sanity pm add = 0x%x ip add = 0x%x\n", - my_pm->ipv4_address, ko->k.k.ipv4); - } - do { - /* udb is not NULL when we begin with for sure */ - head = udb->translation_list_head_index; - db = cnat_main_db + head; - cnat_delete_main_db_entry_v2(db); - } while (!pool_is_free(cnat_user_db, udb)); - - rv = cnat_mapped_static_port_alloc_v2_bulk (pm, - PORT_ALLOC_ANY, &my_index, ko->k.k.ipv4, ko->k.k.port, - udb, BULKSIZE_FROM_VRFMAP(my_vrfmap), &nfv9_log_req, - my_vrfmap->ip_n_to_1); - - if (PREDICT_FALSE(rv != CNAT_SUCCESS)) { - info->error = rv; - in2out_drops_resource_depletion ++; - CNAT_SET_ICMP_MSG_INFO - CNAT_DEBUG_INSIDE_ERR(rv) - return (NULL); - } - /* - * create entry in user db - */ - udb = cnat_user_db_create_entry(&u_ki, my_index); - my_pm = pm + my_index; - if(PREDICT_TRUE(my_pm->private_ip_users_count < PORTS_PER_ADDR)) { - my_pm->private_ip_users_count++; -#ifdef DEBUG_PRINTF_IP_N_TO_1_ENABLED - PLATFORM_DEBUG_PRINT("\n cnat_create_static_main_db_entry_v2 " - "static del n alloc private_ip_users_count = " - "%d",my_pm->private_ip_users_count); -#endif - } else { - PLATFORM_DEBUG_PRINT("\n ERROR: private_ip_users_count has " - "reached MAX PORTS_PER_ADDR"); - } - NAT44_COMMON_STATS.num_subscribers++; -#ifndef NO_BULK_LOGGING - cnat_update_bulk_range_cache(udb, ko->k.k.port, - BULKSIZE_FROM_VRFMAP(my_vrfmap)); -#endif /* #ifndef NO_BULK_LOGGING */ - } else { - - rv = cnat_mapped_static_port_alloc_v2_bulk (pm, - PORT_ALLOC_DIRECTED, &my_index, ko->k.k.ipv4, ko->k.k.port, - udb, BULKSIZE_FROM_VRFMAP(my_vrfmap), &nfv9_log_req, - my_vrfmap->ip_n_to_1); - - if (PREDICT_FALSE(rv != CNAT_SUCCESS)) { - info->error = rv; - CNAT_SET_ICMP_MSG_INFO - CNAT_DEBUG_INSIDE_ERR(rv) - log_port_alloc_error(rv, &(ki->k)); - return (NULL); - } - - /* - * increment port in use for this user - */ - udb->ntranslations += 1; - } - } else { - if (PREDICT_FALSE(global_debug_flag && CNAT_DEBUG_GLOBAL_ALL)) { - printf ("Static port alloc any\n"); - } - /* - * first time allocate port for this user - */ - - /* - * Check if main db has space for new entry - * Allowing a user db entry to be created if main db is not free - * will cause a port to be allocated to that user, which results in - * wastage of that port, hence the check is done here. - */ - h = pool_header(cnat_main_db); - free_main = vec_len(h->free_indices) - 1; - h = pool_header(cnat_user_db); - free_user = vec_len(h->free_indices) - 1; - - /* - * If either main_db or user_db does not have entries - * bail out, with appropriate error - */ - if (PREDICT_FALSE(!(free_main && free_user))) { - u32 log_error; - if(free_main) { - info->error = CNAT_USER_DB_LIMIT; - log_error = CNAT_USER_DB_LIMIT_ERROR; - } else { - info->error = CNAT_MAIN_DB_LIMIT; - log_error = CNAT_MAIN_DB_LIMIT_ERROR; - } - in2out_drops_system_limit_reached ++; - CNAT_SET_ICMP_MSG_INFO - CNAT_DEBUG_INSIDE_ERR(info->error) - spp_printf(log_error, 0, 0); - return NULL; - } - - rv = cnat_mapped_static_port_alloc_v2_bulk (pm, - PORT_ALLOC_ANY, &my_index, ko->k.k.ipv4, ko->k.k.port, - udb, BULKSIZE_FROM_VRFMAP(my_vrfmap), &nfv9_log_req, - my_vrfmap->ip_n_to_1); - - if (PREDICT_FALSE(rv != CNAT_SUCCESS)) { - info->error = rv; - in2out_drops_resource_depletion ++; - CNAT_SET_ICMP_MSG_INFO - CNAT_DEBUG_INSIDE_ERR(rv) - log_port_alloc_error(rv, &(ki->k)); - return (NULL); - } - /* - * create entry in user db - */ - udb = cnat_user_db_create_entry(&u_ki, my_index); - my_pm = pm + my_index; - if(PREDICT_TRUE(my_pm->private_ip_users_count < PORTS_PER_ADDR)) { - my_pm->private_ip_users_count++; -#ifdef DEBUG_PRINTF_IP_N_TO_1_ENABLED - PLATFORM_DEBUG_PRINT("\n cnat_create_static_main_db_entry_v2 " - "static alloc private_ip_users_count = %d", - my_pm->private_ip_users_count); -#endif - } else { - PLATFORM_DEBUG_PRINT("\n ERROR: private_ip_users_count has " - "reached MAX PORTS_PER_ADDR"); - } - NAT44_COMMON_STATS.num_subscribers++; -#ifndef NO_BULK_LOGGING - cnat_update_bulk_range_cache(udb, ko->k.k.port, - BULKSIZE_FROM_VRFMAP(my_vrfmap)); -#endif /* #ifndef NO_BULK_LOGGING */ - } - - /* - * step 3: - * outside port is allocated for this src vrf/src ip addr - * 1)create a new entry in main db - * 2)setup cnat_out2in_hash key - * 3)setup cnat_in2out_hash key - */ - db = cnat_create_main_db_entry_and_hash(ki, ko, udb); - - translation_create_count ++; - db->vrfmap_index = my_vrfmap - cnat_map_by_vrf; - - /* - * don't forget logging - * logging API is unconditional, - * logging configuration check is done inside the inline function - */ - - if(PREDICT_FALSE(nfv9_log_req != CACHE_ALLOC_NO_LOG_REQUIRED)) { - /* if session logging is enabled .. do not log as there is no - * traffic yet - */ - if(PREDICT_FALSE(my_vrfmap->nf_logging_policy != SESSION_LOG_ENABLE)) { - cnat_nfv9_log_mapping_create(db, my_vrfmap -#ifndef NO_BULK_LOGGING - , nfv9_log_req -#endif - ); - } - if(PREDICT_FALSE(my_vrfmap->syslog_logging_policy != SESSION_LOG_ENABLE)) { - cnat_syslog_nat44_mapping_create(db, my_vrfmap, 0 -#ifndef NO_BULK_LOGGING - , nfv9_log_req -#endif - ); - } - } - - return db; -} - - -cnat_main_db_entry_t* -dslite_main_db_lookup_entry(dslite_db_key_bucket_t *ki); - -cnat_user_db_entry_t* -dslite_user_db_lookup_entry(dslite_db_key_bucket_t *uki); - -cnat_user_db_entry_t* -dslite_user_db_create_entry(dslite_db_key_bucket_t *uki, u32 portmap_index); - -cnat_main_db_entry_t* -dslite_create_main_db_entry_and_hash(dslite_db_key_bucket_t *ki, - cnat_db_key_bucket_t *ko, - cnat_user_db_entry_t *udb); - -#ifdef TOBE_PORTED -/* - * this function is called from config handler only - * to allocate a static port based db entry - * - * the actual mapped address and port are already specified - */ -cnat_main_db_entry_t* -dslite_create_static_main_db_entry_v2 (dslite_db_key_bucket_t *ki, - cnat_db_key_bucket_t *ko, - dslite_table_entry_t *dslite_entry_ptr, - cnat_gen_icmp_info *info) -{ - u16 protocol; - u32 head; - cnat_errno_t rv; - dslite_db_key_bucket_t u_ki; - u32 my_index, free_main, free_user; - cnat_portmap_v2_t *pm =0; - cnat_portmap_v2_t *my_pm =0; - cnat_user_db_entry_t *udb = 0; - cnat_main_db_entry_t *db = 0; - pool_header_t *h; - u16 dslite_id = dslite_entry_ptr->dslite_id; -#ifndef NO_BULK_LOGGING - int nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED; -#endif - cnat_vrfmap_t *my_vrfmap =0; - u16 my_vrfmap_index; - - /* UNUSED. Therefore not ported to be multi-thread friendly */ - ASSERT(0); - /* - * need to try lookup again because - * second pkt may come here before the entry is created - * by receiving first pkt due to high line rate. - */ - info->gen_icmp_msg = CNAT_NO_ICMP_MSG; - info->error = CNAT_SUCCESS; - db = dslite_main_db_lookup_entry(ki); - - /* - * If we already have an entry with this inside address, port - * check delete the entry and proceed further. This should - * If yes, something is terribly wrong. Bail out - */ - if (PREDICT_FALSE(db)) { - - if (db->flags & CNAT_DB_FLAG_STATIC_PORT) { - - if ((db->out2in_key.k.ipv4 == ko->k.k.ipv4) && - (db->out2in_key.k.port == ko->k.k.port) && - (db->out2in_key.k.vrf == ko->k.k.vrf)) { - -#ifdef DEBUG_PRINTF_ENABLED - printf("Same Static Port Exists ki 0x%16llx ko 0x%16llx", - ki->k, ko->k); -#endif - /* - * We have already programmed this, return - */ - return (db); - } - - /* - * We already have a static port with different mapping - * Return an error for this case. - */ - info->error = CNAT_ERR_PARSER; - -#ifdef DEBUG_PRINTF_ENABLED - printf("Static Port Existing and Diff ki 0x%16llx ko 0x%16llx", - ki, db->out2in_key); -#endif - { - u32 arr[] = {STAT_PORT_CONFIG_IN_USE, (ki->dk.ipv4_key.k.vrf & CNAT_VRF_MASK), - ki->dk.ipv4_key.k.ipv4, ki->dk.ipv4_key.k.port, (ki->dk.ipv4_key.k.vrf & CNAT_PRO_MASK) }; - spp_printf(CNAT_CONFIG_ERROR, 5, arr); - } - return (db); - } - -#ifdef DEBUG_PRINTF_ENABLED - printf("Deleting Dynamic entry ki 0x%16llx ko 0x%16llx", - ki, db->out2in_key); -#endif - - /* - * If for some reason we have dynamic entries, just delete them - * and proceed. - */ - cnat_delete_main_db_entry_v2(db); - - db = NULL; - } - - - protocol = ki->dk.ipv4_key.k.vrf & CNAT_PRO_MASK; - u_ki.dk.ipv4_key.k.vrf = ki->dk.ipv4_key.k.vrf & CNAT_VRF_MASK; - u_ki.dk.ipv4_key.k.ipv4 = ki->dk.ipv4_key.k.ipv4; - u_ki.dk.ipv4_key.k.port = 0; - u_ki.dk.ipv6[0] = ki->dk.ipv6[0]; - u_ki.dk.ipv6[1] = ki->dk.ipv6[1]; - u_ki.dk.ipv6[2] = ki->dk.ipv6[2]; - u_ki.dk.ipv6[3] = ki->dk.ipv6[3]; - - my_vrfmap_index = vrf_map_array[u_ki.dk.ipv4_key.k.vrf]; - my_vrfmap = cnat_map_by_vrf + my_vrfmap_index; - - pm = dslite_entry_ptr->portmap_list; - - /* - * check if src vrf, src ip addr is already - * in the user db - * if yes, use PORT_ALLOC_DIRECTED - * if no, use PORT_ALLOC_ANY since it is first time - */ - udb = dslite_user_db_lookup_entry(&u_ki); - if (PREDICT_TRUE(udb)) { - /* - * check if main db has space to accomodate new entry - */ - h = pool_header(cnat_main_db); - - free_main = vec_len(h->free_indices) - 1; - if (PREDICT_FALSE(!free_main)) { - info->error = CNAT_MAIN_DB_LIMIT; - nat44_dslite_common_stats[dslite_id].in2out_drops_port_limit_exceeded ++; - DSLITE_DEBUG_INSIDE_ERR(CNAT_MAIN_DB_LIMIT) -#ifdef UT_TEST_CODE - printf("Limit reached : OLD USER"); -#endif - spp_printf(CNAT_MAIN_DB_LIMIT_ERROR, 0, 0); - return NULL; - } - - /* - * allocate port, from existing mapping - */ - my_index = udb->portmap_index; - my_pm = pm + my_index; - /* It is quite possible that we hit the scenario of CSCtj17774. - * Delete all the main db entries and add the ipv4 address sent by - * CGN-MA as Static port alloc any - */ - - if (PREDICT_FALSE(my_pm->ipv4_address != ko->k.k.ipv4)) { - if (PREDICT_FALSE(global_debug_flag && CNAT_DEBUG_GLOBAL_ALL)) { - printf("Delete Main db entry and check for" - " ipv4 address sanity pm add = 0x%x ip add = 0x%x\n", - my_pm->ipv4_address, ko->k.k.ipv4); - } - do { - /* udb is not NULL when we begin with for sure */ - head = udb->translation_list_head_index; - db = cnat_main_db + head; - cnat_delete_main_db_entry_v2(db); - } while (!pool_is_free(cnat_user_db, udb)); - - rv = cnat_mapped_static_port_alloc_v2_bulk (pm, - PORT_ALLOC_ANY, &my_index, ko->k.k.ipv4, ko->k.k.port, - udb, BULKSIZE_FROM_VRFMAP(dslite_entry_ptr), &nfv9_log_req, - my_vrfmap->ip_n_to_1); - - if (PREDICT_FALSE(rv != CNAT_SUCCESS)) { - info->error = rv; - nat44_dslite_common_stats[dslite_id].in2out_drops_port_limit_exceeded ++; - DSLITE_DEBUG_INSIDE_ERR(rv) - return (NULL); - } - /* - * create entry in user db - */ - udb = dslite_user_db_create_entry(&u_ki, my_index); - nat44_dslite_common_stats[dslite_id].num_subscribers++; -#ifndef NO_BULK_LOGGING - if(PREDICT_FALSE(udb && (BULK_ALLOC_NOT_ATTEMPTED != nfv9_log_req))) { - cnat_update_bulk_range_cache(udb, ko->k.k.port, - BULKSIZE_FROM_VRFMAP(dslite_entry_ptr)); - } -#endif /* #ifndef NO_BULK_LOGGING */ - } else { - - rv = cnat_mapped_static_port_alloc_v2_bulk (pm, - PORT_ALLOC_DIRECTED, &my_index, ko->k.k.ipv4, ko->k.k.port, - udb, BULKSIZE_FROM_VRFMAP(dslite_entry_ptr), &nfv9_log_req, - my_vrfmap->ip_n_to_1); - - if (PREDICT_FALSE(rv != CNAT_SUCCESS)) { - info->error = rv; - DSLITE_DEBUG_INSIDE_ERR(rv) - log_port_alloc_error(rv, &(ki->dk.ipv4_key)); - return (NULL); - } - - /* - * increment port in use for this user - */ - udb->ntranslations += 1; - } - } else { - if (PREDICT_FALSE(global_debug_flag && CNAT_DEBUG_GLOBAL_ALL)) { - printf ("Static port alloc any\n"); - } - /* - * first time allocate port for this user - */ - - /* - * Check if main db has space for new entry - * Allowing a user db entry to be created if main db is not free - * will cause a port to be allocated to that user, which results in - * wastage of that port, hence the check is done here. - */ - h = pool_header(cnat_main_db); - free_main = vec_len(h->free_indices) - 1; - h = pool_header(cnat_user_db); - free_user = vec_len(h->free_indices) - 1; - - /* - * If either main_db or user_db does not have entries - * bail out, with appropriate error - */ - if (PREDICT_FALSE(!(free_main && free_user))) { - u32 log_error; - if(free_main) { - info->error = CNAT_USER_DB_LIMIT; - log_error = CNAT_USER_DB_LIMIT_ERROR; - } else { - info->error = CNAT_MAIN_DB_LIMIT; - log_error = CNAT_MAIN_DB_LIMIT_ERROR; - } - nat44_dslite_common_stats[dslite_id].in2out_drops_port_limit_exceeded ++; - DSLITE_DEBUG_INSIDE_ERR(info->error) - spp_printf(log_error, 0, 0); - return NULL; - } - - rv = cnat_mapped_static_port_alloc_v2_bulk (pm, - PORT_ALLOC_ANY, &my_index, ko->k.k.ipv4, ko->k.k.port, - udb, BULKSIZE_FROM_VRFMAP(dslite_entry_ptr), &nfv9_log_req, - my_vrfmap->ip_n_to_1); - - if (PREDICT_FALSE(rv != CNAT_SUCCESS)) { - info->error = rv; - nat44_dslite_common_stats[dslite_id].in2out_drops_port_limit_exceeded ++; - DSLITE_DEBUG_INSIDE_ERR(rv) - log_port_alloc_error(rv, &(ki->dk.ipv4_key)); - return (NULL); - } - /* - * create entry in user db - */ - udb = dslite_user_db_create_entry(&u_ki, my_index); - nat44_dslite_common_stats[dslite_id].num_subscribers++; -#ifndef NO_BULK_LOGGING - if(PREDICT_FALSE(udb && (BULK_ALLOC_NOT_ATTEMPTED != nfv9_log_req))) { - cnat_update_bulk_range_cache(udb, ko->k.k.port, - BULKSIZE_FROM_VRFMAP(dslite_entry_ptr)); - } -#endif /* #ifndef NO_BULK_LOGGING */ - } - - /* - * step 3: - * outside port is allocated for this src vrf/src ip addr - * 1)create a new entry in main db - * 2)setup cnat_out2in_hash key - * 3)setup cnat_in2out_hash key - */ - db = dslite_create_main_db_entry_and_hash(ki, ko, udb); - db->dslite_nat44_inst_id = dslite_id; - nat44_dslite_common_stats[dslite_id].active_translations++; - dslite_translation_create_count++; - - /* - * don't forget logging - * logging API is unconditional, - * logging configuration check is done inside the inline function - */ -#if 0 /* TBD - NEED TO DECIDE ON LOGGING */ - if(PREDICT_FALSE(nfv9_log_req != CACHE_ALLOC_NO_LOG_REQUIRED)) { - /* if session logging is enabled .. do not log as there is no - * traffic yet - */ -#endif /* #if 0 - this has to be removed later */ - - return db; -} -#endif /* TOBE_PORTED */ - - -/* Per port/ip timeout related routines */ -static -u32 cnat_timeout_db_hash_lookup (cnat_key_t t_key) -{ - cnat_key_t key; - u64 a, b, c; - u32 index; - cnat_timeout_db_entry_t *db; - - key.k.ipv4 = t_key.k.ipv4; - key.k.port = t_key.k.port; - key.k.vrf = t_key.k.vrf; - - CNAT_V4_GET_HASH(key.key64, - index, CNAT_TIMEOUT_HASH_MASK) - - - index = cnat_timeout_hash[index].next; - - if (PREDICT_FALSE(index == EMPTY)) - return EMPTY; - - do { - db = cnat_timeout_db + index; - if (PREDICT_TRUE((db->t_key.timeout_key.key64 & CNAT_TIMEOUT_FULL_MASK) - == (key.key64 & CNAT_TIMEOUT_FULL_MASK))) - break; - index = db->t_hash.next; - } while (index != EMPTY); - - return index; -} - -/* Pass db_type as MAIN_DB_TYPE if you are passing - * cnat_main_db_entry_t * casted as void * for db - * else pass db_type as SESSION_DB_TYPE - */ -u16 -query_and_update_db_timeout(void *db, u8 db_type) -{ - cnat_key_t t_search_key; - u32 index; - cnat_timeout_db_entry_t *timeout_db_entry; - pool_header_t *h; - u32 free; - - cnat_main_db_entry_t *mdb = NULL; - cnat_session_entry_t *sdb = NULL; - - if(PREDICT_TRUE(db_type == MAIN_DB_TYPE)) { - mdb = (cnat_main_db_entry_t *)db; - } else if(db_type == SESSION_DB_TYPE) { - sdb = (cnat_session_entry_t *)db; - } else { - return 0; - } - - h = pool_header(cnat_timeout_db); - free = vec_len(h->free_indices) - 1; - - if(free == CNAT_TIMEOUT_HASH_SIZE) { - /* No timeout db configured */ - return 0; - } - - /* First search for ip/port pair */ - if(PREDICT_TRUE(db_type == MAIN_DB_TYPE)) { - t_search_key.k.ipv4 = mdb->dst_ipv4; - t_search_key.k.port = mdb->dst_port; - t_search_key.k.vrf = mdb->in2out_key.k.vrf; - } else { - t_search_key.k.ipv4 = sdb->v4_dest_key.k.ipv4; - t_search_key.k.port = sdb->v4_dest_key.k.port; - t_search_key.k.vrf = sdb->v4_dest_key.k.vrf; - } - - index = cnat_timeout_db_hash_lookup(t_search_key); - - if(index == EMPTY) { - /* Search for port map */ - t_search_key.k.ipv4 = 0; - - index = cnat_timeout_db_hash_lookup(t_search_key); - - if(index == EMPTY) { - /* Search for ip only map */ - if(PREDICT_TRUE(db_type == MAIN_DB_TYPE)) { - t_search_key.k.ipv4 = mdb->dst_ipv4; - } else { - t_search_key.k.ipv4 = sdb->v4_dest_key.k.ipv4; - } - t_search_key.k.port = 0; - - index = cnat_timeout_db_hash_lookup(t_search_key); - if(index != EMPTY) { -#ifdef DEBUG_PRINTF_ENABLED - printf("%s: ip only map sucess\n","query_and_update_db_timeout"); -#endif - } - } else { -#ifdef DEBUG_PRINTF_ENABLED - printf("%s: port only map sucess\n", "query_and_update_db_timeout"); -#endif - } - - } else { -#ifdef DEBUG_PRINTF_ENABLED - printf("%s: ip port map sucess\n","query_and_update_db_timeout"); -#endif - - } - - if(index == EMPTY) { - /* No match found, clear timeout */ - if(PREDICT_TRUE(db_type == MAIN_DB_TYPE)) { - mdb->timeout = 0; - } else { - sdb->timeout = 0; - } -#ifdef DEBUG_PRINTF_ENABLED - printf("%s: No match\n","query_and_update_db_timeout"); -#endif - } else { - /* Match found, update timeout */ - timeout_db_entry = cnat_timeout_db + index; - if(PREDICT_TRUE(db_type == MAIN_DB_TYPE)) { - mdb->timeout = timeout_db_entry->t_key.timeout_value; - } else { - sdb->timeout = timeout_db_entry->t_key.timeout_value; - } - return timeout_db_entry->t_key.timeout_value; - } - return 0; -} - - - -static -void cnat_timeout_db_hash_add (cnat_timeout_db_entry_t *t_entry) -{ - cnat_key_t key; - u64 a, b, c; - u32 index, bucket; - cnat_key_t t_key = t_entry->t_key.timeout_key; - - key.k.ipv4 = t_key.k.ipv4; - key.k.port = t_key.k.port; - key.k.vrf = t_key.k.vrf; - - CNAT_V4_GET_HASH(key.key64, - bucket, CNAT_TIMEOUT_HASH_MASK) - - - index = cnat_timeout_hash[bucket].next; - - /* Add this db entry to the head of the bucket chain */ - t_entry->t_hash.next = index; - cnat_timeout_hash[bucket].next = t_entry - cnat_timeout_db; -} - - - -u16 -cnat_timeout_db_create (cnat_timeout_t t_entry) -{ - cnat_timeout_db_entry_t *db; - cnat_key_t t_key = t_entry.timeout_key; - u32 db_index; - - pool_header_t *h; - u32 free; - - /* UNUSED. Therefore not ported to be multi-thread friendly */ - ASSERT(0); - - db_index = cnat_timeout_db_hash_lookup(t_key); - - if(db_index != EMPTY) { - /* Entry already exists. Check if it is replay or update */ - db = cnat_timeout_db + db_index; - db->t_key.timeout_value = t_entry.timeout_value; - return CNAT_SUCCESS; - } - - h = pool_header(cnat_timeout_db); - free = vec_len(h->free_indices) - 1; - - if(free == 0) { - return CNAT_OUT_LIMIT; - } - - - pool_get(cnat_timeout_db, db); - ASSERT(db); - - memset(db, 0, sizeof(*db)); - - db_index = db - cnat_timeout_db; - - db->t_key.timeout_key.k.ipv4 = t_key.k.ipv4; - db->t_key.timeout_key.k.port = t_key.k.port; - db->t_key.timeout_key.k.vrf = t_key.k.vrf; - db->t_key.timeout_value = t_entry.timeout_value; - - - cnat_timeout_db_hash_add(db); - return CNAT_SUCCESS; -} - -void cnat_timeout_db_delete(cnat_key_t t_key) -{ - cnat_key_t key; - u64 a, b, c; - u32 index, bucket; - cnat_timeout_db_entry_t *this, *prev; - - /* UNUSED. Therefore not ported to be multi-thread friendly */ - ASSERT(0); - - key.k.ipv4 = t_key.k.ipv4; - key.k.port = t_key.k.port; - key.k.vrf = t_key.k.vrf; - - - CNAT_V4_GET_HASH(key.key64, - bucket, CNAT_TIMEOUT_HASH_MASK) - - - index = cnat_timeout_hash[bucket].next; - - if(index == EMPTY) return; - - prev = 0; - do { - this = cnat_timeout_db + index; - if (PREDICT_TRUE( - (this->t_key.timeout_key.key64 & CNAT_TIMEOUT_FULL_MASK) == - (key.key64 & CNAT_TIMEOUT_FULL_MASK))) { - if (prev == 0) { - cnat_timeout_hash[bucket].next = this->t_hash.next; - goto found; - } else { - prev->t_hash.next = this->t_hash.next; - goto found; - } - } - - prev = this; - index = this->t_hash.next; - } while (index != EMPTY); - - if(index == EMPTY) return; - - found: - pool_put(cnat_timeout_db, this); - -} - -void cnat_session_db_hash_delete (cnat_session_entry_t *ep) -{ - u32 a, b, c; - u32 index, bucket; - cnat_session_entry_t *this, *prev; - - CNAT_V4_GET_SESSION_HASH(ep->main_db_index, ep->v4_dest_key.k.ipv4, - ep->v4_dest_key.k.port, ep->v4_dest_key.k.vrf, bucket, - CNAT_SESSION_HASH_MASK) - - - index = cnat_session_hash[bucket].next; - - ASSERT(index != EMPTY); - - prev = 0; - do { - this = cnat_session_db + index; - if (PREDICT_TRUE(this == ep)) { - if (prev == 0) { - cnat_session_hash[bucket].next = - ep->cnat_session_hash.next; - return; - } else { - prev->cnat_session_hash.next = - ep->cnat_session_hash.next; - return; - } - } - prev = this; - index = this->cnat_session_hash.next; - } while (index != EMPTY); - - ASSERT(0); - -} - -cnat_session_entry_t * -cnat_session_db_edm_lookup_entry(cnat_key_t *ko,u32 session_head_index, - u32 main_db_index) -{ - u32 index; - cnat_session_entry_t *db; - - - index = session_head_index; - if (PREDICT_TRUE(index == EMPTY)) { - return (NULL); - } - - do { - db = cnat_session_db + index; - if(PREDICT_TRUE((db->main_db_index == main_db_index) && - (db->v4_dest_key.k.vrf == ko->k.vrf) && - (db->v4_dest_key.k.ipv4 == ko->k.ipv4))) { - - return db; - } - index = db->cnat_session_hash.next; - } while (index != EMPTY); - - return (NULL); -} - - - -cnat_session_entry_t * -cnat_session_db_lookup_entry(cnat_key_t *ko,u32 main_db_index) -{ - u32 a, b, c; - u32 index, bucket; - cnat_session_entry_t *db; - - CNAT_V4_GET_SESSION_HASH(main_db_index, ko->k.ipv4, ko->k.port, - ko->k.vrf, bucket, CNAT_SESSION_HASH_MASK) - - - index = cnat_session_hash[bucket].next; - if (PREDICT_TRUE(index == EMPTY)) { - return (NULL); - } - - do { - db = cnat_session_db + index; - if(PREDICT_TRUE((db->main_db_index == main_db_index) && - (db->v4_dest_key.k.vrf == ko->k.vrf) && - (db->v4_dest_key.k.port == ko->k.port) && - (db->v4_dest_key.k.ipv4 == ko->k.ipv4))) { - - return db; - } - index = db->cnat_session_hash.next; - } while (index != EMPTY); - - return (NULL); -} - -cnat_session_entry_t * -cnat_create_session_db_entry(cnat_key_t *ko, - cnat_main_db_entry_t *bdb, u8 log) -{ - u32 a, b, c; - u32 db_index, bucket_out; - cnat_session_entry_t *db = NULL; - pool_header_t *h; - u32 free_session; - u16 instance; - - db = cnat_session_db_lookup_entry(ko, bdb - cnat_main_db); - if (PREDICT_FALSE(db != NULL)) { - /*printf("Create Session - Entry already Exists\n");*/ - return db; - } - - h = pool_header(cnat_session_db); - free_session = vec_len(h->free_indices) - 1; - - if (bdb->flags & CNAT_DB_DSLITE_FLAG) { - instance = bdb->dslite_nat44_inst_id; - } else { - instance = NAT44_RESERVED_INST_ID; - } - - if (PREDICT_FALSE(!free_session)) { - nat44_dslite_common_stats[instance].drops_sessiondb_limit_exceeded++; - return NULL; - } - - if( PREDICT_FALSE(bdb->nsessions == CNAT_MAX_SESSIONS_PER_BIB)) { - /* printf("Create Session - Max sessions per BIB reached\n"); */ - return NULL; - } - - pthread_spin_lock(cnat_db_v2_main.session_db_lockp); - pool_get(cnat_session_db, db); - memset(db, 0, sizeof(*db)); - - db_index = db - cnat_session_db; - db->v4_dest_key.k.port = ko->k.port; - db->v4_dest_key.k.ipv4 = ko->k.ipv4; - db->v4_dest_key.k.vrf = ko->k.vrf; - - db->main_list.next = db_index; - db->main_list.prev = db_index; - db->main_db_index = bdb - cnat_main_db; - - db->tcp_seq_num = 0; - db->ack_no = 0; - db->window = 0; - - if(PREDICT_FALSE(log)) { - bdb->nsessions++; - query_and_update_db_timeout(db, SESSION_DB_TYPE); - } - - if (PREDICT_FALSE(bdb->nsessions == 1)) { - /* - * first port for this src vrf/src ip addr - */ - bdb->session_head_index = db_index; - } else { - index_dlist_addtail(bdb->session_head_index, - (u8 *)cnat_session_db, sizeof(cnat_session_db[0]), - STRUCT_OFFSET_OF(cnat_session_entry_t, main_list), - db_index); - } - - /* - * setup o2i hash key - */ - CNAT_V4_GET_SESSION_HASH(db->main_db_index, ko->k.ipv4, ko->k.port, - ko->k.vrf, bucket_out, CNAT_SESSION_HASH_MASK) - - - db->cnat_session_hash.next = - cnat_session_hash[bucket_out].next; - cnat_session_hash[bucket_out].next = db_index; - - - if(PREDICT_FALSE(log)) { - if (bdb->flags & CNAT_DB_DSLITE_FLAG) { - cnat_session_log_ds_lite_mapping_create(bdb, - (dslite_table_db_ptr + instance),db); - } else { - cnat_vrfmap_t *my_vrfmap = cnat_map_by_vrf + bdb->vrfmap_index; - cnat_session_log_nat44_mapping_create(bdb, db, my_vrfmap); - } - } - - /* Need to set entry_expires here, as we need to override 0 check for - newly established sessions */ - db->entry_expires = cnat_current_time; - nat44_dslite_common_stats[instance].sessions++; - pthread_spin_unlock(cnat_db_v2_main.session_db_lockp); - return db; -} - -void -cnat_dest_update_main2session(cnat_main_db_entry_t *mdb, - cnat_session_entry_t *sdb) -{ - - sdb->flags = mdb->flags; - sdb->timeout = mdb->timeout; - sdb->entry_expires = mdb->entry_expires; - sdb->alg.delta = mdb->alg.delta; - sdb->tcp_seq_num = mdb->proto_data.seq_pcp.tcp_seq_num; - - /* Reset Main db values to 0 */ - /* Reset only session specific flags */ - mdb->flags &= ~(CNAT_DB_FLAG_TCP_ACTIVE | CNAT_DB_FLAG_UDP_ACTIVE - | CNAT_DB_FLAG_ALG_ENTRY | CNAT_DB_FLAG_ALG_CTRL_FLOW); - mdb->timeout = 0; - mdb->entry_expires = 0; - mdb->alg.delta = 0; - if(PREDICT_FALSE(!((mdb->flags & CNAT_DB_FLAG_PPTP_TUNNEL_ACTIVE) || - (mdb->flags & CNAT_DB_FLAG_PPTP_TUNNEL_INIT)))) { - mdb->proto_data.seq_pcp.tcp_seq_num = 0; - } - - mdb->dst_ipv4 = 0; - mdb->dst_port = 0; -} - - -void -cnat_dest_update_session2main(cnat_main_db_entry_t *mdb, - cnat_session_entry_t *sdb) -{ - - u16 flags = sdb->flags & (CNAT_DB_FLAG_TCP_ACTIVE | - CNAT_DB_FLAG_UDP_ACTIVE | CNAT_DB_FLAG_ALG_ENTRY | - CNAT_DB_FLAG_ALG_CTRL_FLOW); - mdb->flags |= flags; - mdb->timeout = sdb->timeout; - mdb->entry_expires = sdb->entry_expires; - mdb->alg.delta = sdb->alg.delta; - if(PREDICT_FALSE(!((mdb->flags & CNAT_DB_FLAG_PPTP_TUNNEL_ACTIVE) || - (mdb->flags & CNAT_DB_FLAG_PPTP_TUNNEL_INIT)))) { - mdb->proto_data.seq_pcp.tcp_seq_num = sdb->tcp_seq_num; - } - mdb->dst_ipv4 = sdb->v4_dest_key.k.ipv4; - mdb->dst_port = sdb->v4_dest_key.k.port; -} - -static void -_cnat_delete_session_db_entry (cnat_session_entry_t *ep, u8 log) -{ - u32 session_db_index; - u32 bdb_len; - cnat_main_db_entry_t *be =0; - cnat_session_entry_t *sdb_last = NULL; - u16 instance; - - if (PREDICT_FALSE(ep->flags & CNAT_DB_NAT64_FLAG) != 0) { - /* Preventive check - Not a NAT44 entry */ - return; - } - - pool_header_t *h = pool_header(cnat_main_db); - - /* Validate .. just in case we are trying to delete a non existing one */ - bdb_len = vec_len(cnat_main_db); - - /* In case of invalid user just return, deleting only main db - * is not a good idea, since some valid user db entry might be pointing - * to that main db and hence leave the dbs in a inconsistent state - */ - if (PREDICT_FALSE((ep->main_db_index >= bdb_len) || - (clib_bitmap_get(h->free_bitmap, ep->main_db_index)))) { -#ifdef DEBUG_PRINTF_ENABLED - printf("invalid/unused user index in db %d\n", ep->main_db_index); -#endif - spp_printf(CNAT_INV_UNUSED_USR_INDEX, 1, (u32 *) &(ep->main_db_index)); - return; - } - - be = cnat_main_db + ep->main_db_index; - - session_db_index = ep - cnat_session_db; - - be->session_head_index = index_dlist_remelem ( - be->session_head_index, (u8 *)cnat_session_db, - sizeof (cnat_session_db[0]), - STRUCT_OFFSET_OF(cnat_session_entry_t, main_list), - session_db_index); - - if (be->flags & CNAT_DB_DSLITE_FLAG) { - instance = be->dslite_nat44_inst_id; - } else { - instance = NAT44_RESERVED_INST_ID; - } - - if(PREDICT_TRUE(log)) { - if (be->flags & CNAT_DB_DSLITE_FLAG) { - cnat_session_log_ds_lite_mapping_delete(be, - (dslite_table_db_ptr + instance),ep); - } else { - cnat_vrfmap_t *my_vrfmap = cnat_map_by_vrf + be->vrfmap_index; - cnat_session_log_nat44_mapping_delete(be, ep, my_vrfmap); - } - be->nsessions--; - } - - if (PREDICT_FALSE(be->nsessions == 1 && log)) { - /* There is only 1 session left - * Copy the info back to main db and release the last - * existing session - */ - - sdb_last = cnat_session_db + be->session_head_index; - ASSERT(sdb_last != NULL); - - cnat_dest_update_session2main(be, sdb_last); - _cnat_delete_session_db_entry(sdb_last, FALSE); - } - - /* Remove from session DB hashes */ - cnat_session_db_hash_delete(ep); - nat44_dslite_common_stats[instance].sessions--; - - pool_put(cnat_session_db, ep); -} - -void cnat_delete_session_db_entry (cnat_session_entry_t *ep, u8 log) -{ - pthread_spin_lock(cnat_db_v2_main.session_db_lockp); - _cnat_delete_session_db_entry (ep, log); - pthread_spin_unlock(cnat_db_v2_main.session_db_lockp); -} - -cnat_main_db_entry_t* -dslite_main_db_lookup_entry(dslite_db_key_bucket_t *ki) -{ - u64 a, b, c; - u32 index; - cnat_main_db_entry_t *db; - cnat_user_db_entry_t *userdb; - - DSLITE_V6_GET_HASH((&(ki->dk)), - ki->bucket, - CNAT_MAIN_HASH_MASK); - - DSLITE_PRINTF(1,"MDBLU hash..%u\n", ki->bucket); - - index = cnat_in2out_hash[ki->bucket].next; - if (PREDICT_TRUE(index == EMPTY)) { - DSLITE_PRINTF(1,"MDBLU index MT..\n"); - return (NULL); - } - - do { -/* We can add a flag here to indicate if the db entry is for nat44 or - * dslite. If the db entry is for nat44 then we can simply move to the - * one. - */ - db = cnat_main_db + index; - userdb = cnat_user_db + db->user_index; - if (PREDICT_TRUE(db->in2out_key.key64 == ki->dk.ipv4_key.key64) - && userdb->ipv6[0] == ki->dk.ipv6[0] - && userdb->ipv6[1] == ki->dk.ipv6[1] - && userdb->ipv6[2] == ki->dk.ipv6[2] - && userdb->ipv6[3] == ki->dk.ipv6[3]) { - DSLITE_PRINTF(1,"MDBLU success..%u\n", index); - return db; - } - index = db->in2out_hash.next; - } while (index != EMPTY); - - DSLITE_PRINTF(1,"MDBLU Entry does not exist..\n"); - return (NULL); -} - -cnat_user_db_entry_t* -dslite_user_db_lookup_entry(dslite_db_key_bucket_t *uki) -{ - u64 a, b, c; - u32 index; - cnat_user_db_entry_t *udb=NULL; - - DSLITE_V6_GET_HASH((&(uki->dk)), - uki->bucket, - CNAT_USER_HASH_MASK) - - DSLITE_PRINTF(1,"UDBLU hash..%u\n", uki->bucket); - - /* now: index in user vector */ - index = cnat_user_hash[uki->bucket].next; - if (PREDICT_TRUE(index != EMPTY)) { - DSLITE_PRINTF(1,"UDBLU hash table entry not MT..\n"); - do { - udb = cnat_user_db + index; - if (PREDICT_FALSE(udb->key.key64 == uki->dk.ipv4_key.key64) - && udb->ipv6[0] == uki->dk.ipv6[0] - && udb->ipv6[1] == uki->dk.ipv6[1] - && udb->ipv6[2] == uki->dk.ipv6[2] - && udb->ipv6[3] == uki->dk.ipv6[3]) { - DSLITE_PRINTF(1,"UDBLU success..%u\n", index); - return udb; - } - index = udb->user_hash.next; - } while (index != EMPTY); - } - DSLITE_PRINTF(1,"UDBLU Entry doesnt exist..\n"); - return (NULL); -} - -cnat_user_db_entry_t* -dslite_user_db_create_entry(dslite_db_key_bucket_t *uki, - u32 portmap_index) -{ - cnat_user_db_entry_t *udb = NULL; - - /* UNUSED. Therefore not ported to be multi-thread friendly */ - ASSERT(0); - - pool_get(cnat_user_db, udb); - memset(udb, 0, sizeof(*udb)); - - udb->ntranslations = 1; - udb->portmap_index = portmap_index; -// udb->key.key64 = uki->k.key64; - - udb->key.key64 = uki->dk.ipv4_key.key64; - udb->ipv6[0] = uki->dk.ipv6[0]; - udb->ipv6[1] = uki->dk.ipv6[1]; - udb->ipv6[2] = uki->dk.ipv6[2]; - udb->ipv6[3] = uki->dk.ipv6[3]; - - udb->flags |= CNAT_USER_DB_DSLITE_FLAG; - /* Add this user to the head of the bucket chain */ - udb->user_hash.next = - cnat_user_hash[uki->bucket].next; - cnat_user_hash[uki->bucket].next = udb - cnat_user_db; - -#ifndef NO_BULK_LOGGING - INIT_BULK_CACHE(udb) -#endif /* NO_BULK_LOGGING */ - - return udb; -} - -#ifndef TOBE_PORTED -cnat_main_db_entry_t* -dslite_create_main_db_entry_and_hash(dslite_db_key_bucket_t *ki, - cnat_db_key_bucket_t *ko, - cnat_user_db_entry_t *udb) -{ - return 0; -} -#else -cnat_main_db_entry_t* -dslite_create_main_db_entry_and_hash(dslite_db_key_bucket_t *ki, - cnat_db_key_bucket_t *ko, - cnat_user_db_entry_t *udb) -{ - u64 a, b, c; - u32 db_index; - cnat_main_db_entry_t *db = NULL; - - /* UNUSED. Therefore not ported to be multi-thread friendly */ - ASSERT(0); - - pool_get(cnat_main_db, db); - memset(db, 0, sizeof(*db)); - - db_index = db - cnat_main_db; - db->in2out_key.k.ipv4 = ki->dk.ipv4_key.k.ipv4; - db->in2out_key.k.port = ki->dk.ipv4_key.k.port; - db->in2out_key.k.vrf = ki->dk.ipv4_key.k.vrf; - db->out2in_key.k.ipv4 = ko->k.k.ipv4; - db->out2in_key.k.port = ko->k.k.port; - db->out2in_key.k.vrf = ko->k.k.vrf; - - db->user_ports.next = db_index; - db->user_ports.prev = db_index; - db->user_index = udb - cnat_user_db; - //db->portmap_index = udb->portmap_index; - db->flags |= CNAT_DB_DSLITE_FLAG; - - if (PREDICT_FALSE(udb->ntranslations == 1)) { - /* - * first port for this src vrf/src ip addr - */ - udb->translation_list_head_index = db_index; - DSLITE_PRINTF(1,"First translation of this user..\n"); - } else { - index_dlist_addtail(udb->translation_list_head_index, - (u8 *)cnat_main_db, sizeof(cnat_main_db[0]), - STRUCT_OFFSET_OF(cnat_main_db_entry_t, user_ports), - db_index); - } - - /* - * setup o2i hash key - */ - CNAT_V4_GET_HASH(ko->k.key64, - ko->bucket, - CNAT_MAIN_HASH_MASK) - db->out2in_hash.next = cnat_out2in_hash[ko->bucket].next; - cnat_out2in_hash[ko->bucket].next = db_index; - /* - * setup i2o hash key, bucket is already calculate - */ - db->in2out_hash.next = cnat_in2out_hash[ki->bucket].next; - cnat_in2out_hash[ki->bucket].next = db_index; - - DSLITE_PRINTF(1,"Create main db and hash..%u %u %u %u %x\n", - ki->bucket, ko->bucket, - db_index, db->user_index, ko->k.key64); - -#if DEBUG > 1 - printf("\nMy_Instance_Number %d: Bucket %d, Db_Index %d", - my_instance_number, ki->bucket, db_index); - printf("\nInside (VRF 0x%x, IP 0x%x, PORT 0x%x)", - db->in2out_key.k.vrf, db->in2out_key.k.ipv4, db->in2out_key.k.port); - printf("\nOutside (VRF 0x%x, IP 0x%x, PORT 0x%x)", - db->out2in_key.k.vrf, db->out2in_key.k.ipv4, db->out2in_key.k.port); - printf("\nUser Index %d, IP 0x%x", - db->user_index, udb->key.k.ipv4); -#endif - - //nat44_dslite_common_stats[DSLITE_COMMON_STATS].active_translations++; - - return db; -} - -static inline void handle_dslite_port_exceeded_logging( - cnat_user_db_entry_t *udb, - dslite_key_t * key, - dslite_table_entry_t *dslite_entry_ptr) -{ - - if(PREDICT_TRUE(udb->flags & CNAT_USER_DB_PORT_LIMIT_EXCEEDED)) { - /* Already logged ..*/ - return; - } - - /* else, set the flag and call the log API */ - udb->flags = udb->flags | CNAT_USER_DB_PORT_LIMIT_EXCEEDED; - cnat_log_ds_lite_port_limit_exceeded(key, dslite_entry_ptr); - return; -} -#endif - -void handle_cnat_port_exceeded_logging( - cnat_user_db_entry_t *udb, - cnat_key_t * key, - cnat_vrfmap_t *vrfmap) -{ - - if(PREDICT_TRUE(udb->flags & CNAT_USER_DB_PORT_LIMIT_EXCEEDED)) { - /* Already logged ..*/ - return; - } - - /* else, set the flag and call the log API */ - udb->flags = udb->flags | CNAT_USER_DB_PORT_LIMIT_EXCEEDED; - cnat_log_nat44_port_limit_exceeded(key,vrfmap); - return; -} - -#ifndef TOBE_PORTED -cnat_main_db_entry_t* -dslite_get_main_db_entry_v2(dslite_db_key_bucket_t *ki, - port_pair_t port_pair_type, - port_type_t port_type, - cnat_gen_icmp_info *info, - dslite_table_entry_t *dslite_entry_ptr, - cnat_key_t *dest_info) -{ - return 0; -} -#else -/* - * this function is called by exception node - * when lookup is fialed in i2o node - * - * if reash per user port limit, - * set user_db_entry pointer, and error == CNAT_OUT_LIMIT - */ -cnat_main_db_entry_t* -dslite_get_main_db_entry_v2(dslite_db_key_bucket_t *ki, - port_pair_t port_pair_type, - port_type_t port_type, - cnat_gen_icmp_info *info, - dslite_table_entry_t *dslite_entry_ptr, - cnat_key_t *dest_info) -{ - u16 protocol; - cnat_errno_t rv; - dslite_db_key_bucket_t u_ki; - cnat_db_key_bucket_t ko; - u32 my_index, free_main, free_user; - u32 current_timestamp; - cnat_vrfmap_t *my_vrfmap =0; - u16 my_vrfmap_index; - cnat_portmap_v2_t *pm =0; - cnat_user_db_entry_t *udb = 0; - cnat_main_db_entry_t *db = 0; - pool_header_t *h; - u16 dslite_id = dslite_entry_ptr->dslite_id; - -#ifndef NO_BULK_LOGGING - int nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED; -#endif - - /* UNUSED. Therefore not ported to be multi-thread friendly */ - ASSERT(0); - - /* - * need to try lookup again because - * second pkt may come here before the entry is created - * by receiving first pkt due to high line rate. - */ - info->gen_icmp_msg = CNAT_NO_ICMP_MSG; - info->error = CNAT_SUCCESS; - db = dslite_main_db_lookup_entry(ki); - if (PREDICT_TRUE(db)) { - /* what if the source is talking to a - * new dest now? We will have to handle this case and - * take care of - creating session db and logging - */ - if(PREDICT_FALSE((!dest_info->k.ipv4) && (!dest_info->k.port))) { - return db; /* if dest_info is null don't create session */ - } - - if(PREDICT_TRUE((db->dst_ipv4 == dest_info->k.ipv4) && - (db->dst_port == dest_info->k.port))) { - return db; - } - dest_info->k.vrf = db->in2out_key.k.vrf; - /* Src is indeed talking to a different dest */ - cnat_session_entry_t *session_db2 = NULL; - if(PREDICT_TRUE(db->nsessions == 1)) { - session_db2 = cnat_handle_1to2_session(db, dest_info); - if(PREDICT_TRUE(session_db2 != NULL)) { - CNAT_DB_TIMEOUT_RST(session_db2); - return db; - } else { - info->error = CNAT_ERR_NO_SESSION_DB; - return NULL; - } - } else if(PREDICT_FALSE(db->nsessions == 0)) { - /* Should be static entry.. should never happen - */ - if(PREDICT_TRUE(dest_info->k.ipv4 != 0)) { - cnat_add_dest_n_log(db, dest_info); - } - return db; - } else { - /* The src has already created multiple sessions.. very rare - */ - session_db2 = cnat_create_session_db_entry(dest_info, - db, TRUE); - if(PREDICT_TRUE(session_db2 != NULL)) { - CNAT_DB_TIMEOUT_RST(session_db2); - return db; - } else { - info->error = CNAT_ERR_NO_SESSION_DB; - return NULL; - } - } - - } - - /* - * step 1. check if outside vrf is configured or not - * and Find the set of portmaps for the outside vrf - * insider vrf is one to one mappted to outside vrf - * key is vrf and ip only - * ki.k.k.vrf has protocol bits, mask out - */ - protocol = ki->dk.ipv4_key.k.vrf & CNAT_PRO_MASK; - u_ki.dk.ipv4_key.k.vrf = ki->dk.ipv4_key.k.vrf & CNAT_VRF_MASK; -#ifdef DSLITE_USER_IPV4 - u_ki.dk.ipv4_key.k.ipv4 = ki->dk.ipv4_key.k.ipv4; -#else - /* - * Inside ipv4 address should be masked, if port limit - * need to be done at B4 element level. - */ - u_ki.dk.ipv4_key.k.ipv4 = 0; -#endif - u_ki.dk.ipv4_key.k.port = 0; - - u_ki.dk.ipv6[0] = ki->dk.ipv6[0]; - u_ki.dk.ipv6[1] = ki->dk.ipv6[1]; - u_ki.dk.ipv6[2] = ki->dk.ipv6[2]; - u_ki.dk.ipv6[3] = ki->dk.ipv6[3]; - - my_vrfmap_index = vrf_map_array[u_ki.dk.ipv4_key.k.vrf]; - my_vrfmap = cnat_map_by_vrf + my_vrfmap_index; -/* Checking if the inst entry is active or not is done much earlier - */ -#if 0 - my_vrfmap_index = vrf_map_array[u_ki.k.k.vrf]; - my_vrfmap = cnat_map_by_vrf + my_vrfmap_index; - my_vrfmap_entry_found = ((my_vrfmap_index != VRF_MAP_ENTRY_EMPTY) && - (my_vrfmap->status == S_RUN) && - (my_vrfmap->i_vrf == u_ki.k.k.vrf)); - - if (PREDICT_FALSE(!my_vrfmap_entry_found)) { - u32 arr[] = {ki->k.k.vrf, ki->k.k.ipv4, ki->k.k.port}; - if ((my_vrfmap_index == VRF_MAP_ENTRY_EMPTY) || - (my_vrfmap->i_vrf == u_ki.k.k.vrf)) { - info->error = CNAT_NO_CONFIG; - CNAT_DEBUG_INSIDE_ERR(CNAT_NO_CONFIG) - spp_printf(CNAT_NO_CONFIG_ERROR, 3, arr); - } else { - info->error = CNAT_NO_VRF_RUN; - CNAT_DEBUG_INSIDE_ERR(CNAT_NO_VRF_RUN) - spp_printf(CNAT_NO_VRF_RUN_ERROR, 3, arr); - } - - return (NULL); - } -#endif -/* - dslite_inst_ptr = dslite_nat44_config_table[dslite_inst_id]; -*/ - pm = dslite_entry_ptr->portmap_list; - //pm = my_vrfmap->portmap_list; - - /* - * set o2i key with protocl bits - */ - ko.k.k.vrf = dslite_entry_ptr->o_vrf | protocol; - //ko.k.k.vrf = my_vrfmap->o_vrf | protocol; - - /* - * step 2. check if src vrf, src ip addr is alreay - * in the user db - * if yes, use PORT_ALLOC_DIRECTED - * if no, use PORT_ALLOC_ANY since it is first time - */ - udb = dslite_user_db_lookup_entry(&u_ki); - if (PREDICT_TRUE(udb)) { - /* - * not first time allocate port for this user - * check limit - */ - if (PREDICT_FALSE(udb->ntranslations >= - dslite_entry_ptr->cnat_main_db_max_ports_per_user)) { - //cnat_main_db_max_ports_per_user)) - - /* Check for the port type here. If we are getting - * a STATIC PORT, allow the config. - */ - if (PREDICT_TRUE(port_type != PORT_TYPE_STATIC)) { - info->error = CNAT_OUT_LIMIT; - DSLITE_DEBUG_INSIDE_ERR(CNAT_OUT_LIMIT) - port_exceeded_msg_log(u_ki.dk.ipv4_key.k.ipv4, u_ki.dk.ipv4_key.k.vrf); - nat44_dslite_common_stats[dslite_id].in2out_drops_port_limit_exceeded ++; - u_ki.dk.ipv4_key.k.vrf = ki->dk.ipv4_key.k.vrf; - u_ki.dk.ipv4_key.k.port = ki->dk.ipv4_key.k.port; - handle_dslite_port_exceeded_logging(udb, &u_ki.dk, dslite_entry_ptr); - return (NULL); - } - } - - CHECK_CLEAR_PORT_LIMIT_EXCEED_FLAG(udb, - dslite_entry_ptr->cnat_main_db_max_ports_per_user) - - /* - * check if main db has space to accomodate new entry - */ - h = pool_header(cnat_main_db); - - free_main = vec_len(h->free_indices) - 1; - if (PREDICT_FALSE(!free_main)) { - info->error = CNAT_MAIN_DB_LIMIT; - nat44_dslite_common_stats[dslite_id].in2out_drops_system_limit_reached ++; - DSLITE_DEBUG_INSIDE_ERR(CNAT_MAIN_DB_LIMIT) - - current_timestamp = spp_trace_log_get_unix_time_in_seconds(); - if (PREDICT_FALSE((current_timestamp - last_log_timestamp) > - 1800)) { - spp_printf(CNAT_SESSION_THRESH_EXCEEDED, 0, NULL); - last_log_timestamp = current_timestamp; - } - -#ifdef UT_TEST_CODE - printf("Limit reached : OLD USER"); -#endif - return NULL; - } - - /* - * allocate port, from existing mapping - */ - my_index = udb->portmap_index; - - if (PREDICT_FALSE(port_type == PORT_TYPE_STATIC)) { - rv = cnat_static_port_alloc_v2_bulk(pm, - PORT_ALLOC_DIRECTED, - port_pair_type, - ki->dk.ipv4_key.k.ipv4, - ki->dk.ipv4_key.k.port, - &my_index, - &(ko.k.k.ipv4), - &(ko.k.k.port), - STAT_PORT_RANGE_FROM_INST_PTR(dslite_entry_ptr) -#ifndef NO_BULK_LOGGING - , udb, - BULKSIZE_FROM_VRFMAP(dslite_entry_ptr), - &nfv9_log_req -#endif - , my_vrfmap->ip_n_to_1 - ); - } else if (PREDICT_TRUE(port_type != PORT_TYPE_RTSP) ) { - - rv = cnat_dynamic_port_alloc_v2_bulk(pm, - PORT_ALLOC_DIRECTED, - port_pair_type, - &my_index, - &(ko.k.k.ipv4), - &(ko.k.k.port), - STAT_PORT_RANGE_FROM_INST_PTR(dslite_entry_ptr) -#ifndef NO_BULK_LOGGING - , udb, - BULKSIZE_FROM_VRFMAP(dslite_entry_ptr), - &nfv9_log_req -#endif - , 0, - &(dslite_entry_ptr->rseed_ip) - ); - DSLITE_PRINTF(1,"D_PORT_ALLOC %x %u\n", ko.k.k.ipv4, ko.k.k.port); - } else { - /* - * For RTSP, two translation entries are created, - * check if main db has space to accomodate two new entry - */ - free_main = free_main - 1; - - if (PREDICT_FALSE(!free_main)) { - info->error = CNAT_MAIN_DB_LIMIT; - nat44_dslite_common_stats[dslite_id].in2out_drops_system_limit_reached ++; - DSLITE_DEBUG_INSIDE_ERR(CNAT_MAIN_DB_LIMIT) - - return NULL; - } else { - - rv = cnat_dynamic_port_alloc_rtsp_bulk(pm, - PORT_ALLOC_DIRECTED, - port_pair_type, - ki->dk.ipv4_key.k.port, - &my_index, - &(ko.k.k.ipv4), - &(ko.k.k.port), - STAT_PORT_RANGE_FROM_INST_PTR(dslite_entry_ptr) -#ifndef NO_BULK_LOGGING - , udb, - BULKSIZE_FROM_VRFMAP(dslite_entry_ptr), - &nfv9_log_req -#endif - , &(dslite_entry_ptr->rseed_ip) - ); - } - } - - if (PREDICT_FALSE(rv != CNAT_SUCCESS)) { - DSLITE_PRINTF(1,"D_PORT_ALLOC port alloc error\n"); - info->error = rv; - DSLITE_DEBUG_INSIDE_ERR(rv) - nat44_dslite_common_stats[dslite_id].in2out_drops_resource_depletion ++; - log_port_alloc_error(rv, &(ki->dk.ipv4_key)); - return (NULL); - } - /* - * increment port in use for this user - */ - udb->ntranslations += 1; - } else { - /* - * first time allocate port for this user - */ - - /* - * Do not create entry if port limit is invalid - */ - if (PREDICT_FALSE(!(dslite_entry_ptr->cnat_main_db_max_ports_per_user))) { - if (PREDICT_TRUE(port_type != PORT_TYPE_STATIC)) { - info->error = CNAT_OUT_LIMIT; - nat44_dslite_common_stats[dslite_id].in2out_drops_port_limit_exceeded ++; - port_exceeded_msg_log(u_ki.dk.ipv4_key.k.ipv4, u_ki.dk.ipv4_key.k.vrf); - DSLITE_DEBUG_INSIDE_ERR(CNAT_OUT_LIMIT) - return (NULL); - } - } - - /* - * Check if main db has space for new entry - * Allowing a user db entry to be created if main db is not free - * will cause a port to be allocated to that user, which results in - * wastage of that port, hence the check is done here. - */ - h = pool_header(cnat_main_db); - free_main = vec_len(h->free_indices) - 1; - - h = pool_header(cnat_user_db); - free_user = vec_len(h->free_indices) - 1; - - /* - * If either main_db or user_db does not have entries - * bail out, with appropriate error - */ - if (PREDICT_FALSE(!(free_main && free_user))) { - u32 log_error; - if(free_main) { - info->error = CNAT_USER_DB_LIMIT; - log_error = CNAT_USER_DB_LIMIT_ERROR; - } else { - info->error = CNAT_MAIN_DB_LIMIT; - log_error = CNAT_MAIN_DB_LIMIT_ERROR; - } - nat44_dslite_common_stats[dslite_id].in2out_drops_system_limit_reached ++; - DSLITE_DEBUG_INSIDE_ERR(info->error) - spp_printf(log_error, 0, 0); - return NULL; - } - - if (PREDICT_FALSE(port_type == PORT_TYPE_STATIC)) { - rv = cnat_static_port_alloc_v2_bulk(pm, - PORT_ALLOC_ANY, - port_pair_type, - ki->dk.ipv4_key.k.ipv4, - ki->dk.ipv4_key.k.port, - &my_index, - &(ko.k.k.ipv4), - &(ko.k.k.port), - STAT_PORT_RANGE_FROM_INST_PTR(dslite_entry_ptr) -#ifndef NO_BULK_LOGGING - , NULL, - BULKSIZE_FROM_VRFMAP(dslite_entry_ptr), - &nfv9_log_req -#endif - , my_vrfmap->ip_n_to_1 - - ); - } else if (PREDICT_TRUE(port_type != PORT_TYPE_RTSP)) { - rv = cnat_dynamic_port_alloc_v2_bulk(pm, - PORT_ALLOC_ANY, - port_pair_type, - &my_index, - &(ko.k.k.ipv4), - &(ko.k.k.port), - STAT_PORT_RANGE_FROM_INST_PTR(dslite_entry_ptr) -#ifndef NO_BULK_LOGGING - , NULL, - BULKSIZE_FROM_VRFMAP(dslite_entry_ptr), - &nfv9_log_req -#endif - , 0, - &(dslite_entry_ptr->rseed_ip) - ); - DSLITE_PRINTF(1,"NU:D PORT ALLOC..%x %u\n", ko.k.k.ipv4, - ko.k.k.port); - - } else { - /* - * For RTSP, two translation entries are created, - * check if main db has space to accomodate two new entry - */ - free_main = free_main - 1; - - if (PREDICT_FALSE(!free_main)) { - info->error = CNAT_MAIN_DB_LIMIT; - nat44_dslite_common_stats[dslite_id].in2out_drops_system_limit_reached ++; - DSLITE_DEBUG_INSIDE_ERR(CNAT_MAIN_DB_LIMIT) - - return NULL; - } else { - - rv = cnat_dynamic_port_alloc_rtsp_bulk(pm, - PORT_ALLOC_DIRECTED, - port_pair_type, - ki->dk.ipv4_key.k.port, - &my_index, - &(ko.k.k.ipv4), - &(ko.k.k.port), - STAT_PORT_RANGE_FROM_INST_PTR(dslite_entry_ptr) -#ifndef NO_BULK_LOGGING - , NULL, - BULKSIZE_FROM_VRFMAP(dslite_entry_ptr), - &nfv9_log_req -#endif - , &(dslite_entry_ptr->rseed_ip) - ); - /* TODO: Add the port pair flag here */ - } - } - - - - if (PREDICT_FALSE(rv != CNAT_SUCCESS)) { - DSLITE_PRINTF(1,"NU:D_PORT_ALLOC port alloc error\n"); - info->error = rv; - nat44_dslite_common_stats[dslite_id].in2out_drops_resource_depletion ++; - DSLITE_DEBUG_INSIDE_ERR(rv) - log_port_alloc_error(rv, &(ki->dk.ipv4_key)); - return (NULL); - } - /* - * create entry in user db - */ - udb = dslite_user_db_create_entry(&u_ki, my_index); - nat44_dslite_common_stats[dslite_id].num_subscribers++; - DSLITE_PRINTF(1,"UDB crete entry done..\n"); -#ifndef NO_BULK_LOGGING - if(PREDICT_TRUE(udb && (BULK_ALLOC_NOT_ATTEMPTED != nfv9_log_req))) { - cnat_update_bulk_range_cache(udb, ko.k.k.port, - BULKSIZE_FROM_VRFMAP(dslite_entry_ptr)); - } -#endif /* #ifndef NO_BULK_LOGGING */ - } - - /* - * step 3: - * outside port is allocated for this src vrf/src ip addr - * 1)create a new entry in main db - * 2)setup cnat_out2in_hash key - * 3)setup cnat_in2out_hash key - */ - db = dslite_create_main_db_entry_and_hash(ki, &ko, udb); - DSLITE_PRINTF(1,"dslite_create_main_db_entry_and_hash done..\n"); - //db->vrfmap_index = my_vrfmap - cnat_map_by_vrf; - db->dslite_nat44_inst_id = dslite_id; - nat44_dslite_common_stats[dslite_id].active_translations++; - if (PREDICT_FALSE(port_type == PORT_TYPE_STATIC)) { - nat44_dslite_common_stats[dslite_id].num_static_translations++; - } else { - nat44_dslite_common_stats[dslite_id].num_dynamic_translations++; - } - - dslite_translation_create_count++; - - db->dst_ipv4 = dest_info->k.ipv4; - db->dst_port = dest_info->k.port; - if(PREDICT_TRUE(db->dst_ipv4 || db->dst_port)) { - /* for static fwding, let the nsessions remain zero */ - db->nsessions++; - } - - /* - * don't forget logging - * logging API is unconditional, - * logging configuration check is done inside the inline function - */ - if(PREDICT_FALSE(nfv9_log_req != CACHE_ALLOC_NO_LOG_REQUIRED)) { - if(PREDICT_FALSE( dslite_entry_ptr->nf_logging_policy == - SESSION_LOG_ENABLE)) { - if(PREDICT_TRUE(db->dst_ipv4 || db->dst_port)) { - cnat_nfv9_ds_lite_log_session_create(db, - dslite_entry_ptr,NULL); - } - } else { - cnat_nfv9_ds_lite_mapping_create(db,dslite_entry_ptr -#ifndef NO_BULK_LOGGING - ,nfv9_log_req -#endif - ); - } - if(PREDICT_TRUE((dslite_entry_ptr->syslog_logging_policy != SESSION_LOG_ENABLE) || - (db->dst_ipv4 || db->dst_port))) { - cnat_syslog_ds_lite_mapping_create(db,dslite_entry_ptr,NULL -#ifndef NO_BULK_LOGGING - ,nfv9_log_req -#endif - ); - } - } - -#if 0 - if (PREDICT_FALSE(port_pair_type == PORT_PAIR)) { - cnat_main_db_entry_t *db2 = 0; - dslite_db_key_bucket_t new_ki = *ki; - u64 a, b, c; - - new_ki.k.k.port += 1; - ko.k.k.port += 1; - - CNAT_V4_GET_HASH(new_ki.k.key64, new_ki.bucket, - CNAT_MAIN_HASH_MASK); - - db2 = cnat_create_main_db_entry_and_hash(&new_ki, &ko, udb); - - translation_create_count ++; - db2->dslite_nat44_inst_id = dslite_id; - db2->entry_expires = cnat_current_time; - db2->flags |= CNAT_DB_FLAG_ALG_ENTRY; - udb->ntranslations += 1; -#ifndef NO_BULK_LOGGING - if(PREDICT_FALSE(nfv9_log_req == BULK_ALLOC_NOT_ATTEMPTED)) - cnat_nfv9_log_mapping_create(db2, my_vrfmap, nfv9_log_req); -#else - cnat_nfv9_log_mapping_create(db2, my_vrfmap); -#endif - } -#endif - return db; -} -#endif /* TOBE_PORTED */ - -#if 0 -/* TOBE_PORTED */ -uword -cnat_db_v2_node_fn (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return 0; -} -VLIB_REGISTER_NODE (cnat_db_v2_node) = { - .function = cnat_db_v2_node_fn, - .name = "vcgn-db-v2", - .vector_size = sizeof (u32), - .type = VLIB_NODE_TYPE_INTERNAL, - - .n_errors = ARRAY_LEN(cnat_db_v2_error_strings), - .error_strings = cnat_db_v2_error_strings, - - .n_next_nodes = CNAT_DB_V2_DROP, - - /* edit / add dispositions here */ - .next_nodes = { - [CNAT_DB_V2_DROP] = "error-drop", - }, -}; -#endif -void cnat_db_v2_init (void) -{ - - u32 i, n; - cnat_timeout_db_entry_t * tdb __attribute__((unused)); - - cgse_nat_db_entry_t *comb_db __attribute__((unused)); - cgse_nat_user_db_entry_t *comb_user __attribute__((unused)); - cgse_nat_session_db_entry_t *comb_session __attribute__((unused)); - - n = CNAT_DB_SIZE*1.15; /* add 15% LB margin */ - - /* - * We also make it multiple of NUM_BITS_IN_UWORD for better - * DB scanning algorithm - */ - if (n % NUM_BITS_IN_UWORD) - n += (NUM_BITS_IN_UWORD - (n % NUM_BITS_IN_UWORD)); - - pool_alloc(cgse_nat_db,n); - for(i=0; i< n; i++) { - pool_get(cgse_nat_db, comb_db); - } - - for(i=0; i< n; i++) { - pool_put(cgse_nat_db, cgse_nat_db + i); - } - - cnat_main_db = &cgse_nat_db->nat44_main_db; - - /* For Sessions */ - if(PLATFORM_DBL_SUPPORT) { - /* create session table for NAT44 and NAT64 itself */ - printf("DBL Support exist %d\n", PLATFORM_DBL_SUPPORT); - n = CNAT_SESSION_DB_SIZE * 1.15; /* add 15% LB margin */ - } else { - /* Create session table for NAT64 only */ - printf("DBL Support Not exist\n"); - n = NAT64_MAIN_DB_SIZE * 1.15; /* add 15% LB margin */ - } - - /* - * We also make it multiple of NUM_BITS_IN_UWORD for better - * DB scanning algorithm - */ - if (n % NUM_BITS_IN_UWORD) - n += (NUM_BITS_IN_UWORD - (n % NUM_BITS_IN_UWORD)); - - pool_alloc(cgse_session_db,n); - for(i=0; i< n; i++) { - pool_get(cgse_session_db, comb_session); - } - - for(i=0; i< n; i++) { - pool_put(cgse_session_db, cgse_session_db + i); - } - - cnat_session_db = &cgse_session_db->nat44_session_db; - - vec_validate(cnat_out2in_hash, CNAT_MAIN_HASH_MASK); - memset(cnat_out2in_hash, 0xff, CNAT_MAIN_HASH_SIZE*sizeof(index_slist_t)); - - vec_validate(cnat_in2out_hash, CNAT_MAIN_HASH_MASK); - memset(cnat_in2out_hash, 0xff, CNAT_MAIN_HASH_SIZE*sizeof(index_slist_t)); - - vec_validate(cnat_session_hash, CNAT_SESSION_HASH_MASK); - memset(cnat_session_hash, 0xff, CNAT_SESSION_HASH_SIZE*sizeof(index_slist_t)); - - n = CNAT_USER_DB_SIZE * 1.15; /* use hash size as db size for LB margin */ - if (n % NUM_BITS_IN_UWORD) - n += (NUM_BITS_IN_UWORD - (n % NUM_BITS_IN_UWORD)); - - pool_alloc(cgse_user_db,n); - for(i=0; i< n; i++) { - pool_get(cgse_user_db, comb_user); - } - - for(i=0; i< n; i++) { - pool_put(cgse_user_db, cgse_user_db + i); - } - - cnat_user_db = &cgse_user_db->nat44_user_db; - - vec_validate(cnat_user_hash, CNAT_USER_HASH_MASK); - memset(cnat_user_hash, 0xff, CNAT_USER_HASH_SIZE*sizeof(index_slist_t)); - - n = CNAT_TIMEOUT_HASH_SIZE; /* use hash size as db size for LB margin */ - for(i=0; i< n; i++) { - pool_get(cnat_timeout_db, tdb); - } - - for(i=0; i< n; i++) { - pool_put(cnat_timeout_db, cnat_timeout_db + i); - } - - vec_validate(cnat_timeout_hash, CNAT_TIMEOUT_HASH_MASK); - memset(cnat_timeout_hash, 0xff, CNAT_TIMEOUT_HASH_SIZE*sizeof(index_slist_t)); - -#ifdef TOBE_PORTED - for (i=0;i -#include - -#include "cnat_cli.h" - -u32 global_debug_flag = CNAT_DEBUG_NONE; -u16 debug_i_vrf = CNAT_DEBUG_NONE; -u32 debug_i_flag = CNAT_DEBUG_NONE; -u32 debug_i_addr_start = CNAT_DEBUG_NONE; -u32 debug_i_addr_end = CNAT_DEBUG_NONE; - -u16 debug_o_vrf = CNAT_DEBUG_NONE; -u32 debug_o_flag = CNAT_DEBUG_NONE; -u32 debug_o_addr_start = CNAT_DEBUG_NONE; -u32 debug_o_addr_end = CNAT_DEBUG_NONE; - -u32 udp_inside_checksum_disable = 0; -u32 udp_outside_checksum_disable = 0; -u32 udp_inside_packet_dump_enable = 0; -u32 udp_outside_packet_dump_enable = 0; - -u32 tcp_logging_enable_flag = 0; - -u32 icmp_debug_flag = 0; -u32 frag_debug_flag = 0; - -u32 nfv9_logging_debug_flag = 0; -u32 syslog_debug_flag = 0; - -u32 summary_stats_debug_flag = 0; - -/* - * By defaut we set the config debug level to 1 - */ -u32 config_debug_level = 1; - -#ifdef TOBE_PORTED -extern void show_bulk_port_stats(); -extern void clear_bulk_port_stats(); -extern void show_bulk_port_allocation(u16 in_vrfid, u32 inside_ip); -extern void set_bulk_size_to_all_vrfs(int bulk_size); - -u32 *cnat_debug_addr_list; - -extern int global_pd_dbg_lvl; -extern int global_pi_dbg_lvl; -extern int global_l2_dbg_lvl; -extern u32 cnat_pptp_debug_flag; -extern u32 cnat_pcp_debug_flag; - -void spp_api_cnat_get_cgn_db_summary -(spp_api_cnat_generic_command_request_t *); - -void spp_api_cnat_v4_debug_dummy_t_handler -(spp_api_cnat_v4_debug_dummy_t *mp) -{ - u32 arr[] = { DEBUG_DUMMY }; - spp_printf(CNAT_DUMMY_HANDLER_HIT, 1, arr); - if(global_pd_dbg_lvl) { - PLATFORM_DEBUG_PRINT("\n invalid debug command received: message id is 0\n"); - } - mp->rc = CNAT_ERR_INVALID_MSG_ID; - -} - -void spp_api_cnat_v4_debug_dummy_max_t_handler -(spp_api_cnat_v4_debug_dummy_max_t *mp) -{ - u32 arr[] = { DEBUG_DUMMY_MAX }; - spp_printf(CNAT_DUMMY_HANDLER_HIT, 1, arr); - if(global_pd_dbg_lvl) { - PLATFORM_DEBUG_PRINT("\n invalid debug command received: message id is out of range\n"); - } - mp->rc = CNAT_ERR_INVALID_MSG_ID; - -} - - -void spp_api_cnat_v4_debug_global_t_handler -(spp_api_cnat_v4_debug_global_t *mp) -{ - if ((mp->debug_flag == CNAT_DEBUG_GLOBAL_ERR) || - (mp->debug_flag == CNAT_DEBUG_GLOBAL_ALL) || - (mp->debug_flag == CNAT_DEBUG_NONE)) { - mp->rc = CNAT_SUCCESS; - global_debug_flag = mp->debug_flag; - return; - } - - mp->rc = CNAT_ERR_PARSER; - if(global_pd_dbg_lvl) { - PLATFORM_DEBUG_PRINT("invalid global debug flag %x\n", - mp->debug_flag); - } - return; -} - -void spp_node_print_cnat_counters() -{ - if (cnat_global_counters.nfv9_downstream_constipation_count) { - PLATFORM_DEBUG_PRINT("\nNF downstream constipation count: %llu\n", - cnat_global_counters.nfv9_downstream_constipation_count); - } - - if (xlat_global_counters.v4_to_v6_frag_invalid_uidb_drop_count || - xlat_global_counters.v6_to_v4_frag_invalid_uidb_drop_count || - xlat_global_counters.v4_to_v6_icmp_invalid_uidb_drop_count || - xlat_global_counters.v6_to_v4_icmp_invalid_uidb_drop_count || - xlat_global_counters.v4_to_v6_tcp_invalid_uidb_drop_count || - xlat_global_counters.v6_to_v4_tcp_invalid_uidb_drop_count || - xlat_global_counters.v4_to_v6_udp_invalid_uidb_drop_count || - xlat_global_counters.v6_to_v4_udp_invalid_uidb_drop_count || - xlat_global_counters.v4_to_v6_udp_crc_zero_invalid_uidb_drop_count) { - - PLATFORM_DEBUG_PRINT("\nMy_instance %d: v4_to_v6 frag invalid uidb drop count %lld", - my_instance_number, - xlat_global_counters.v4_to_v6_frag_invalid_uidb_drop_count); - - PLATFORM_DEBUG_PRINT("\nMy_instance %d: v6_to_v4 frag invalid uidb drop count %lld", - my_instance_number, - xlat_global_counters.v6_to_v4_frag_invalid_uidb_drop_count); - - PLATFORM_DEBUG_PRINT("\nMy_instance %d: v4_to_v6 icmp invalid uidb drop count %lld", - my_instance_number, - xlat_global_counters.v4_to_v6_icmp_invalid_uidb_drop_count); - - PLATFORM_DEBUG_PRINT("\nMy_instance %d: v6_to_v4 icmp invalid uidb drop count %lld", - my_instance_number, - xlat_global_counters.v6_to_v4_icmp_invalid_uidb_drop_count); - - PLATFORM_DEBUG_PRINT("\nMy_instance %d: v4_to_v6 tcp invalid uidb drop count %lld", - my_instance_number, - xlat_global_counters.v4_to_v6_tcp_invalid_uidb_drop_count); - - PLATFORM_DEBUG_PRINT("\nMy_instance %d: v6_to_v4 tcp invalid uidb drop count %lld", - my_instance_number, - xlat_global_counters.v6_to_v4_tcp_invalid_uidb_drop_count); - - PLATFORM_DEBUG_PRINT("\nMy_instance %d: v4_to_v6 udp invalid uidb drop count %lld", - my_instance_number, - xlat_global_counters.v4_to_v6_udp_invalid_uidb_drop_count); - - PLATFORM_DEBUG_PRINT("\nMy_instance %d: v6_to_v4 udp invalid uidb drop count %lld", - my_instance_number, - xlat_global_counters.v6_to_v4_udp_invalid_uidb_drop_count); - - PLATFORM_DEBUG_PRINT("\nMy_instance %d: v4_to_v6 udp crc0 invld uidb drop count %lld", - my_instance_number, - xlat_global_counters.v4_to_v6_udp_crc_zero_invalid_uidb_drop_count); - - PLATFORM_DEBUG_PRINT("\n"); - } - - -} - -void spp_log_p2mp_req(spp_api_cnat_p2mp_debug_request_t *mp) -{ - u8 i = 0; - u32 num_rec = spp_net_to_host_byte_order_32(&mp->param[i++]); - u32 err_c_num_args; - - while (num_rec--) { - u8 j = 0; - u16 err_c; - u16 num_args; - u32 argv[32]; - - err_c_num_args = spp_net_to_host_byte_order_32(&mp->param[i++]); - err_c = (err_c_num_args >> 16) & 0xFFFF; - num_args = err_c_num_args & 0xFFFF; - - num_args = (num_args <= 32) ? num_args : 32; - while (j < num_args) { - argv[j++] = spp_net_to_host_byte_order_32(&mp->param[i++]); - } - - i += ((num_args - 32) > 0) ? (num_args - 32) : 0; - spp_printf(err_c, num_args, argv); - } -} - -void nat64_debug_addr_pool_add_del() -{ - cnat_portmap_v2_t *my_pm = NULL; - cnat_portmap_v2_t *pm = NULL; - u32 len, i, pm_len; - - PLATFORM_DEBUG_PRINT("\n sizeof port_map =%d\n", sizeof( cnat_portmap_v2_t)); - len = 10; - PLATFORM_DEBUG_PRINT("\n adding 10 entries in vector 1-10\n "); - vec_add2(pm, my_pm, len); - pm = my_pm; - - PLATFORM_DEBUG_PRINT(" pm =%p , my_pm = %p\n", pm, my_pm); - for(i=0;iipv4_address = i+1; - my_pm++; - } - PLATFORM_DEBUG_PRINT(" pm =%p , my_pm = %p\n", pm, my_pm); - - pm_len = vec_len(pm); - PLATFORM_DEBUG_PRINT("\n printing vector contents : vec_len = %d \n", pm_len); - my_pm = pm; - for(i=0;iipv4_address); - my_pm++; - } - PLATFORM_DEBUG_PRINT(" pm =%p , my_pm = %p\n", pm, my_pm); - - PLATFORM_DEBUG_PRINT("\n adding 5 entries in vector 11-15\n "); - len = 5; - vec_add2(pm, my_pm, len); - - PLATFORM_DEBUG_PRINT(" pm =%p , my_pm = %p\n", pm, my_pm); - for(i=0;iipv4_address = 11+i; - my_pm++; - } - - PLATFORM_DEBUG_PRINT(" pm =%p , my_pm = %p\n", pm, my_pm); - pm_len = vec_len(pm); - PLATFORM_DEBUG_PRINT("\n printing vector contents : vec_len = %d \n", pm_len); - my_pm = pm; - for(i=0;iipv4_address); - my_pm++; - } - PLATFORM_DEBUG_PRINT(" pm =%p , my_pm = %p\n", pm, my_pm); - - PLATFORM_DEBUG_PRINT("\n adding 6 entries in vector 16-21\n "); - len = 6; - vec_add2(pm, my_pm, len); - PLATFORM_DEBUG_PRINT(" pm =%p , my_pm = %p\n", pm, my_pm); - for(i=0;iipv4_address = 16+i; - my_pm++; - } - - PLATFORM_DEBUG_PRINT(" pm =%p , my_pm = %p\n", pm, my_pm); - pm_len = vec_len(pm); - PLATFORM_DEBUG_PRINT("\n printing vector contents : vec_len = %d \n", pm_len); - my_pm = pm; - for(i=0;iipv4_address); - my_pm++; - } - - PLATFORM_DEBUG_PRINT(" pm =%p , my_pm = %p\n", pm, my_pm); - PLATFORM_DEBUG_PRINT("\nDeleting 7 entries starting from entry value=8\n"); - pm_len = vec_len(pm); - my_pm = pm; - PLATFORM_DEBUG_PRINT(" pm_len =%d\n", pm_len); - for(i=0;iipv4_address == 8){ - PLATFORM_DEBUG_PRINT("\n match found brraeaking..\n"); - break; - } - my_pm++; - } - - PLATFORM_DEBUG_PRINT(" pm =%p , my_pm = %p i= %d\n", pm, my_pm, i); -// vec_delete(pm, 7, my_pm); - vec_delete(pm, 7, i); - PLATFORM_DEBUG_PRINT(" pm =%p , my_pm = %p\n", pm, my_pm); - - PLATFORM_DEBUG_PRINT(" printing entries aftr deletion from 8-14\n"); - pm_len = vec_len(pm); - PLATFORM_DEBUG_PRINT("\n printing vector contents : vec_len = %d \n", pm_len); - my_pm = pm; - for(i=0;iipv4_address); - my_pm++; - } - - - PLATFORM_DEBUG_PRINT(" pm =%p , my_pm = %p\n", pm, my_pm); - - PLATFORM_DEBUG_PRINT("\nadding deleted items again 8-14\n"); - len =7; - vec_add2(pm, my_pm, len); - - PLATFORM_DEBUG_PRINT(" pm =%p , my_pm = %p\n", pm, my_pm); - for(i=0;iipv4_address = 8+i; - my_pm++; - } - - PLATFORM_DEBUG_PRINT(" pm =%p , my_pm = %p\n", pm, my_pm); - pm_len = vec_len(pm); - PLATFORM_DEBUG_PRINT("\n printing vector contents : vec_len = %d \n", pm_len); - my_pm = pm; - for(i=0;iipv4_address); - my_pm++; - } - PLATFORM_DEBUG_PRINT(" pm =%p , my_pm = %p\n", pm, my_pm); - PLATFORM_DEBUG_PRINT("\n"); -} - - -void uidb_mapping_dump_timeout() { - - u32 i; - - PLATFORM_DEBUG_PRINT("\nCGSE uidb mapping table \n"); - for(i = 0;i < 30;i++) { - PLATFORM_DEBUG_PRINT("%d ",*(cgse_uidb_index_cgse_id_mapping_ptr + i)); - } - -} - -void nat64_debug_dump_info(u32 debug_value) -{ - - switch(debug_value) { - - case 1 : - bib_add_v6_entry1(); - break; - - case 2 : - bib_add_v6_entry2(); - break; - - case 3 : - bib_add_v6_entry1_new(); - break; - - case 4 : - bib_add_v6_entry1_new_static(); - break; - - case 5 : - bib_add_v6_entry3(); - break; - - case 6 : - bib_add_v6_entry_new2(); - break; - - case 7 : - nat64_fill_table_entry(); - break; - - case 10 : - nat64_db_dump_main(); - break; - - case 11 : - nat64_db_dump_user(); - break; - - case 12 : - nat64_db_dump_session(); - break; - - case 13 : - nat64_dump_table(); - break; - - case 14 : - bib_del_v6_entry1_static(); - break; - - case 15 : - nat64_debug_addr_pool_add_del(); - break; - - case 16 : - nat64_db_dump_timeout(0); - break; - - case 17 : - uidb_mapping_dump_timeout(); - break; - - default : break; - } -} - - -void cnat_debug_flags_set (spp_api_cnat_p2mp_debug_request_t *mp) -{ - u32 debug_variable = spp_net_to_host_byte_order_32(&mp->param[0]); - u32 debug_value = spp_net_to_host_byte_order_32(&mp->param[1]); - - cnat_key_t t_key; - - switch (debug_variable) { - - case CNAT_DEBUG_FLAG_UDP_INSIDE_CHECKSUM_DISABLE: - udp_inside_checksum_disable = debug_value; - PLATFORM_DEBUG_PRINT("\nudp_inside_checksum_disable set to %d\n", debug_value); - break; - - case CNAT_DEBUG_FLAG_UDP_OUTSIDE_CHECKSUM_DISABLE: - udp_outside_checksum_disable = debug_value; - PLATFORM_DEBUG_PRINT("\nudp_outside_checksum_disable set to %d\n", debug_value); - break; - - case CNAT_DEBUG_FLAG_UDP_OUTSIDE_PKT_DUMP_ENABLE: - udp_outside_packet_dump_enable = debug_value; - PLATFORM_DEBUG_PRINT("\nudp_outside_packet_dump_enable set to %d\n", debug_value); - break; - - case CNAT_DEBUG_FLAG_UDP_INSIDE_PKT_DUMP_ENABLE: - udp_inside_packet_dump_enable = debug_value; - PLATFORM_DEBUG_PRINT("\nudp_inside_packet_dump_enable set to %d\n", debug_value); - break; - - case CNAT_DEBUG_FLAG_ICMP_PKT_DUMP_ENABLE: - icmp_debug_flag = debug_value; - PLATFORM_DEBUG_PRINT("\nicmp_debug_flag set to %d\n", debug_value); - break; - - case CNAT_DEBUG_FLAG_FRAG_PKT_DUMP_ENABLE: - frag_debug_flag = debug_value; - PLATFORM_DEBUG_PRINT("\nfrag_debug_flag set to %d\n", debug_value); - break; - - case CNAT_DEBUG_FLAG_XLAT_CONFIG_DEBUG_ENABLE: - xlat_config_debug_level = debug_value; - PLATFORM_DEBUG_PRINT("\nxlat_config_debug_level set to %d\n", debug_value); - break; - - case CNAT_DEBUG_FLAG_NAT64_CONFIG_DEBUG_ENABLE: - nat64_config_debug_level = debug_value; - PLATFORM_DEBUG_PRINT("\nnat64_config_debug_level set to %d\n", debug_value); - nat64_debug_dump_info(debug_value); - break; - - case CNAT_DEBUG_FLAG_NAT64_DATA_PATH_DEBUG_ENABLE: - nat64_data_path_debug_level = debug_value; - PLATFORM_DEBUG_PRINT("\nnat64_data_path_debug_level set to %d\n", debug_value); - break; - - case CNAT_DEBUG_FLAG_DSLITE_CONFIG_DEBUG_ENABLE: - ds_lite_config_debug_level = debug_value; - PLATFORM_DEBUG_PRINT("\nds_lite_config_debug_level set to %d\n", debug_value); - break; - - case CNAT_DEBUG_FLAG_XLAT_DATA_PATH_DEBUG_ENABLE: - xlat_data_path_debug_level = debug_value; - PLATFORM_DEBUG_PRINT("\nxlat_data_path_debug_level set to %d\n", debug_value); - break; - - case CNAT_DEBUG_FLAG_CONFIG_DEBUG_ENABLE: - config_debug_level = debug_value; - - PLATFORM_DEBUG_PRINT("\nconfig_debug_level set to %d\n", debug_value); - break; - - case CNAT_DEBUG_FLAG_CONFIG_PPTP_ENABLE: - cnat_pptp_debug_flag = debug_value; - - if(debug_value == 0) { - pptp_dump_counters(); - } - - PLATFORM_DEBUG_PRINT("\ncnat_pptp_debug_level set to %d\n", debug_value); - break; - - case CNAT_DEBUG_FLAG_CONFIG_PCP_ENABLE: - cnat_pcp_debug_flag = debug_value; - - if(debug_value == 0) { - pcp_dump_counters(); - } - PLATFORM_DEBUG_PRINT("\ncnat_pcp_debug_level set to %d\n", debug_value); - break; - - case CNAT_DEBUG_FLAG_GLOBAL_DEBUG_ALL_ENABLE: - global_debug_flag = debug_value; - PLATFORM_DEBUG_PRINT("\nglobal_debug_flag set to %d\n", debug_value); - break; - - case CNAT_DEBUG_FLAG_SUMMARY_STATS_DEBUG_ENABLE: - summary_stats_debug_flag = debug_value; - PLATFORM_DEBUG_PRINT("\nsummary_stats_debug_flag set to %d\n", debug_value); - break; - - case CNAT_DEBUG_FLAG_SHOW_DEBUG_ENABLE: - show_debug_level = debug_value; - PLATFORM_DEBUG_PRINT("\nshow_debug_level set to %d\n", debug_value); - break; - - case CNAT_DEBUG_FLAG_TCP_LOGGING_ENABLE: - tcp_debug_logging_enable_disable(debug_value); - break; - case CNAT_DEBUG_FLAG_V6RD_DATA_PATH_DEBUG_ENABLE: - v6rd_data_path_debug_level = debug_value; - PLATFORM_DEBUG_PRINT("\nv6rd_data_path_debug_level set to %d\n", debug_value); - break; - case CNAT_DEBUG_FLAG_V6RD_CONFIG_DEBUG_ENABLE: - v6rd_config_debug_level = debug_value; - PLATFORM_DEBUG_PRINT("\nv6rd_config_debug_level set to %d\n", debug_value); - break; - case CNAT_DEBUG_FLAG_V6RD_DEFRAG_DEBUG_ENABLE: - /* set debug atleast to 1, so that critical errors are always - * enabled - */ - v6rd_defrag_debug_level = debug_value ? debug_value : 1; - PLATFORM_DEBUG_PRINT("\nv6rd_config_debug_level set to %d\n", debug_value); - break; - - - case CNAT_DEBUG_SET_STATIC_PORT_RANGE: - PLATFORM_DEBUG_PRINT("\nChange Static Port Range from %d --> %d\n", - cnat_static_port_range, debug_value); - cnat_static_port_range = debug_value; - break; - - case CNAT_DEBUG_FLAG_DSLITE_DP_ENABLE: - PLATFORM_DEBUG_PRINT("\n Changing dslite debug flag from %d --> %d\n", - dslite_debug_level, debug_value); - dslite_debug_level = debug_value; - break; - - case CNAT_DEBUG_FLAG_NFV9_LOGGING_DUMP_ENABLE: - nfv9_logging_debug_flag = debug_value; - PLATFORM_DEBUG_PRINT("\nnfv9_logging_debug_flag set to %d\n", debug_value); - break; - - case CNAT_DEBUG_FLAG_SYSLOG_LOGGING_DUMP_ENABLE: - syslog_debug_flag = debug_value; - PLATFORM_DEBUG_PRINT("\nsyslog_debug_flag set to %d\n", debug_value); - break; - - case CNAT_DEBUG_FLAG_MAPE_CONFIG_DEBUG_ENABLE: - mape_config_debug_level = debug_value; - PLATFORM_DEBUG_PRINT("\nmape_config_debug_level set to %d\n", debug_value); - break; - - case CNAT_DEBUG_FLAG_MAPE_DATA_PATH_DEBUG_ENABLE: - mape_data_path_debug_level = debug_value; - PLATFORM_DEBUG_PRINT("\nmape_data_path_debug_level set to %d\n", debug_value); - break; - - case CNAT_DEBUG_FLAGS_DUMP: - default: - { - PLATFORM_DEBUG_PRINT("\nCurrent values of Debug Variables\n"); - PLATFORM_DEBUG_PRINT("\nTo modify an item chose its index and provide the value\n"); - PLATFORM_DEBUG_PRINT("\n%d: udp_inside_checksum_disable %d\n", - CNAT_DEBUG_FLAG_UDP_INSIDE_CHECKSUM_DISABLE, - udp_inside_checksum_disable); - PLATFORM_DEBUG_PRINT("%d: udp_outside_checksum_disable %d\n", - CNAT_DEBUG_FLAG_UDP_OUTSIDE_CHECKSUM_DISABLE, - udp_outside_checksum_disable); - PLATFORM_DEBUG_PRINT("%d: udp_inside_packet_dump_enable %d\n", - CNAT_DEBUG_FLAG_UDP_OUTSIDE_PKT_DUMP_ENABLE, - udp_inside_packet_dump_enable); - PLATFORM_DEBUG_PRINT("%d: udp_outside_packet_dump_enable %d\n", - CNAT_DEBUG_FLAG_UDP_INSIDE_PKT_DUMP_ENABLE, - udp_outside_packet_dump_enable); - PLATFORM_DEBUG_PRINT("%d: icmp_debug_flag %d\n", - CNAT_DEBUG_FLAG_ICMP_PKT_DUMP_ENABLE, - icmp_debug_flag); - PLATFORM_DEBUG_PRINT("%d: frag_debug_flag %d\n", - CNAT_DEBUG_FLAG_FRAG_PKT_DUMP_ENABLE, - frag_debug_flag); - PLATFORM_DEBUG_PRINT("%d: config_debug_level %d\n", - CNAT_DEBUG_FLAG_CONFIG_DEBUG_ENABLE, - config_debug_level); - PLATFORM_DEBUG_PRINT("%d: global_debug_flag %d\n", - CNAT_DEBUG_FLAG_GLOBAL_DEBUG_ALL_ENABLE, - global_debug_flag); - PLATFORM_DEBUG_PRINT("%d: summary_stats_debug_flag %d\n", - CNAT_DEBUG_FLAG_SUMMARY_STATS_DEBUG_ENABLE, - summary_stats_debug_flag); - PLATFORM_DEBUG_PRINT("%d: show_debug_level %d\n", - CNAT_DEBUG_FLAG_SHOW_DEBUG_ENABLE, - show_debug_level); - PLATFORM_DEBUG_PRINT("%d: xlat_config_debug_level %d\n", - CNAT_DEBUG_FLAG_XLAT_CONFIG_DEBUG_ENABLE, - xlat_config_debug_level); - PLATFORM_DEBUG_PRINT("%d: xlat_data_path_debug_level %d\n", - CNAT_DEBUG_FLAG_XLAT_DATA_PATH_DEBUG_ENABLE, - xlat_data_path_debug_level); - PLATFORM_DEBUG_PRINT("%d: tcp_logging_enable_flag %d\n", - CNAT_DEBUG_FLAG_TCP_LOGGING_ENABLE, - tcp_logging_enable_flag); - PLATFORM_DEBUG_PRINT(" tcp_logging_enable_options DISABLE %d, ENABLE %d, PKT_DUMP %d, SUMMARY_DUMP %d\n", - TCP_LOGGING_DISABLE, TCP_LOGGING_ENABLE, - TCP_LOGGING_PACKET_DUMP, TCP_LOGGING_SUMMARY_DUMP); - PLATFORM_DEBUG_PRINT("%d: nfv9_logging_debug_flag %d\n", - CNAT_DEBUG_FLAG_NFV9_LOGGING_DUMP_ENABLE, - nfv9_logging_debug_flag); - PLATFORM_DEBUG_PRINT("%d: syslog_debug_flag %d\n", - CNAT_DEBUG_FLAG_SYSLOG_LOGGING_DUMP_ENABLE, - syslog_debug_flag); - PLATFORM_DEBUG_PRINT("%d: cnat_static_port_range %d\n", - CNAT_DEBUG_SET_STATIC_PORT_RANGE, - cnat_static_port_range); - PLATFORM_DEBUG_PRINT("%d: v6rd_data_path_debug_level %d\n", - CNAT_DEBUG_FLAG_V6RD_DATA_PATH_DEBUG_ENABLE, - v6rd_data_path_debug_level); - PLATFORM_DEBUG_PRINT("%d: v6rd_config_debug_level %d\n", - CNAT_DEBUG_FLAG_V6RD_CONFIG_DEBUG_ENABLE, - v6rd_config_debug_level); - PLATFORM_DEBUG_PRINT("%d: v6rd_defrag_debug_level %d\n", - CNAT_DEBUG_FLAG_V6RD_DEFRAG_DEBUG_ENABLE, - v6rd_defrag_debug_level); - PLATFORM_DEBUG_PRINT("%d: nat64_stful_debug %d\n", - CNAT_DEBUG_FLAG_NAT64_CONFIG_DEBUG_ENABLE, - nat64_config_debug_level); - PLATFORM_DEBUG_PRINT("%d: nat64_data_path_debug_level %d\n", - CNAT_DEBUG_FLAG_NAT64_DATA_PATH_DEBUG_ENABLE, - nat64_data_path_debug_level); - PLATFORM_DEBUG_PRINT("%d: dslite_debug_level %d\n", - CNAT_DEBUG_FLAG_DSLITE_DP_ENABLE, - dslite_debug_level); - PLATFORM_DEBUG_PRINT("%d: ds_lite_config_debug_level %d\n", - CNAT_DEBUG_FLAG_DSLITE_CONFIG_DEBUG_ENABLE, - ds_lite_config_debug_level); - PLATFORM_DEBUG_PRINT("%d: mape_config_debug_level %d\n", - CNAT_DEBUG_FLAG_MAPE_CONFIG_DEBUG_ENABLE, - mape_config_debug_level); - PLATFORM_DEBUG_PRINT("%d: mape_data_path_debug_level %d\n", - CNAT_DEBUG_FLAG_MAPE_DATA_PATH_DEBUG_ENABLE, - mape_data_path_debug_level); - } - break; - } -} - -extern void dump_cnat_frag_stats(void); - -void spp_api_cnat_p2mp_debug_request_t_handler -(spp_api_cnat_p2mp_debug_request_t *mp) -{ - u16 command_type; - -/* - if (mp->core_num != my_instance_number) { - mp->rc = CNAT_NOT_THIS_CORE; - return; - } -*/ - - command_type = spp_net_to_host_byte_order_16(&mp->dump_type); - PLATFORM_DEBUG_PRINT("-->> Core%d: Received debug msg ... cmd type: %d\n", - my_instance_number, command_type); - - switch (command_type) { - - case CNAT_DEBUG_GENERIC_COMMAND_DUMP_POLICY: - PLATFORM_DEBUG_PRINT("Core%d: policy\n", my_instance_number); - cnat_db_dump_policy(); - break; - - case CNAT_DEBUG_GENERIC_COMMAND_DUMP_MAIN_DB: - PLATFORM_DEBUG_PRINT("Core%d: Main db\n", my_instance_number); - cnat_db_dump_main(); - break; - - case CNAT_DEBUG_GENERIC_COMMAND_DUMP_MAIN_DB_SUMMARY: - PLATFORM_DEBUG_PRINT("Core%d: Main db Summary\n", my_instance_number); - cnat_db_dump_main_summary(); - break; - - case CNAT_DEBUG_GENERIC_COMMAND_DUMP_USER_DB: - PLATFORM_DEBUG_PRINT("Core%d: User db\n", my_instance_number); - cnat_db_dump_user(); - break; - - case CNAT_DEBUG_GENERIC_COMMAND_DUMP_USER_DB_SUMMARY: - PLATFORM_DEBUG_PRINT("Core%d: User db Summary\n", my_instance_number); - cnat_db_dump_user_summary(); - break; - - case CNAT_DEBUG_GENERIC_COMMAND_DUMP_HASHES_DB: - PLATFORM_DEBUG_PRINT("Core%d: Hashes db\n", my_instance_number); - cnat_db_dump_hashes(); - break; - - case CNAT_DEBUG_GENERIC_COMMAND_DUMP_VRF_MAP: - PLATFORM_DEBUG_PRINT("Core%d: Vrf map \n", my_instance_number); - cnat_db_dump_portmaps(); - break; - - case CNAT_DEBUG_GENERIC_COMMAND_DUMP_SUMMARY_DB: - PLATFORM_DEBUG_PRINT("Core%d: dump summary DB \n", my_instance_number); - cnat_db_summary(); - break; - - case CNAT_DEBUG_GENERIC_COMMAND_DUMP_STATS: - PLATFORM_DEBUG_PRINT("Core%d: dump stats \n", my_instance_number); - spp_node_print_stats(1, NULL); - break; - - /* Currently does same as clear node ctr, may change */ - case CNAT_DEBUG_GENERIC_COMMAND_CLEAR_STATS: - PLATFORM_DEBUG_PRINT("Core%d: clear stats \n", my_instance_number); - spp_node_clear_stats(); - break; - - case CNAT_DEBUG_SPP_LOG: - PLATFORM_DEBUG_PRINT("Core%d: SPP LOG \n", my_instance_number); - spp_log_p2mp_req(mp); - break; - - case CNAT_DEBUG_GENERIC_COMMAND_DUMP_NODE_COUNTER: - PLATFORM_DEBUG_PRINT("Core%d: NODE Counter dump \n", my_instance_number); - spp_node_print_counters(); - break; - - case CNAT_DEBUG_GENERIC_COMMAND_CLEAR_NODE_COUNTER: - PLATFORM_DEBUG_PRINT("Core%d: clear node counter \n", my_instance_number); - spp_node_clear_stats(); - break; - - case CNAT_DEBUG_GENERIC_COMMAND_DUMP_CNAT_COUNTER: - PLATFORM_DEBUG_PRINT("Core%d: CNAT Counter dump \n", my_instance_number); - spp_node_print_cnat_counters(); - break; - - case CNAT_DEBUG_GENERIC_COMMAND_DUMP_VA: - PLATFORM_DEBUG_PRINT("Core%d: VA dump \n", my_instance_number); - { - int argc = 1; - u32 arg[2] = {spp_net_to_host_byte_order_32(&mp->param[0]), 0}; - - cnat_va_dump(argc, arg); - } - break; - - case CNAT_DEBUG_GENERIC_COMMAND_SHOW_CONFIG: - PLATFORM_DEBUG_PRINT("Core%d: Show config dump \n", my_instance_number); - { - int argc = 0; - unsigned long arg[3]; - - if (arg[argc++] = spp_net_to_host_byte_order_32(&mp->param[0])) { - if (arg[argc++] = spp_net_to_host_byte_order_32(&mp->param[1])) { - ; - } else { - argc--; - } - } - - cnat_show_cdb_command_v2(argc, arg); -/* - xlat_show_config(); - cnat_alg_show(); -*/ - v6rd_show_config(); - dslite_show_config(); - nat64_dump_table(); - mape_show_config(); - } - break; - - case CNAT_DEBUG_GENERIC_COMMAND_SHOW_NFV9: - PLATFORM_DEBUG_PRINT("Core%d: NFv9 dump \n", my_instance_number); - #if 0 /* Currently not calling this */ - cnat_nfv9_show_cmd(); - #endif - break; - - case CNAT_DEBUG_GENERIC_COMMAND_SHOW_IVRF: - PLATFORM_DEBUG_PRINT("Core%d: IVRF dump \n", my_instance_number); - { - int argc = 0; - unsigned long arg[3]; - - if (arg[argc++] = spp_net_to_host_byte_order_32(&mp->param[0])) { - if (arg[argc++] = spp_net_to_host_byte_order_32(&mp->param[1])) { - if (arg[argc++] = spp_net_to_host_byte_order_32(&mp->param[2])) { - ; - } else { - argc--; - } - } else { - argc--; - } - } - - - PLATFORM_DEBUG_PRINT("VRF: %d \n", spp_net_to_host_byte_order_32(&mp->param[0])); - PLATFORM_DEBUG_PRINT("2nd arg: %d \n", - spp_net_to_host_byte_order_32(&mp->param[1])); - - cnat_show_ivrf_command_v2(argc, arg); - } - break; - - case CNAT_DEBUG_GENERIC_COMMAND_SHOW_OVRF: - PLATFORM_DEBUG_PRINT("Core%d: OVRF dump \n", my_instance_number); - { - int argc = 0; - unsigned long arg[3]; - if (arg[argc++] = spp_net_to_host_byte_order_32(&mp->param[0])) { - if (arg[argc++] = spp_net_to_host_byte_order_32(&mp->param[1])) { - if (arg[argc++] = spp_net_to_host_byte_order_32(&mp->param[2])) { - ; - } else { - argc--; - } - } else { - argc--; - } - } - - PLATFORM_DEBUG_PRINT("VRF: %d \n", spp_net_to_host_byte_order_32(&mp->param[0])); - PLATFORM_DEBUG_PRINT("2nd arg: %d \n", - spp_net_to_host_byte_order_32(&mp->param[1])); - - cnat_show_ovrf_command_v2(argc, arg); - } - break; - - case CNAT_DEBUG_GENERIC_COMMAND_DEBUG_OPTIONS: - PLATFORM_DEBUG_PRINT("Core%d: Debug option dump \n", my_instance_number); - { - global_pd_dbg_lvl = 0; - global_pi_dbg_lvl = 0; - global_l2_dbg_lvl = 0; - - global_pd_dbg_lvl = - spp_net_to_host_byte_order_32(&mp->param[0]); - global_pi_dbg_lvl = - spp_net_to_host_byte_order_32(&mp->param[1]); - global_l2_dbg_lvl = - spp_net_to_host_byte_order_32(&mp->param[2]); - - PLATFORM_DEBUG_PRINT("global_pd_dbg_lvl: %d, global_pi_dbg_lvl: %d, global_l2_dbg_lvl: %d\n", - global_pd_dbg_lvl, global_pi_dbg_lvl, global_l2_dbg_lvl); - } - break; - - case CNAT_DEBUG_GENERIC_COMMAND_DUMP_DEBUG_LEVELS: - PLATFORM_DEBUG_PRINT("Core%d: PD Debug level: %d \n", my_instance_number, global_pd_dbg_lvl); - PLATFORM_DEBUG_PRINT("Core%d: PI Debug level: %d \n", my_instance_number, global_pi_dbg_lvl); - PLATFORM_DEBUG_PRINT("Core%d: L2 Debug level: %d \n", my_instance_number, global_l2_dbg_lvl); - break; - - case CNAT_DEBUG_GENERIC_COMMAND_DEBUG_FLAGS: - PLATFORM_DEBUG_PRINT("Core%d: Debug flags \n", my_instance_number); - cnat_debug_flags_set(mp); - break; - - case CNAT_READ_TEMP_SENSORS: - PLATFORM_INIT_TEMP_SENSORS(); - PLATFORM_READ_CPU_SENSORS(TEMPERATURE_SENSOR_TEST_MODE); - break; - - case CNAT_BLOCK_OCTEON_SENSOR_READ: - - PLATFORM_SET_TEMP_READ_BLOCK(temperature_read_blocked , mp); -#ifdef TARGET_RODDICK - temperature_read_blocked = - spp_net_to_host_byte_order_32(&mp->param[0]); -#endif - break; - - case CNAT_DEBUG_TIMEOUT_DB_SUMMARY: - cnat_db_dump_timeout(); - break; - - /* This option has to be removed later */ - case CNAT_DEBUG_SET_BULK_SIZE: - PLATFORM_DEBUG_PRINT("\nSetting bulk size to %d\n", - spp_net_to_host_byte_order_32(&mp->param[0])); - set_bulk_size_to_all_vrfs( - spp_net_to_host_byte_order_32(&mp->param[0])); - break; - - case CNAT_DEBUG_SHOW_BULK_STAT: - show_bulk_port_stats(); - break; - - case CNAT_DEBUG_CLEAR_BULK_STAT: - clear_bulk_port_stats(); - break; - - case CNAT_DEBUG_SHOW_BULK_ALLOC: - { - u16 in_vrfid = spp_net_to_host_byte_order_32(&mp->param[0]); - u32 inside_ip = spp_net_to_host_byte_order_32(&mp->param[1]); - show_bulk_port_allocation(in_vrfid, inside_ip); - } - break; - - case CNAT_DEBUG_NAT44_IN2OUT_FRAG_STATS: - dump_cnat_frag_stats(); - break; - - default: - mp->rc = CNAT_ERR_INVALID_MSG_ID; - break; - } - - mp->rc = CNAT_SUCCESS; - return; -} - - -void spp_api_cnat_v4_debug_in2out_private_addr_t_handler -(spp_api_cnat_v4_debug_in2out_private_addr_t *mp) -{ - u16 i_vrf; - u32 debug_flag; - u32 start_addr, end_addr; - - - start_addr = - spp_net_to_host_byte_order_32(&mp->start_addr); - end_addr = - spp_net_to_host_byte_order_32(&mp->end_addr); - i_vrf = - spp_net_to_host_byte_order_16(&mp->i_vrf); - debug_flag = - spp_net_to_host_byte_order_32(&mp->debug_flag); - - if ((i_vrf > MAX_UIDX) || (start_addr > end_addr) || - ((debug_flag != CNAT_DEBUG_NONE) && - ((debug_flag & CNAT_DEBUG_ALL) == CNAT_DEBUG_NONE))) { - mp->rc = CNAT_ERR_PARSER; - PLATFORM_DEBUG_PRINT("invalid debug ivrf 0x%x flag 0x%x " - "start addr 0x%x end addr 0x%x\n", - i_vrf, debug_flag, - start_addr, end_addr); - return; - } - - PLATFORM_DEBUG_PRINT("debug ivrf 0x%x flag 0x%x " - "start addr 0x%x end addr 0x%x\n", - i_vrf, debug_flag, - start_addr, end_addr); - - mp->rc = CNAT_SUCCESS; - debug_i_vrf = i_vrf; - debug_i_flag = debug_flag; - debug_i_addr_start = start_addr; - debug_i_addr_end = end_addr; - -} - -void spp_api_cnat_v4_debug_out2in_public_addr_t_handler -(spp_api_cnat_v4_debug_out2in_public_addr_t *mp) -{ - u16 o_vrf; - u32 debug_flag; - u32 start_addr, end_addr; - - start_addr = - spp_net_to_host_byte_order_32(&mp->start_addr); - end_addr = - spp_net_to_host_byte_order_32(&mp->end_addr); - o_vrf = - spp_net_to_host_byte_order_16(&mp->o_vrf); - debug_flag = - spp_net_to_host_byte_order_32(&mp->debug_flag); - - if ((o_vrf > MAX_UIDX) || (start_addr > end_addr) || - ((debug_flag != CNAT_DEBUG_NONE) && - ((debug_flag & CNAT_DEBUG_ALL) == CNAT_DEBUG_NONE))) { - mp->rc = CNAT_ERR_PARSER; - PLATFORM_DEBUG_PRINT("invalid debug ovrf 0x%x flag 0x%x " - "start addr 0x%x end addr 0x%x\n", - o_vrf, debug_flag, - start_addr, end_addr); - return; - } - - mp->rc = CNAT_SUCCESS; - debug_o_vrf = o_vrf; - debug_o_flag = debug_flag; - debug_o_addr_start = start_addr; - debug_o_addr_end = end_addr; - - PLATFORM_DEBUG_PRINT(" o2i debug currently is not supported\n"); -} - -void nat64_reset_session_expiry(nat64_bib_entry_t *db) -{ - NAT64_STFUL_DEBUG_PRINT(3, " invoking nat64_clean_bib_db_entry\n " ); - nat64_clean_bib_db_entry(db); - NAT64_STFUL_DEBUG_PRINT(3, "done with clean_bib_db_entry\n " ); -} - -void spp_api_nat64_clear_db_request_t_handler -(spp_api_nat64_clear_db_request_t *mp) -{ - u16 port, proto, flag; - u32 index; - u32 i; - nat64_bib_entry_t* db; - nat64_v6_key_t ki; - nat64_table_entry_t *my_nat64_table_db_ptr; - u16 nat64_id; - - NAT64_STFUL_FUNC_ENTER; - NAT64_STFUL_DEBUG_DUMP_MSG(mp); - - nat64_id = spp_net_to_host_byte_order_16(&mp->nat64_id); - my_nat64_table_db_ptr = nat64_table_ptr + nat64_id; - - port = spp_net_to_host_byte_order_16(&mp->port_num); - proto = mp->protocol; - - ki.vrf = nat64_id; - ki.vrf |= ((u16)proto << CNAT_PRO_SHIFT); - - for(i =0 ; i< 4 ; i++) - ki.ipv6[i] = spp_net_to_host_byte_order_32(&mp->ip_addr[i]); - - ki.port = port; - - flag = mp->flags; - - mp->rc = CNAT_SUCCESS; - - NAT64_STFUL_DEBUG_PRINT(3, "\n Nat64_id = %d, port =%d, \ - proto =%d, flags=0x%08X",\ - nat64_id, port, proto, flag); - - NAT64_STFUL_DEBUG_PRINT(3, "\n IPv6 Addr = %08X : %08X: %08X: %08X",\ - ki.ipv6[0], ki.ipv6[1], ki.ipv6[2], ki.ipv6[3]); - - if (flag == CNAT_DB_CLEAR_SPECIFIC) { - NAT64_STFUL_DEBUG_PRINT(3, "\n clear specific \n"); - - db = nat64_bib_db_lookup_entry(&ki); - if (db == NULL) { - NAT64_STFUL_DEBUG_PRINT(3, "\n clear specific - not present\n"); - mp->rc = CNAT_NOT_FOUND_ANY; - return; - } - - if( !(db->flags & CNAT_DB_NAT64_FLAG) || - (db->nat64_inst_id != nat64_id)) - return; - - - nat64_reset_session_expiry(db); - return; - } - - pool_header_t *p = pool_header(nat64_bib_db); - - for(index = 0; index < vec_len(nat64_bib_db); index++) { - - /* check is it nat44, if yes skip , do it n nat44 as well */ - - if (PREDICT_FALSE(!clib_bitmap_get(p->free_bitmap, index))) { - db = nat64_bib_db + index; - - if( !(db->flags & CNAT_DB_NAT64_FLAG) || - (db->nat64_inst_id != nat64_id)) - continue; - - if (flag == CNAT_DB_CLEAR_ALL) { - nat64_reset_session_expiry(db); - continue; - } - - if (flag & CNAT_DB_CLEAR_ADDR) { - if ((db->v6_in_key.ipv6[0] != ki.ipv6[0]) || - (db->v6_in_key.ipv6[1] != ki.ipv6[1]) || - (db->v6_in_key.ipv6[2] != ki.ipv6[2]) || - (db->v6_in_key.ipv6[3] != ki.ipv6[3])){ - NAT64_STFUL_DEBUG_PRINT(3, "\n%s:%d\n", __FUNCTION__, \ - __LINE__ ); - continue; - } - } - - if (flag & CNAT_DB_CLEAR_PROTO) { - if (((db->v6_in_key.vrf & CNAT_PRO_MASK) >> CNAT_PRO_SHIFT) - != proto) { - NAT64_STFUL_DEBUG_PRINT(3, "\n%s:%d\n", __FUNCTION__, \ - __LINE__ ); - continue; - } - } - - if (flag & CNAT_DB_CLEAR_PORT) { - if (db->v6_in_key.port != port) { - NAT64_STFUL_DEBUG_PRINT(3, "\n%s:%d\n", __FUNCTION__, \ - __LINE__ ); - continue; - } - } - - NAT64_STFUL_DEBUG_PRINT(3, "\n%s:%d\n", __FUNCTION__, \ - __LINE__ ); - /* - * Delete if the db entry matches and it is not a - */ - nat64_reset_session_expiry(db); - } - } -} - -void inline cnat_clear_session_db(cnat_main_db_entry_t *db) -{ - if(PREDICT_FALSE(db->nsessions > 1)) { - u32 session_index = db->session_head_index; - cnat_session_entry_t *sdb; - do { - sdb = cnat_session_db + session_index; - if(PREDICT_FALSE(!sdb)) { - //TO DO: Debug msg? - break; - } - sdb->entry_expires = 0; - session_index = sdb->main_list.next; - } while(session_index != db->session_head_index - && db->session_head_index != EMPTY); - } - return; -} - -#ifdef CGSE_DS_LITE -extern dslite_table_entry_t dslite_table_array[]; - -void spp_api_ds_lite_clear_db_request_t_handler -(spp_api_ds_lite_clear_db_request_t *mp) -{ - u16 port, proto, flag; - u32 index; - u32 i; - cnat_main_db_entry_t *db; - cnat_user_db_entry_t *udb; - dslite_key_t ki; - dslite_table_entry_t *my_table_db_ptr; - u16 id; - u16 i_vrf; - - - id = spp_net_to_host_byte_order_16(&mp->ds_lite_id); - id = DS_LITE_CONFIG_TO_ARRAY_ID(id); - - my_table_db_ptr = &dslite_table_array[id]; - i_vrf = my_table_db_ptr->i_vrf; - - port = spp_net_to_host_byte_order_16(&mp->port_num); - proto = mp->protocol; - - ki.ipv4_key.k.vrf = i_vrf; - ki.ipv4_key.k.vrf |= ((u16)proto << CNAT_PRO_SHIFT); - - for(i =0 ; i< 4 ; i++) - ki.ipv6[i] = spp_net_to_host_byte_order_32(&mp->ip_addr[i]); - - ki.ipv4_key.k.port = port; - - flag = mp->flags; - - mp->rc = CNAT_SUCCESS; - - DSLITE_PRINTF(3, "\n dslite id = %d, port =%d" - "proto =%d, flags=0x%08X",\ - id, port, proto, flag); - - DSLITE_PRINTF(3, "\n IPv6 Addr = %08X : %08X: %08X: %08X",\ - ki.ipv6[0], ki.ipv6[1], ki.ipv6[2], ki.ipv6[3]); - - if (flag == CNAT_DB_CLEAR_SPECIFIC) { - DSLITE_PRINTF(3, "\n Clear specific NOT supported for DS Lite \n"); - return; - } - - pool_header_t *p = pool_header(cnat_main_db); - - for(index = 0; index < vec_len(cnat_main_db); index++) { - - /* check is it dslite entry, if not skip */ - - if (PREDICT_FALSE(!clib_bitmap_get(p->free_bitmap, index))) { - db = cnat_main_db + index; - - if( !(db->flags & CNAT_DB_DSLITE_FLAG) || - ((db->in2out_key.k.vrf & CNAT_VRF_MASK) != i_vrf) || - (db->flags & CNAT_DB_FLAG_STATIC_PORT)) { - continue; - } - - if (flag == CNAT_DB_CLEAR_ALL) { - - /* - * Make the entry time as very old (0), and wait - * for a timeout to auto-expire the entry. - */ - db->entry_expires = 0; - /* Handle sessions as well.. */ - cnat_clear_session_db(db); - continue; - } - - if (flag & CNAT_DB_CLEAR_ADDR) { - udb = cnat_user_db + db->user_index; - if(PREDICT_FALSE(!udb)) { - continue; - } - if ((udb->ipv6[0] != ki.ipv6[0]) || - (udb->ipv6[1] != ki.ipv6[1]) || - (udb->ipv6[2] != ki.ipv6[2]) || - (udb->ipv6[3] != ki.ipv6[3])) { - continue; - } - } - - if (flag & CNAT_DB_CLEAR_PROTO) { - if (((db->in2out_key.k.vrf & CNAT_PRO_MASK) >> CNAT_PRO_SHIFT) - != proto) { - continue; - } - } - - if (flag & CNAT_DB_CLEAR_PORT) { - if (db->in2out_key.k.port != port) { - continue; - } - } - - /* - * Mark for expiry in the next round of DB scan - */ - db->entry_expires = 0; - /* Handle sessions as well.. */ - cnat_clear_session_db(db); - } - } -} -#endif /* #ifdef CGSE_DS_LITE */ - -void spp_api_cnat_clear_db_request_t_handler -(spp_api_cnat_clear_db_request_t *mp) -{ - u16 i_vrf, port, proto, flag; - u32 ip_addr, index; - u64 a,b,c; - cnat_main_db_entry_t * db; - cnat_db_key_bucket_t ki; - -#if defined(TARGET_LINUX_UDVR) || defined(CNAT_PG) - i_vrf = mp->inside_vrf; - ip_addr = mp->ip_addr; - port = mp->port_num; - proto = mp->protocol; -#else - i_vrf = spp_net_to_host_byte_order_16(&mp->inside_vrf); - ip_addr = spp_net_to_host_byte_order_32(&mp->ip_addr); - port = spp_net_to_host_byte_order_16(&mp->port_num); - proto = spp_net_to_host_byte_order_16(&mp->protocol); -#endif - - - - ki.k.k.vrf = i_vrf; - ki.k.k.vrf |= ((u16)proto << CNAT_PRO_SHIFT); - ki.k.k.ipv4 = ip_addr; - ki.k.k.port = port; - - flag = mp->wildcard; - - mp->rc = CNAT_SUCCESS; - - if (flag == CNAT_DB_CLEAR_SPECIFIC) { - CNAT_V4_GET_HASH(ki.k.key64, - ki.bucket, - CNAT_MAIN_HASH_MASK); - index = cnat_in2out_hash[ki.bucket].next; - if (PREDICT_TRUE(index == EMPTY)) { - mp->rc = CNAT_NOT_FOUND_ANY; - return; - } - - do { - db = cnat_main_db + index; - - /* - * Delete if the db entry matches and it is not a - * STATIC port entry - */ - if ((db->in2out_key.key64 == ki.k.key64) && - !(db->flags & CNAT_DB_FLAG_STATIC_PORT) && - !(db->flags & CNAT_DB_NAT64_FLAG) && - !(db->flags & CNAT_DB_DSLITE_FLAG)) { - - /* - * Make the entry time as very old (0), and wait - * for a timeout to auto-expire the entry. - */ - db->entry_expires = 0; - /* Handle sessions as well.. */ - cnat_clear_session_db(db); - return; - } - index = db->in2out_hash.next; - } while (index != EMPTY); - - mp->rc = CNAT_NOT_FOUND_ANY; - return; - } - - pool_header_t *p = vec_header(cnat_main_db, sizeof(pool_header_t)); - - for(index = 0; index < vec_len(cnat_main_db); index++) { - - if (PREDICT_TRUE(!clib_bitmap_get(p->free_bitmap, index))) { - db = cnat_main_db + index; - - if(PREDICT_FALSE(db->flags & CNAT_DB_NAT64_FLAG)) { - continue; - } - - if(PREDICT_FALSE(db->flags & CNAT_DB_DSLITE_FLAG)) { - continue; - } - - if (flag == CNAT_DB_CLEAR_ALL) { - if (!(db->flags & CNAT_DB_FLAG_STATIC_PORT)) { - db->entry_expires = 0; - /* Handle sessions as well.. */ - cnat_clear_session_db(db); - } - continue; - } - - if (flag & CNAT_DB_CLEAR_VRF) { - if (((db->in2out_key.k.vrf & CNAT_VRF_MASK) != i_vrf)) { - continue; - } - } - - if (flag & CNAT_DB_CLEAR_ADDR) { - if ((db->in2out_key.k.ipv4 != ip_addr)) { - continue; - } - } - - if (flag & CNAT_DB_CLEAR_PROTO) { - if (((db->in2out_key.k.vrf & CNAT_PRO_MASK) >> CNAT_PRO_SHIFT) - != proto) { - continue; - } - } - - if (flag & CNAT_DB_CLEAR_PORT) { - if (db->in2out_key.k.port != port) { - continue; - } - } - - /* - * Delete if the db entry matches and it is not a - * STATIC port entry - */ - if (!(db->flags & CNAT_DB_FLAG_STATIC_PORT)) { - db->entry_expires = 0; - /* Handle sessions as well.. */ - cnat_clear_session_db(db); - } - } - } -} - -void -spp_api_cnat_generic_command_debug (cnat_generic_command_resp *mp_resp) -{ -#ifdef SHOW_DEBUG - u32 i, j; - - i = spp_net_to_host_byte_order_32(&(mp_resp->num_bytes)); - - PLATFORM_DEBUG_PRINT("\nNum_Bytes %d\n", i); - - for (j = 0; j < i; j++) { - PLATFORM_DEBUG_PRINT("0x%02X ", mp_resp->raw_data[j]); - if ((j % 16) == 15) { - PLATFORM_DEBUG_PRINT("\n"); - } - } -#endif -} - -/* - * The following commands implements command to dump the - * user-db information - * port-map information - * for a give user source IP address - * - * The format of the output is: - * Word 0: Address of udb - * Word 1: udb->translation_list_head_index - * Word 2: - * Bytes 0..1: udb->ntranslations - * Bytes 2..2: udb->icmp_msg_coung - * Bytes 3..3: udb->unused - * Word 3: udb->portmap_index - * Word 4: udb->key.k.ipv4 - * Word 5: - * Bytes 0..1: udb->key.k.port = 0 - * Bytes 2..3: udb->key.k.vrf - * Word 6: udb->user_hash - * Word 7: Address of my_pm - * Word 8: my_pm->status - * Word 9: my_pm->inuse - * Word A: my_pm->delete_time - * Word B: my_pm->ipv4_address - */ -void spp_api_cnat_generic_command_user_db_pm -(spp_api_cnat_generic_command_request_t *mp) -{ - u32 i; - cnat_db_key_bucket_t u_ki; - u16 my_vrfmap_index; - u32 *result_array; - cnat_generic_command_resp *mp_resp; - cnat_user_db_entry_t *udb; - cnat_user_db_entry_t *mp_udb; - cnat_vrfmap_t *my_vrfmap; - cnat_portmap_v2_t *pm; - cnat_portmap_v2_t *my_pm; - - /* - * Request structure is used to send the response - */ - mp_resp = (cnat_generic_command_resp *) mp; - - u_ki.k.k.vrf = spp_net_to_host_byte_order_32(&mp->params[1]); - u_ki.k.k.ipv4 = spp_net_to_host_byte_order_32(&mp->params[2]); - u_ki.k.k.port = 0; - - udb = cnat_user_db_lookup_entry(&u_ki); - - if (!udb) { - mp_resp->num_bytes = spp_host_to_net_byte_order_32(0); - goto no_udb_found; - } - - result_array = (u32 *) (&(mp_resp->raw_data[0])); - - i = 0; - result_array[i++] = spp_host_to_net_byte_order_32((u32) udb); - - mp_udb = (cnat_user_db_entry_t *) &(result_array[i]); - - /* - * Align the entry to the next 4 byte boundary - */ - i = i + ((sizeof(cnat_user_db_entry_t)+3)/4); - - /* - * Fill in the UDB information - */ - mp_udb->translation_list_head_index = - spp_host_to_net_byte_order_32(udb->translation_list_head_index); - mp_udb->ntranslations = - spp_host_to_net_byte_order_16(udb->ntranslations); - mp_udb->icmp_msg_count = udb->icmp_msg_count; - mp_udb->flags = udb->flags; - mp_udb->portmap_index = - spp_host_to_net_byte_order_32(udb->portmap_index); - mp_udb->key.k.ipv4 = - spp_host_to_net_byte_order_32(udb->key.k.ipv4); - mp_udb->key.k.port = - spp_host_to_net_byte_order_16(udb->key.k.port); - mp_udb->key.k.vrf = - spp_host_to_net_byte_order_16(udb->key.k.vrf); - mp_udb->user_hash.next = - spp_host_to_net_byte_order_32(udb->user_hash.next); - - my_vrfmap_index = vrf_map_array[u_ki.k.k.vrf]; - my_vrfmap = cnat_map_by_vrf + my_vrfmap_index; - pm = my_vrfmap->portmap_list; - my_pm = pm + udb->portmap_index; - - /* - * Fill in the port_map information - */ - result_array[i++] = spp_host_to_net_byte_order_32((u32) my_pm); - result_array[i++] = spp_host_to_net_byte_order_32(my_pm->inuse); - result_array[i++] = spp_host_to_net_byte_order_32(my_pm->delete_time); - result_array[i++] = spp_host_to_net_byte_order_32(my_pm->ipv4_address); - - mp_resp->num_bytes = spp_host_to_net_byte_order_32(i*4); - -no_udb_found: - spp_api_cnat_generic_command_debug(mp_resp); -} - -/* - * The following commands implements command to dump the - * DB usage stats for - * main-db - * user-db - * in2out hash - * out2in hash - * - * The format of the output is: - * Word 0: Main-DB - Total - * Word 1: Main-DB - Active - * Word 2: Main-DB - Free - * Word 3: User-DB - Total - * Word 4: User-DB - Active - * Word 5: User-DB - Free - * Word 6: Hash In2Out - Size - * Word 7: Hash In2Out - Used - * Word 8: Hash In2Out - Used Percentage - * Word 9: Hash Out2In - Size - * Word A: Hash Out2In - Used - * Word B: Hash Out2In - Used Percentage - */ -void spp_api_cnat_generic_command_db_summary -(spp_api_cnat_generic_command_request_t *mp) -{ - u32 count1, count2, count3; - u32 i = 0; - u32 k = 0; - cnat_generic_command_resp *mp_resp; - u32 *result_array; - - /* - * Request structure is used to send the response - */ - mp_resp = (cnat_generic_command_resp *) mp; - result_array = (u32 *) (&(mp_resp->raw_data[0])); - - /* - * Find entries free and used in main-db - */ - count1 = vec_len(cnat_main_db); - count2 = db_free_entry(cnat_main_db); - count3 = count1 - count2; - - *(result_array + i++) = spp_host_to_net_byte_order_32(count1); - *(result_array + i++) = spp_host_to_net_byte_order_32(count3); - *(result_array + i++) = spp_host_to_net_byte_order_32(count2); - - /* - * Find entries free and used in user-db - */ - count1 = vec_len(cnat_user_db); - count2 = db_free_entry(cnat_user_db); - count3 = count1 - count2; - - *(result_array + i++) = spp_host_to_net_byte_order_32(count1); - *(result_array + i++) = spp_host_to_net_byte_order_32(count3); - *(result_array + i++) = spp_host_to_net_byte_order_32(count2); - - /* - * Find entries used in in2out and out2in hash tables - * and percentage utilization. - */ - count1 = count2 = 0; - for (k = 0; k < CNAT_MAIN_HASH_SIZE; k++) { - if(cnat_in2out_hash[k].next != ~0) count1++; - if(cnat_out2in_hash[k].next != ~0) count2++; - - } - - count3 = count1*100/CNAT_MAIN_HASH_SIZE; - - *(result_array + i++) = spp_host_to_net_byte_order_32(CNAT_MAIN_HASH_SIZE); - *(result_array + i++) = spp_host_to_net_byte_order_32(count1); - *(result_array + i++) = spp_host_to_net_byte_order_32(count3); - - count3 = count2*100/CNAT_MAIN_HASH_SIZE; - - *(result_array + i++) = spp_host_to_net_byte_order_32(CNAT_MAIN_HASH_SIZE); - *(result_array + i++) = spp_host_to_net_byte_order_32(count2); - *(result_array + i++) = spp_host_to_net_byte_order_32(count3); - - mp_resp->num_bytes = spp_host_to_net_byte_order_32(i*4); - - spp_api_cnat_generic_command_debug(mp_resp); -} - -/* - * The following commands implements generic commands such as: - * - * Command 1: - * Reads num_bytes octets from a start_locn - * generic command 0 0 0 0 0 - * - * Command 2: - * Writes upto 8 octets from a start_locn - * generic command 0 0 0 0 0 - * - * Command 3: - * Dump the db summary stats - * generic command - * - * Command 4: - * Dump the user db entry - * generic command - * - * The following structures are referenced by this command: - * typedef struct _spp_api_cnat_generic_command_request { - * u16 _spp_msg_id; - * u8 rc; - * u8 core_num; - * u32 params[8]; - * } spp_api_cnat_generic_command_request_t; - * - * typedef struct { - * u16 spp_msg_id; - * u8 rc; - * u8 core; - * u32 num_bytes; - * u8 raw_data[0]; - * } cnat_generic_command_resp; - * - */ -void spp_api_cnat_generic_command_request_t_handler -(spp_api_cnat_generic_command_request_t *mp) -{ - cnat_generic_command_resp *resp_ptr; - u32 command_type, start_locn, num_bytes; - - command_type = spp_net_to_host_byte_order_32(&mp->params[0]); - resp_ptr = (cnat_generic_command_resp *) mp; - - switch (command_type) { - case CNAT_DEBUG_GENERIC_COMMAND_READ_MEM: - start_locn = spp_net_to_host_byte_order_32(&mp->params[1]); - num_bytes = spp_net_to_host_byte_order_32(&mp->params[2]); - clib_memcpy(&(resp_ptr->raw_data[0]), (u8 *) start_locn, num_bytes); - resp_ptr->num_bytes = spp_host_to_net_byte_order_32(num_bytes); - -#ifdef SHOW_DEBUG - { - u32 i; - - for (i = 0; i < num_bytes; i++) { - PLATFORM_DEBUG_PRINT("0x%02X ", resp_ptr->raw_data[i]); - if ((i % 16) == 15) { - PLATFORM_DEBUG_PRINT("\n"); - } - } - } -#endif - break; - - case CNAT_DEBUG_GENERIC_COMMAND_WRITE_MEM: - start_locn = spp_net_to_host_byte_order_32(&mp->params[1]); - num_bytes = spp_net_to_host_byte_order_32(&mp->params[2]); - - if (num_bytes > sizeof(u64)) { - mp->rc = CNAT_ERR_INVALID_MSG_SIZE; - return; - } - - clib_memcpy((u8 *) start_locn, &(mp->params[3]), num_bytes); - resp_ptr->num_bytes = 0; - break; - - case CNAT_DEBUG_GENERIC_COMMAND_DB_SUMMARY: - spp_api_cnat_generic_command_db_summary(mp); - break; - - case CNAT_DEBUG_GENERIC_COMMAND_USER_DB_PM: - spp_api_cnat_generic_command_user_db_pm(mp); - break; - - case CNAT_DEBUG_GET_CGN_DB_SUMMARY: - spp_api_cnat_get_cgn_db_summary(mp); - break; - - default: - mp->rc = CNAT_ERR_INVALID_MSG_ID; - break; - } -} - - -static int cnat_debug_init (void *notused) -{ - spp_msg_api_set_handler(SPP_API_CNAT_V4_DEBUG_DUMMY, - spp_api_cnat_v4_debug_dummy_t_handler); - - spp_msg_api_set_handler(SPP_API_CNAT_V4_DEBUG_DUMMY_MAX, - spp_api_cnat_v4_debug_dummy_max_t_handler); - - spp_msg_api_set_handler(SPP_API_CNAT_V4_DEBUG_GLOBAL, - spp_api_cnat_v4_debug_global_t_handler); - - spp_msg_api_set_handler(SPP_API_CNAT_V4_DEBUG_IN2OUT_PRIVATE_ADDR, - spp_api_cnat_v4_debug_in2out_private_addr_t_handler); - - spp_msg_api_set_handler(SPP_API_CNAT_V4_DEBUG_OUT2IN_PUBLIC_ADDR, - spp_api_cnat_v4_debug_out2in_public_addr_t_handler); - - spp_msg_api_set_handler(SPP_API_CNAT_CLEAR_DB_REQUEST, - spp_api_cnat_clear_db_request_t_handler); - - spp_msg_api_set_handler(SPP_API_CNAT_GENERIC_COMMAND_REQUEST, - spp_api_cnat_generic_command_request_t_handler); - - spp_msg_api_set_handler(SPP_API_CNAT_P2MP_DEBUG_REQUEST, - spp_api_cnat_p2mp_debug_request_t_handler); - - spp_msg_api_set_handler(SPP_API_NAT64_CLEAR_DB_REQUEST, - spp_api_nat64_clear_db_request_t_handler); - - spp_msg_api_set_handler(SPP_API_DS_LITE_CLEAR_DB_REQUEST, - spp_api_ds_lite_clear_db_request_t_handler); - - return 0; -} - -/* -************************ -* spp_api_cnat_get_cgn_db_summary -* This is for finding out the per core CPU users and utilization -************************ -*/ - -void spp_api_cnat_get_cgn_db_summary -(spp_api_cnat_generic_command_request_t *mp) -{ - u32 total_db_entries, total_free_entries, used_entries; - u32 i = 0; - cnat_generic_command_resp *mp_resp; - u32 *result_array; - - /* - * Request structure is used to send the response - */ - mp_resp = (cnat_generic_command_resp *) mp; - result_array = (u32 *) (&(mp_resp->raw_data[0])); - - /* - * Find entries free and used in main-db - */ - total_db_entries = vec_len(cnat_main_db); - total_free_entries = db_free_entry(cnat_main_db); - used_entries = total_db_entries - total_free_entries; - - *(result_array + i++) = spp_host_to_net_byte_order_32(total_db_entries); - *(result_array + i++) = spp_host_to_net_byte_order_32(used_entries); - *(result_array + i++) = spp_host_to_net_byte_order_32(total_free_entries); - - /* - * Find entries free and used in user-db - */ - total_db_entries = vec_len(cnat_user_db); - total_free_entries = db_free_entry(cnat_user_db); - used_entries = total_db_entries - total_free_entries; - - *(result_array + i++) = spp_host_to_net_byte_order_32(total_db_entries); - *(result_array + i++) = spp_host_to_net_byte_order_32(used_entries); - *(result_array + i++) = spp_host_to_net_byte_order_32(total_free_entries); - - mp_resp->num_bytes = spp_host_to_net_byte_order_32(i*sizeof(u32)); -} - -SPP_INIT_FUNCTION(cnat_debug_init); -#endif /* TOBE_PORTED */ diff --git a/plugins/plugins/vcgn/cnat_global.c b/plugins/plugins/vcgn/cnat_global.c deleted file mode 100644 index 71770834..00000000 --- a/plugins/plugins/vcgn/cnat_global.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - *------------------------------------------------------------------ - * cnat_global.c - global variables - * - * Copyright (c) 2008-2009, 2012 Cisco and/or its affiliates. - * 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. - *------------------------------------------------------------------ - */ - -/* gloable variables */ - -#include -#include -#include -#include - -#include "dslite_defs.h" -#include "tcp_header_definitions.h" -u32 cnat_current_time; -u8 nfv9_configured = 0; -/* ctx/sf alloc error counters */ -u32 null_enq_pkt; -u32 null_deq_pkt; - -u32 null_enq_ctx; -u32 null_deq_ctx; - -u32 null_enq_wqe; -u32 null_deq_wqe; - -u32 ctx_alloc_errs; -u32 sf_alloc_errs; - -u32 rcv_pkt_errs; - -/* TOBE_PORTED : Remove following once we bring DSLite */ -u32 dslite_config_debug_level = 1; -u32 dslite_data_path_debug_level = 1; -u32 dslite_defrag_debug_level = 1; -u32 dslite_debug_level = 1; - -dslite_table_entry_t *dslite_table_db_ptr; - -/* - * ipv4_decr_ttl_n_calc_csum() - * - It decrements the TTL and calculates the incremental IPv4 checksum - */ - -/* TOBE_PORTED: Following is in cnat_util.c */ -always_inline __attribute__((unused)) -void ipv4_decr_ttl_n_calc_csum(ipv4_header *ipv4) -{ - u32 checksum; - u16 old; - u16 ttl; - - ttl = ipv4->ttl; - old = clib_net_to_host_u16(ttl); - - /* Decrement TTL */ - ipv4->ttl--; - - /* Calculate incremental checksum */ - checksum = old + (~clib_net_to_host_u16(ttl) & 0xFFFF); - checksum += clib_net_to_host_u16(ipv4->checksum); - checksum = (checksum & 0xFFFF) + (checksum >> 16); - ipv4->checksum = clib_host_to_net_u32(checksum + (checksum >> 16)); -} - diff --git a/plugins/plugins/vcgn/cnat_global.h b/plugins/plugins/vcgn/cnat_global.h deleted file mode 100644 index 823a4797..00000000 --- a/plugins/plugins/vcgn/cnat_global.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - *------------------------------------------------------------------ - * cnat_global.h - global definition and variables - * to be used by non cnat files - * - * Copyright (c) 2007-2012 Cisco and/or its affiliates. - * 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 __CNAT_GLOBAL_H__ -#define __CNAT_GLOBAL_H__ - -/* gloable variables */ - -extern u8 cnat_db_init_done; -extern u32 cnat_current_time; -extern u64 in2out_drops_port_limit_exceeded; -extern u64 in2out_drops_system_limit_reached; -extern u64 in2out_drops_resource_depletion; -extern u64 no_translation_entry_drops; -extern u8 nfv9_configured; -extern u32 translation_create_count; -extern u32 translation_create_rate; - -extern u32 translation_delete_count; -extern u32 translation_delete_rate; - -extern u32 in2out_forwarding_count; -extern u32 in2out_forwarding_rate; - -extern u32 out2in_forwarding_count; -extern u32 out2in_forwarding_rate; - -extern u32 total_address_pool_allocated; - -extern u32 nat44_active_translations; - -#if 1 //DSLITE_DEF -extern u32 dslite_translation_create_rate; -extern u32 dslite_translation_delete_rate; -extern u32 dslite_translation_create_count; -extern u32 dslite_in2out_forwarding_count; -extern u32 dslite_in2out_forwarding_count; -extern u32 dslite_out2in_forwarding_rate; -#endif -/* sf/ctx allocation error collection declarations */ -#define COLLECT_FREQ_FACTOR 100 -#define NUM_SECONDS_TO_WAIT 10 -#define COUNTER_BUFFER_SIZE 25 - -extern u32 null_enq_pkt; -extern u32 null_deq_pkt; - -extern u32 null_enq_ctx; -extern u32 null_deq_ctx; - -extern u32 null_enq_wqe; -extern u32 null_deq_wqe; - -extern u32 ctx_alloc_errs; -extern u32 sf_alloc_errs; - -extern u32 rcv_pkt_errs; - -struct counter_array_t { - u32 sf_error_counter; - u32 ctx_error_counter; - u32 timestamp; -} counter_array_t; - -#define COUNTER_BUFFER_SIZE 25 -struct counter_array_t err_cnt_arr[COUNTER_BUFFER_SIZE]; - -//#define DISABLE_ICMP_THROTTLE_FOR_DEBUG_PURPOSE - -#endif /*__CNAT_GLOBAL_H__*/ diff --git a/plugins/plugins/vcgn/cnat_ipv4_icmp.h b/plugins/plugins/vcgn/cnat_ipv4_icmp.h deleted file mode 100644 index 664b62ac..00000000 --- a/plugins/plugins/vcgn/cnat_ipv4_icmp.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - *----------------------------------------------------------------------------- - * - * Filename: cnat_ipv4_icmp.h - * - * Description: common functions for icmp node - * - * Assumptions and Constraints: - * - * Copyright (c) 2000-2009, 2014 Cisco and/or its affiliates. - * 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 __CNAT_IPV4_ICMP_H__ -#define __CNAT_IPV4_ICMP_H__ - -#include "tcp_header_definitions.h" -#include "cnat_db.h" -#include "cnat_v4_functions.h" -#include "cnat_global.h" -#include "cnat_config.h" - -typedef struct { - icmp_v4_t *icmp; - ipv4_header *em_ip; - u16 *em_port; - u16 *em_l4_checksum; -} icmp_em_ip_info; - -extern void swap_ip_src_icmp_id(ipv4_header *ip, - icmp_v4_t *icmp, - cnat_main_db_entry_t *db, - u16 vrf); - -extern void swap_ip_dst_icmp_id(ipv4_header *ip, - icmp_v4_t *icmp, - cnat_main_db_entry_t *db, - u16 vrf); - -extern void swap_ip_src_emip_dst(ipv4_header *ip, - icmp_em_ip_info *icmp_info, - cnat_main_db_entry_t *db, u16 vrf); - -extern void swap_ip_dst_emip_src(ipv4_header *ip, - icmp_em_ip_info *icmp_info, - cnat_main_db_entry_t *db, u16 vrf); - - -#endif /* __CNAT_IPV4_ICMP_H__ */ diff --git a/plugins/plugins/vcgn/cnat_ipv4_icmp_error_inside_input.c b/plugins/plugins/vcgn/cnat_ipv4_icmp_error_inside_input.c deleted file mode 100644 index 218d7e53..00000000 --- a/plugins/plugins/vcgn/cnat_ipv4_icmp_error_inside_input.c +++ /dev/null @@ -1,476 +0,0 @@ -/* - *--------------------------------------------------------------------------- - * cnat_ipv4_icmp_error_inside_input.c - cnat_ipv4_icmp_error_inside_input node pipeline stage functions - * - * Copyright (c) 2008-2014 Cisco and/or its affiliates. - * 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 -#include -#include -#include - -#include "cnat_ipv4_icmp.h" - -#define foreach_cnat_ipv4_icmp_e_inside_input_error \ -_(CNAT_V4_ICMP_E_I2O_T_PKT, "cnat v4 icmp_e i2o packet transmit") \ -_(CNAT_V4_ICMP_E_I2O_D_PKT, "cnat v4 icmp_e i2o packet drop") \ -_(CNAT_V4_ICMP_E_I2O_TTL_DROP, "cnat v4 icmp_e i2o ttl drop") - -typedef enum { -#define _(sym,str) sym, - foreach_cnat_ipv4_icmp_e_inside_input_error -#undef _ - CNAT_IPV4_ICMP_E_INSIDE_INPUT_N_ERROR, -} cnat_ipv4_icmp_e_inside_input_t; - -static char * cnat_ipv4_icmp_e_inside_input_error_strings[] = { -#define _(sym,string) string, - foreach_cnat_ipv4_icmp_e_inside_input_error -#undef _ -}; - -typedef struct { - u32 cached_next_index; - /* $$$$ add data here */ - - /* convenience variables */ - vlib_main_t * vlib_main; - vnet_main_t * vnet_main; -} cnat_ipv4_icmp_e_inside_input_main_t; - -typedef enum { - CNAT_V4_ICMP_E_I2O_T, - CNAT_V4_ICMP_E_I2O_D, - CNAT_V4_ICMP_E_I2O_NEXT, -} cnat_ipv4_icmp_e_inside_input_next_t; - -cnat_ipv4_icmp_e_inside_input_main_t cnat_ipv4_icmp_e_inside_input_main; -vlib_node_registration_t cnat_ipv4_icmp_e_inside_input_node; - -#define NSTAGES 5 - -inline void swap_ip_src_emip_dst(ipv4_header *ip, - icmp_em_ip_info *icmp_info, - cnat_main_db_entry_t *db, u16 vrf) -{ - icmp_v4_t *icmp; - ipv4_header *em_ip; - u16 *em_port; - u32 old_ip; - u16 old_port; - u16 old_ip_checksum; - - /* - * declear variable - */ - CNAT_UPDATE_L3_CHECKSUM_DECLARE - CNAT_UPDATE_ICMP_ERR_CHECKSUM_DECLARE - - /* - * fix inner layer ip & l4 checksum - */ - em_ip = icmp_info->em_ip; - em_port = icmp_info->em_port; - - CNAT_UPDATE_L3_CHECKSUM(((u16)(db->in2out_key.k.ipv4)), - ((u16)(db->in2out_key.k.ipv4 >> 16)), - (clib_net_to_host_u16(em_ip->checksum)), - ((u16)(db->out2in_key.k.ipv4)), - ((u16)(db->out2in_key.k.ipv4 >> 16))) - - old_ip = clib_net_to_host_u32(em_ip->dest_addr); - old_port = clib_net_to_host_u16(*em_port); - old_ip_checksum = clib_net_to_host_u16(em_ip->checksum); - - em_ip->dest_addr = - clib_host_to_net_u32(db->out2in_key.k.ipv4); - em_ip->checksum = - clib_host_to_net_u16(new_l3_c); - *em_port = - clib_host_to_net_u16(db->out2in_key.k.port); - - /* - * fix outter layer ip & icmp checksum - */ - icmp = icmp_info->icmp; - CNAT_UPDATE_ICMP_ERR_CHECKSUM(((u16)(old_ip & 0xFFFF)), - ((u16)(old_ip >> 16)), - (old_port), - (old_ip_checksum), - (clib_net_to_host_u16(icmp->checksum)), - ((u16)(db->out2in_key.k.ipv4 & 0xffff)), - ((u16)(db->out2in_key.k.ipv4 >> 16)), - ((u16)(db->out2in_key.k.port)), - ((u16)(new_l3_c))) - - icmp->checksum = - clib_host_to_net_u16(new_icmp_c); - - old_ip = clib_net_to_host_u32(ip->src_addr); - - ip->src_addr = - clib_host_to_net_u32(db->out2in_key.k.ipv4); - - CNAT_UPDATE_L3_CHECKSUM(((u16)(old_ip & 0xFFFF)), - ((u16)(old_ip >> 16)), - (clib_net_to_host_u16(ip->checksum)), - ((u16)(db->out2in_key.k.ipv4)), - ((u16)(db->out2in_key.k.ipv4 >> 16))) - ip->checksum = - clib_host_to_net_u16(new_l3_c); - -#if 0 - if(is_static_dest_nat_enabled(vrf) == CNAT_SUCCESS) { - /* - * fix inner layer ip & l4 checksum - */ - em_snat_ip = icmp_info->em_ip; - em_snat_port = icmp_info->em_port; - - old_ip = spp_net_to_host_byte_order_32(&(em_snat_ip->src_addr)); - old_port = spp_net_to_host_byte_order_16(em_snat_port); - old_ip_checksum = spp_net_to_host_byte_order_16(&(em_snat_ip->checksum)); - direction = 0; - if(cnat_static_dest_db_get_translation(em_snat_ip->src_addr, &postmap_ip, vrf, direction) == CNAT_SUCCESS) { - old_postmap_ip = spp_net_to_host_byte_order_32(&postmap_ip); - - CNAT_UPDATE_L3_CHECKSUM(((u16)(old_ip)), - ((u16)(old_ip >> 16)), - (spp_net_to_host_byte_order_16(&(em_snat_ip->checksum))), - ((u16)(old_postmap_ip)), - ((u16)(old_postmap_ip >> 16))) - em_snat_ip->src_addr = postmap_ip; - em_snat_ip->checksum = - spp_host_to_net_byte_order_16(new_l3_c); - - /* - * fix outter layer ip & icmp checksum - */ - icmp = icmp_info->icmp; - CNAT_UPDATE_ICMP_ERR_CHECKSUM(((u16)(old_ip & 0xFFFF)), - ((u16)(old_ip >> 16)), - (old_port), - (old_ip_checksum), - (spp_net_to_host_byte_order_16(&(icmp->checksum))), - ((u16)(old_postmap_ip & 0xffff)), - ((u16)(old_postmap_ip >> 16)), - ((u16)(old_port)), - ((u16)(new_l3_c))) - - icmp->checksum = - spp_host_to_net_byte_order_16(new_icmp_c); - - } - } - - if(is_static_dest_nat_enabled(vrf) == CNAT_SUCCESS) { - direction = 0; - if(cnat_static_dest_db_get_translation(ip->dest_addr, &postmap_ip, vrf, direction) == CNAT_SUCCESS) { - - old_ip = spp_net_to_host_byte_order_32(&(ip->dest_addr)); - old_postmap_ip = spp_net_to_host_byte_order_32(&postmap_ip); - - CNAT_UPDATE_L3_CHECKSUM(((u16)(old_ip & 0xFFFF)), - ((u16)(old_ip >> 16)), - (spp_net_to_host_byte_order_16(&(ip->checksum))), - ((u16)(old_postmap_ip & 0xFFFF)), - ((u16)(old_postmap_ip >> 16))) - ip->dest_addr = postmap_ip; - - ip->checksum = - clib_host_to_net_u16(new_l3_c); - } - } -#endif /* if 0 */ - -} - -/* - * Use the generic buffer metadata + first line of packet data prefetch - * stage function from . This is usually a Good Idea. - */ -#define stage0 generic_stage0 - - -static inline void -stage1(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) -{ - u64 a, b, c; - u32 bucket; - u8 *prefetch_target; - - vlib_buffer_t * b0 = vlib_get_buffer (vm, buffer_index); - ipv4_header *ip = vlib_buffer_get_current (b0); - u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; - icmp_v4_t *icmp = (icmp_v4_t *)((u8*)ip + ipv4_hdr_len); - ipv4_header *em_ip = (ipv4_header*)((u8*)icmp + 8); /* embedded pkt's v4 hdr */ - u8 em_ip_hdr_len = (em_ip->version_hdr_len_words & 0xf) << 2; - - u64 tmp = 0; - u32 protocol = CNAT_ICMP; - - /* Check L4 header for embedded packet */ - if (em_ip->protocol == TCP_PROT) { - tcp_hdr_type *tcp = (tcp_hdr_type*)((u8 *)em_ip + em_ip_hdr_len); - vnet_buffer(b0)->vcgn_uii.key.k.port = - clib_net_to_host_u16(tcp->dest_port); - protocol = CNAT_TCP; - - } else if (em_ip->protocol == UDP_PROT) { - udp_hdr_type_t *udp = (udp_hdr_type_t *)((u8 *)em_ip + em_ip_hdr_len); - vnet_buffer(b0)->vcgn_uii.key.k.port = - clib_net_to_host_u16(udp->dest_port); - protocol = CNAT_UDP; - - } else { - icmp_v4_t *icmp = (icmp_v4_t*)((u8 *)em_ip + em_ip_hdr_len); - vnet_buffer(b0)->vcgn_uii.key.k.port = - clib_net_to_host_u16(icmp->identifier); - - if (PREDICT_FALSE((icmp->type != ICMPV4_ECHOREPLY) && - (icmp->type != ICMPV4_ECHO))) { - /* - * Try to set invalid protocol for these cases, so that - * hash lookup does not return valid main_db. This approach - * may optimize the regular cases with valid protocols - * as it avoids one more check for regular cases in stage3 - */ - protocol = CNAT_INVALID_PROTO; - } - } - - tmp = vnet_buffer(b0)->vcgn_uii.key.k.ipv4 = - clib_net_to_host_u32(em_ip->dest_addr); - - tmp |= ((u64)vnet_buffer(b0)->vcgn_uii.key.k.port) << 32; - - PLATFORM_CNAT_SET_RX_VRF(vnet_buffer(b0)->sw_if_index[VLIB_RX], - vnet_buffer(b0)->vcgn_uii.key.k.vrf, - protocol) - tmp |= ((u64)vnet_buffer(b0)->vcgn_uii.key.k.vrf) << 48; - - CNAT_V4_GET_HASH(tmp, bucket, CNAT_MAIN_HASH_MASK) - - prefetch_target = (u8 *)(&cnat_in2out_hash[bucket]); - vnet_buffer(b0)->vcgn_uii.bucket = bucket; - - /* Prefetch the hash bucket */ - CLIB_PREFETCH(prefetch_target, CLIB_CACHE_LINE_BYTES, LOAD); -} - -#define SPP_LOG2_CACHE_LINE_BYTES 6 -#define SPP_CACHE_LINE_BYTES (1 << SPP_LOG2_CACHE_LINE_BYTES) - -static inline void -stage2(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) -{ - vlib_buffer_t * b0 = vlib_get_buffer(vm, buffer_index); - uword prefetch_target0, prefetch_target1; - u32 bucket = vnet_buffer(b0)->vcgn_uii.bucket; - - /* read the hash bucket */ - u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket - = cnat_in2out_hash[bucket].next; - - if (PREDICT_TRUE(db_index != EMPTY)) { - /* - * Prefetch database keys. We save space by not cache-line - * aligning the DB entries. We don't want to waste LSU - * bandwidth prefetching stuff we won't need. - */ - prefetch_target0 = (uword)(cnat_main_db + db_index); - CLIB_PREFETCH((void*)prefetch_target0, CLIB_CACHE_LINE_BYTES, LOAD); - /* Just beyond DB key #2 */ - prefetch_target1 = prefetch_target0 + - STRUCT_OFFSET_OF(cnat_main_db_entry_t, user_ports); - /* If the targets are in different lines, do the second prefetch */ - if (PREDICT_FALSE((prefetch_target0 & ~(SPP_CACHE_LINE_BYTES-1)) != - (prefetch_target1 & ~(SPP_CACHE_LINE_BYTES-1)))) { - CLIB_PREFETCH((void *)prefetch_target1, CLIB_CACHE_LINE_BYTES, LOAD); - } - } -} - -static inline void -stage3(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) -{ - cnat_main_db_entry_t *db; - vlib_buffer_t * b0 = vlib_get_buffer(vm, buffer_index); - u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket; - - /* - * Note: if the search already failed (empty bucket), - * the answer is already in the pipeline context structure - */ - if (PREDICT_TRUE(db_index != EMPTY)) { - - /* - * Note: hash collisions suck. We can't easily prefetch around them. - * The first trip around the track will be fast. After that, maybe - * not so much... - */ - do { - db = cnat_main_db + db_index; - if (PREDICT_TRUE(db->in2out_key.key64 == - vnet_buffer(b0)->vcgn_uii.key.key64)) { - break; - } - db_index = db->in2out_hash.next; - } while (db_index != EMPTY); - - /* Stick the answer back into the pipeline context structure */ - vnet_buffer(b0)->vcgn_uii.bucket = db_index; - } -} - - - -static inline u32 last_stage (vlib_main_t *vm, vlib_node_runtime_t *node, - u32 bi) -{ - vlib_buffer_t *b0 = vlib_get_buffer (vm, bi); - u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket; - int disposition = CNAT_V4_ICMP_E_I2O_T; - int counter = CNAT_V4_ICMP_E_I2O_T_PKT; - - ipv4_header *ip = (ipv4_header *)vlib_buffer_get_current(b0); - u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; - icmp_v4_t *icmp = (icmp_v4_t *)((u8*)ip + ipv4_hdr_len); - ipv4_header *em_ip = (ipv4_header*)((u8*)icmp + 8); /* embedded pkt's v4 hdr */ - u8 em_ip_hdr_len = (em_ip->version_hdr_len_words & 0xf) << 2; - vlib_node_t *n = vlib_get_node (vm, cnat_ipv4_icmp_e_inside_input_node.index); - u32 node_counter_base_index = n->error_heap_index; - vlib_error_main_t * em = &vm->error_main; - cnat_main_db_entry_t *db = NULL; - icmp_em_ip_info icmp_info; - - if (PLATFORM_HANDLE_TTL_DECREMENT) { - if (PREDICT_FALSE(ip->ttl <= 1)) { - /* - * As it is ICMP error packet with TTL <= 1, - * let's drop the packet (no need to genereate - * another ICMP error). - */ - - disposition = CNAT_V4_ICMP_E_I2O_D; - counter = CNAT_V4_ICMP_E_I2O_TTL_DROP; - - goto drop_pkt; - } - } - - if (PREDICT_TRUE(db_index != EMPTY)) { - icmp_info.em_ip = em_ip; - icmp_info.icmp = icmp; - //icmp_info.em_port = vnet_buffer(b0)->vcgn_uii.key.k.port; - - /* Note: This could have been done in stage1 itself, - * but we need to introduce one u16 * in vnet_buffer_opaque_t - * Since this flow is expected to be very rare in actual - * deployment scenario, we may afford to do these steps here - * as well. Lets confirm during core review. */ - if (em_ip->protocol == TCP_PROT) { - tcp_hdr_type *tcp = (tcp_hdr_type*)((u8 *)em_ip + em_ip_hdr_len); - icmp_info.em_port = &(tcp->dest_port); - } else if (em_ip->protocol == UDP_PROT) { - udp_hdr_type_t *udp = (udp_hdr_type_t *) - ((u8 *)em_ip + em_ip_hdr_len); - icmp_info.em_port = &(udp->dest_port); - } else { - icmp_v4_t *icmp_inner = (icmp_v4_t*)((u8 *)em_ip + em_ip_hdr_len); - icmp_info.em_port = &(icmp_inner->identifier); - } - - db = cnat_main_db + db_index; - /* - * 1. update dst addr:dst port of embedded ip pkt - * update src addr of icmp pkt - * 2. fix udp/tcp/ip checksum of embedded pkt - * fix icmp, ip check of icmp pkt - * don need to update the timer - */ - - if (PREDICT_FALSE(icmp_debug_flag)) { - printf("\nDUMPING ICMP PKT BEFORE\n"); - print_icmp_pkt(ip); - } - - if (PLATFORM_HANDLE_TTL_DECREMENT) { - /* - * Decrement TTL and update IPv4 checksum - */ - ipv4_decr_ttl_n_calc_csum(ip); - } - - swap_ip_src_emip_dst(ip, &icmp_info, - db, db->in2out_key.k.vrf); - - if (PREDICT_FALSE(icmp_debug_flag)) { - printf("\nDUMPING ICMP PKT AFTER\n"); - print_icmp_pkt(ip); - } - in2out_forwarding_count++; - - } else { - disposition = CNAT_V4_ICMP_E_I2O_D; - counter = CNAT_V4_ICMP_E_I2O_D_PKT; - } - -drop_pkt: - - em->counters[node_counter_base_index + counter] += 1; - return disposition; -} - -#include - -static uword cnat_ipv4_icmp_e_inside_input_node_fn (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return dispatch_pipeline (vm, node, frame); -} - - -VLIB_REGISTER_NODE (cnat_ipv4_icmp_e_inside_input_node) = { - .function = cnat_ipv4_icmp_e_inside_input_node_fn, - .name = "vcgn-v4-icmp-e-i2o", - .vector_size = sizeof (u32), - .type = VLIB_NODE_TYPE_INTERNAL, - - .n_errors = ARRAY_LEN(cnat_ipv4_icmp_e_inside_input_error_strings), - .error_strings = cnat_ipv4_icmp_e_inside_input_error_strings, - - .n_next_nodes = CNAT_V4_ICMP_E_I2O_NEXT, - - /* edit / add dispositions here */ - .next_nodes = { - [CNAT_V4_ICMP_E_I2O_T] = "ip4-input", - [CNAT_V4_ICMP_E_I2O_D] = "error-drop", - }, -}; - -clib_error_t *cnat_ipv4_icmp_e_inside_input_init (vlib_main_t *vm) -{ - cnat_ipv4_icmp_e_inside_input_main_t * mp = &cnat_ipv4_icmp_e_inside_input_main; - - mp->vlib_main = vm; - mp->vnet_main = vnet_get_main(); - - return 0; -} - -VLIB_INIT_FUNCTION (cnat_ipv4_icmp_e_inside_input_init); diff --git a/plugins/plugins/vcgn/cnat_ipv4_icmp_error_outside_input.c b/plugins/plugins/vcgn/cnat_ipv4_icmp_error_outside_input.c deleted file mode 100644 index f25f4d02..00000000 --- a/plugins/plugins/vcgn/cnat_ipv4_icmp_error_outside_input.c +++ /dev/null @@ -1,452 +0,0 @@ -/* - *--------------------------------------------------------------------------- - * cnat_ipv4_icmp_error_outside_input.c - cnat_ipv4_icmp_error_outside_input node pipeline stage functions - * - * Copyright (c) 2008-2014 Cisco and/or its affiliates. - * 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 -#include -#include -#include - -#include "cnat_ipv4_icmp.h" - -#define foreach_cnat_ipv4_icmp_e_outside_input_error \ -_(CNAT_V4_ICMP_E_O2I_T_PKT, "cnat v4 icmp_e o2i packet transmit") \ -_(CNAT_V4_ICMP_E_O2I_D_PKT, "cnat v4 icmp_e o2i packet drop") \ -_(CNAT_V4_ICMP_E_O2I_TTL_DROP, "cnat v4 icmp_e o2i ttl drop") - -typedef enum { -#define _(sym,str) sym, - foreach_cnat_ipv4_icmp_e_outside_input_error -#undef _ - CNAT_IPV4_ICMP_E_OUTSIDE_INPUT_N_ERROR, -} cnat_ipv4_icmp_e_outside_input_t; - -static char * cnat_ipv4_icmp_e_outside_input_error_strings[] = { -#define _(sym,string) string, - foreach_cnat_ipv4_icmp_e_outside_input_error -#undef _ -}; - -typedef struct { - u32 cached_next_index; - /* $$$$ add data here */ - - /* convenience variables */ - vlib_main_t * vlib_main; - vnet_main_t * vnet_main; -} cnat_ipv4_icmp_e_outside_input_main_t; - -typedef enum { - CNAT_V4_ICMP_E_O2I_T, - CNAT_V4_ICMP_E_O2I_D, - CNAT_V4_ICMP_E_O2I_NEXT, -} cnat_ipv4_icmp_e_outside_input_next_t; - -cnat_ipv4_icmp_e_outside_input_main_t cnat_ipv4_icmp_e_outside_input_main; -vlib_node_registration_t cnat_ipv4_icmp_e_outside_input_node; - -#define NSTAGES 5 - -inline void swap_ip_dst_emip_src(ipv4_header *ip, - icmp_em_ip_info *icmp_info, - cnat_main_db_entry_t *db, u16 vrf) -{ - icmp_v4_t *icmp; - ipv4_header *em_ip; - u16 *em_port; - u32 old_ip; - u16 old_port; - u16 old_ip_checksum; - - /* - * declear variable - */ - CNAT_UPDATE_L3_CHECKSUM_DECLARE - CNAT_UPDATE_ICMP_ERR_CHECKSUM_DECLARE - - /* - * fix inner layer ip & l4 checksum - */ - em_ip = icmp_info->em_ip; - em_port = icmp_info->em_port; - - CNAT_UPDATE_L3_CHECKSUM(((u16)(db->out2in_key.k.ipv4)), - ((u16)(db->out2in_key.k.ipv4 >> 16)), - (clib_net_to_host_u16(em_ip->checksum)), - ((u16)(db->in2out_key.k.ipv4)), - ((u16)(db->in2out_key.k.ipv4 >> 16))) - - old_ip = clib_net_to_host_u32(em_ip->src_addr); - old_port = clib_net_to_host_u16(*em_port); - old_ip_checksum = clib_net_to_host_u16(em_ip->checksum); - - em_ip->src_addr = - clib_host_to_net_u32(db->in2out_key.k.ipv4); - em_ip->checksum = - clib_host_to_net_u16(new_l3_c); - *em_port = - clib_host_to_net_u16(db->in2out_key.k.port); - - /* - * fix outter layer ip & icmp checksum - */ - icmp = icmp_info->icmp; - CNAT_UPDATE_ICMP_ERR_CHECKSUM(((u16)(old_ip & 0xFFFF)), - ((u16)(old_ip >> 16)), - (old_port), - (old_ip_checksum), - (clib_net_to_host_u16(icmp->checksum)), - ((u16)(db->in2out_key.k.ipv4 & 0xffff)), - ((u16)(db->in2out_key.k.ipv4 >> 16)), - ((u16)(db->in2out_key.k.port)), - ((u16)(new_l3_c))) - - icmp->checksum = - clib_host_to_net_u16(new_icmp_c); - - old_ip = clib_net_to_host_u32(ip->dest_addr); - - ip->dest_addr = - clib_host_to_net_u32(db->in2out_key.k.ipv4); - - CNAT_UPDATE_L3_CHECKSUM(((u16)(old_ip & 0xFFFF)), - ((u16)(old_ip >> 16)), - (clib_net_to_host_u16(ip->checksum)), - ((u16)(db->in2out_key.k.ipv4)), - ((u16)(db->in2out_key.k.ipv4 >> 16))) - ip->checksum = - clib_host_to_net_u16(new_l3_c); - -#if 0 - if(is_static_dest_nat_enabled(vrf) == CNAT_SUCCESS) { - /* - * fix inner layer ip & l4 checksum - */ - em_snat_ip = icmp_info->em_ip; - em_snat_port = icmp_info->em_port; - - old_ip = spp_net_to_host_byte_order_32(&(em_snat_ip->dest_addr)); - old_port = spp_net_to_host_byte_order_16(em_snat_port); - old_ip_checksum = spp_net_to_host_byte_order_16(&(em_snat_ip->checksum)); - direction = 1; - if(cnat_static_dest_db_get_translation(em_snat_ip->dest_addr, &postmap_ip, vrf, direction) == CNAT_SUCCESS) { - old_postmap_ip = spp_net_to_host_byte_order_32(&postmap_ip); - - CNAT_UPDATE_L3_CHECKSUM(((u16)(old_ip)), - ((u16)(old_ip >> 16)), - (spp_net_to_host_byte_order_16(&(em_snat_ip->checksum))), - ((u16)(old_postmap_ip)), - ((u16)(old_postmap_ip >> 16))) - em_snat_ip->dest_addr = postmap_ip; - em_snat_ip->checksum = - spp_host_to_net_byte_order_16(new_l3_c); - - /* - * fix outter layer ip & icmp checksum - */ - icmp = icmp_info->icmp; - CNAT_UPDATE_ICMP_ERR_CHECKSUM(((u16)(old_ip & 0xFFFF)), - ((u16)(old_ip >> 16)), - (old_port), - (old_ip_checksum), - (spp_net_to_host_byte_order_16(&(icmp->checksum))), - ((u16)(old_postmap_ip & 0xffff)), - ((u16)(old_postmap_ip >> 16)), - ((u16)(old_port)), - ((u16)(new_l3_c))) - - icmp->checksum = - spp_host_to_net_byte_order_16(new_icmp_c); - - } - } - - if(is_static_dest_nat_enabled(vrf) == CNAT_SUCCESS) { - direction = 1; - if(cnat_static_dest_db_get_translation(ip->src_addr, &postmap_ip, vrf, direction) == CNAT_SUCCESS) { - CNAT_UPDATE_L3_CHECKSUM_DECLARE - - old_ip = spp_net_to_host_byte_order_32(&(ip->src_addr)); - old_postmap_ip = spp_net_to_host_byte_order_32(&postmap_ip); - - CNAT_UPDATE_L3_CHECKSUM(((u16)(old_ip & 0xFFFF)), - ((u16)(old_ip >> 16)), - (spp_net_to_host_byte_order_16(&(ip->checksum))), - ((u16)(old_postmap_ip & 0xFFFF)), - ((u16)(old_postmap_ip >> 16))) - ip->checksum = - spp_host_to_net_byte_order_16(new_l3_c); - ip->src_addr = postmap_ip; - } - } -#endif /* if 0 */ -} - -/* - * Use the generic buffer metadata + first line of packet data prefetch - * stage function from . This is usually a Good Idea. - */ -#define stage0 generic_stage0 - - -static inline void -stage1(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) -{ - u64 a, b, c; - u32 bucket; - u8 *prefetch_target; - - vlib_buffer_t * b0 = vlib_get_buffer (vm, buffer_index); - ipv4_header *ip = vlib_buffer_get_current (b0); - u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; - icmp_v4_t *icmp = (icmp_v4_t *)((u8*)ip + ipv4_hdr_len); - ipv4_header *em_ip = (ipv4_header*)((u8*)icmp + 8); /* embedded pkt's v4 hdr */ - u8 em_ip_hdr_len = (em_ip->version_hdr_len_words & 0xf) << 2; - - u64 tmp = 0; - u32 protocol = CNAT_ICMP; - - /* Check L4 header for embedded packet */ - if (em_ip->protocol == TCP_PROT) { - tcp_hdr_type *tcp = (tcp_hdr_type*)((u8 *)em_ip + em_ip_hdr_len); - vnet_buffer(b0)->vcgn_uii.key.k.port = - clib_net_to_host_u16(tcp->src_port); - protocol = CNAT_TCP; - - } else if (em_ip->protocol == UDP_PROT) { - udp_hdr_type_t *udp = (udp_hdr_type_t *)((u8 *)em_ip + em_ip_hdr_len); - vnet_buffer(b0)->vcgn_uii.key.k.port = - clib_net_to_host_u16(udp->src_port); - protocol = CNAT_UDP; - - } else { - icmp_v4_t *icmp = (icmp_v4_t*)((u8 *)em_ip + em_ip_hdr_len); - vnet_buffer(b0)->vcgn_uii.key.k.port = - clib_net_to_host_u16(icmp->identifier); - - if (PREDICT_FALSE((icmp->type != ICMPV4_ECHOREPLY) && - (icmp->type != ICMPV4_ECHO))) { - /* - * Try to set invalid protocol for these cases, so that - * hash lookup does not return valid main_db. This approach - * may optimize the regular cases with valid protocols - * as it avoids one more check for regular cases in stage3 - */ - protocol = CNAT_INVALID_PROTO; - } - } - - tmp = vnet_buffer(b0)->vcgn_uii.key.k.ipv4 = - clib_net_to_host_u32(em_ip->src_addr); - - tmp |= ((u64)vnet_buffer(b0)->vcgn_uii.key.k.port) << 32; - - PLATFORM_CNAT_SET_RX_VRF(vnet_buffer(b0)->sw_if_index[VLIB_RX], - vnet_buffer(b0)->vcgn_uii.key.k.vrf, - protocol) - tmp |= ((u64)vnet_buffer(b0)->vcgn_uii.key.k.vrf) << 48; - - CNAT_V4_GET_HASH(tmp, bucket, CNAT_MAIN_HASH_MASK) - - prefetch_target = (u8 *)(&cnat_out2in_hash[bucket]); - vnet_buffer(b0)->vcgn_uii.bucket = bucket; - - /* Prefetch the hash bucket */ - CLIB_PREFETCH(prefetch_target, CLIB_CACHE_LINE_BYTES, LOAD); -} - - -#define SPP_LOG2_CACHE_LINE_BYTES 6 -#define SPP_CACHE_LINE_BYTES (1 << SPP_LOG2_CACHE_LINE_BYTES) - -static inline void -stage2(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) -{ - vlib_buffer_t * b0 = vlib_get_buffer(vm, buffer_index); - uword prefetch_target0, prefetch_target1; - u32 bucket = vnet_buffer(b0)->vcgn_uii.bucket; - - /* read the hash bucket */ - u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket - = cnat_out2in_hash[bucket].next; - - if (PREDICT_TRUE(db_index != EMPTY)) { - /* - * Prefetch database keys. We save space by not cache-line - * aligning the DB entries. We don't want to waste LSU - * bandwidth prefetching stuff we won't need. - */ - prefetch_target0 = (uword)(cnat_main_db + db_index); - CLIB_PREFETCH((void*)prefetch_target0, CLIB_CACHE_LINE_BYTES, LOAD); - /* Just beyond DB key #2 */ - prefetch_target1 = prefetch_target0 + - STRUCT_OFFSET_OF(cnat_main_db_entry_t, user_ports); - /* If the targets are in different lines, do the second prefetch */ - if (PREDICT_FALSE((prefetch_target0 & ~(SPP_CACHE_LINE_BYTES-1)) != - (prefetch_target1 & ~(SPP_CACHE_LINE_BYTES-1)))) { - CLIB_PREFETCH((void *)prefetch_target1, CLIB_CACHE_LINE_BYTES, LOAD); - } - } -} - - -static inline void -stage3(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) -{ - cnat_main_db_entry_t *db; - vlib_buffer_t * b0 = vlib_get_buffer(vm, buffer_index); - u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket; - - /* - * Note: if the search already failed (empty bucket), - * the answer is already in the pipeline context structure - */ - if (PREDICT_TRUE(db_index != EMPTY)) { - - /* - * Note: hash collisions suck. We can't easily prefetch around them. - * The first trip around the track will be fast. After that, maybe - * not so much... - */ - do { - db = cnat_main_db + db_index; - if (PREDICT_TRUE(db->out2in_key.key64 == - vnet_buffer(b0)->vcgn_uii.key.key64)) { - break; - } - db_index = db->out2in_hash.next; - } while (db_index != EMPTY); - - /* Stick the answer back into the pipeline context structure */ - vnet_buffer(b0)->vcgn_uii.bucket = db_index; - } -} - -static inline u32 last_stage (vlib_main_t *vm, vlib_node_runtime_t *node, - u32 bi) -{ - vlib_buffer_t *b0 = vlib_get_buffer (vm, bi); - u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket; - int disposition = CNAT_V4_ICMP_E_O2I_T; - int counter = CNAT_V4_ICMP_E_O2I_T_PKT; - - ipv4_header *ip = (ipv4_header *)vlib_buffer_get_current(b0); - u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; - icmp_v4_t *icmp = (icmp_v4_t *)((u8*)ip + ipv4_hdr_len); - ipv4_header *em_ip = (ipv4_header*)((u8*)icmp + 8); /* embedded pkt's v4 hdr */ - u8 em_ip_hdr_len = (em_ip->version_hdr_len_words & 0xf) << 2; - vlib_node_t *n = vlib_get_node (vm, cnat_ipv4_icmp_e_outside_input_node.index); - u32 node_counter_base_index = n->error_heap_index; - vlib_error_main_t * em = &vm->error_main; - cnat_main_db_entry_t *db = NULL; - icmp_em_ip_info icmp_info; - - - if (PREDICT_TRUE(db_index != EMPTY)) { - - icmp_info.em_ip = em_ip; - icmp_info.icmp = icmp; - - /* Note: This could have been done in stage1 itself, - * but we need to introduce one u16 * in vnet_buffer_opaque_t - * Since this flow is expected to be very rare in actual - * deployment scenario, we may afford to do these steps here - * as well. Lets confirm during core review. */ - - if (em_ip->protocol == TCP_PROT) { - tcp_hdr_type *tcp = (tcp_hdr_type*)((u8 *)em_ip + em_ip_hdr_len); - icmp_info.em_port = &(tcp->src_port); - } else if (em_ip->protocol == UDP_PROT) { - udp_hdr_type_t *udp = (udp_hdr_type_t *) - ((u8 *)em_ip + em_ip_hdr_len); - icmp_info.em_port = &(udp->src_port); - } else { - icmp_v4_t *icmp_inner = (icmp_v4_t*)((u8 *)em_ip + em_ip_hdr_len); - icmp_info.em_port = &(icmp_inner->identifier); - } - - db = cnat_main_db + db_index; - - if (PREDICT_FALSE(icmp_debug_flag)) { - printf("\nDUMPING ICMP PKT BEFORE\n"); - print_icmp_pkt(ip); - } - - if (PLATFORM_HANDLE_TTL_DECREMENT) { - /* - * Decrement TTL and update IPv4 checksum - */ - ipv4_decr_ttl_n_calc_csum(ip); - } - - swap_ip_dst_emip_src(ip, &icmp_info, - db, db->in2out_key.k.vrf); - - if (PREDICT_FALSE(icmp_debug_flag)) { - printf("\nDUMPING ICMP PKT AFTER\n"); - print_icmp_pkt(ip); - } - - } else { - disposition = CNAT_V4_ICMP_E_O2I_D; - counter = CNAT_V4_ICMP_E_O2I_D_PKT; - } - - em->counters[node_counter_base_index + counter] += 1; - return disposition; -} - -#include - -static uword cnat_ipv4_icmp_e_outside_input_node_fn (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return dispatch_pipeline (vm, node, frame); -} - - -VLIB_REGISTER_NODE (cnat_ipv4_icmp_e_outside_input_node) = { - .function = cnat_ipv4_icmp_e_outside_input_node_fn, - .name = "vcgn-v4-icmp-e-o2i", - .vector_size = sizeof (u32), - .type = VLIB_NODE_TYPE_INTERNAL, - - .n_errors = ARRAY_LEN(cnat_ipv4_icmp_e_outside_input_error_strings), - .error_strings = cnat_ipv4_icmp_e_outside_input_error_strings, - - .n_next_nodes = CNAT_V4_ICMP_E_O2I_NEXT, - - /* edit / add dispositions here */ - .next_nodes = { - [CNAT_V4_ICMP_E_O2I_T] = "ip4-input", - [CNAT_V4_ICMP_E_O2I_D] = "error-drop", - }, -}; - -clib_error_t *cnat_ipv4_icmp_e_outside_input_init (vlib_main_t *vm) -{ - cnat_ipv4_icmp_e_outside_input_main_t * mp = &cnat_ipv4_icmp_e_outside_input_main; - - mp->vlib_main = vm; - mp->vnet_main = vnet_get_main(); - - return 0; -} - -VLIB_INIT_FUNCTION (cnat_ipv4_icmp_e_outside_input_init); diff --git a/plugins/plugins/vcgn/cnat_ipv4_icmp_query_inside_input.c b/plugins/plugins/vcgn/cnat_ipv4_icmp_query_inside_input.c deleted file mode 100644 index 1b9f0266..00000000 --- a/plugins/plugins/vcgn/cnat_ipv4_icmp_query_inside_input.c +++ /dev/null @@ -1,404 +0,0 @@ -/* - *--------------------------------------------------------------------------- - * cnat_ipv4_icmp_query_inside_input.c - cnat_ipv4_icmp_query_inside_input node pipeline stage functions - * - * - * Copyright (c) 2008-2014 Cisco and/or its affiliates. - * 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 -#include -#include -#include - -#include "cnat_ipv4_icmp.h" - -#define foreach_cnat_ipv4_icmp_q_inside_input_error \ -_(CNAT_V4_ICMP_Q_I2O_T_PKT, "cnat v4 icmp_q i2o packet transmit") \ -_(CNAT_V4_ICMP_Q_I2O_MISS_PKT, "cnat v4 icmp_q i2o db miss") \ -_(CNAT_V4_ICMP_Q_I2O_TTL_GEN, "cnat v4 icmp_q i2o ttl generate") \ -_(CNAT_V4_ICMP_Q_I2O_TTL_DROP, "cnat v4 icmp_q i2o ttl drop") \ -_(CNAT_V4_ICMP_Q_I2O_NO_SESSION_DROP, "cnat v4 icmp_q i2o no session drop") - -typedef enum { -#define _(sym,str) sym, - foreach_cnat_ipv4_icmp_q_inside_input_error -#undef _ - CNAT_IPV4_ICMP_Q_INSIDE_INPUT_N_ERROR, -} cnat_ipv4_icmp_q_inside_input_t; - -static char * cnat_ipv4_icmp_q_inside_input_error_strings[] = { -#define _(sym,string) string, - foreach_cnat_ipv4_icmp_q_inside_input_error -#undef _ -}; - -typedef struct { - u32 cached_next_index; - /* $$$$ add data here */ - - /* convenience variables */ - vlib_main_t * vlib_main; - vnet_main_t * vnet_main; -} cnat_ipv4_icmp_q_inside_input_main_t; - -typedef enum { - CNAT_V4_ICMP_Q_I2O_T, - CNAT_V4_ICMP_Q_I2O_E, - CNAT_V4_ICMP_Q_I2O_D, - CNAT_V4_ICMP_Q_I2O_NEXT, -} cnat_ipv4_icmp_q_inside_input_next_t; - -cnat_ipv4_icmp_q_inside_input_main_t cnat_ipv4_icmp_q_inside_input_main; -vlib_node_registration_t cnat_ipv4_icmp_q_inside_input_node; - -#define NSTAGES 5 - -inline void swap_ip_src_icmp_id(ipv4_header *ip, - icmp_v4_t *icmp, - cnat_main_db_entry_t *db, u16 vrf) -{ -#if 0 - u32 postmap_ip; - u8 direction; - u32 old_ip; - u32 old_postmap_ip; - - - if(is_static_dest_nat_enabled(vrf) == CNAT_SUCCESS) { - direction = 0; - if(cnat_static_dest_db_get_translation(ip->dest_addr, &postmap_ip, vrf, direction) == CNAT_SUCCESS) { - CNAT_UPDATE_L3_CHECKSUM_DECLARE - - old_ip = spp_net_to_host_byte_order_32(&(ip->dest_addr)); - old_postmap_ip = spp_net_to_host_byte_order_32(&postmap_ip); - - CNAT_UPDATE_L3_CHECKSUM(((u16)(old_ip & 0xFFFF)), - ((u16)(old_ip >> 16)), - (spp_net_to_host_byte_order_16(&(ip->checksum))), - ((u16)(old_postmap_ip & 0xFFFF)), - ((u16)(old_postmap_ip >> 16))) - ip->dest_addr = postmap_ip; - - ip->checksum = - spp_host_to_net_byte_order_16(new_l3_c); - } - } -#endif /* if 0 */ - /* - * declare variable - */ - CNAT_UPDATE_L3_L4_CHECKSUM_DECLARE - /* - * calculate checksum - */ - CNAT_UPDATE_L3_ICMP_CHECKSUM(((u16)(db->in2out_key.k.ipv4)), - ((u16)(db->in2out_key.k.ipv4 >> 16)), - (db->in2out_key.k.port), - (clib_net_to_host_u16(ip->checksum)), - (clib_net_to_host_u16(icmp->checksum)), - ((u16)(db->out2in_key.k.ipv4)), - ((u16)(db->out2in_key.k.ipv4 >> 16)), - (db->out2in_key.k.port)) - //set ip header - ip->src_addr = - clib_host_to_net_u32(db->out2in_key.k.ipv4); - ip->checksum = - clib_host_to_net_u16(new_l3_c); - - //set icmp header - icmp->identifier = - clib_host_to_net_u16(db->out2in_key.k.port); - icmp->checksum = - clib_host_to_net_u16(new_l4_c); -} - -/* - * Use the generic buffer metadata + first line of packet data prefetch - * stage function from . This is usually a Good Idea. - */ -#define stage0 generic_stage0 - -static inline void -stage1(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) -{ - u64 a, b, c; - u32 bucket; - u8 *prefetch_target; - - vlib_buffer_t * b0 = vlib_get_buffer (vm, buffer_index); - ipv4_header *ip = vlib_buffer_get_current (b0); - u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; - icmp_v4_t *icmp = (icmp_v4_t *)((u8*)ip + ipv4_hdr_len); - - u64 tmp = 0; - tmp = vnet_buffer(b0)->vcgn_uii.key.k.ipv4 = - clib_net_to_host_u32(ip->src_addr); - vnet_buffer(b0)->vcgn_uii.key.k.port = - clib_net_to_host_u16 (icmp->identifier); - - tmp |= ((u64)vnet_buffer(b0)->vcgn_uii.key.k.port) << 32; - - PLATFORM_CNAT_SET_RX_VRF(vnet_buffer(b0)->sw_if_index[VLIB_RX], - vnet_buffer(b0)->vcgn_uii.key.k.vrf, - CNAT_ICMP) - tmp |= ((u64)vnet_buffer(b0)->vcgn_uii.key.k.vrf) << 48; - - CNAT_V4_GET_HASH(tmp, bucket, CNAT_MAIN_HASH_MASK) - - prefetch_target = (u8 *)(&cnat_in2out_hash[bucket]); - vnet_buffer(b0)->vcgn_uii.bucket = bucket; - - /* Prefetch the hash bucket */ - CLIB_PREFETCH(prefetch_target, CLIB_CACHE_LINE_BYTES, LOAD); -} - -#define SPP_LOG2_CACHE_LINE_BYTES 6 -#define SPP_CACHE_LINE_BYTES (1 << SPP_LOG2_CACHE_LINE_BYTES) - -static inline void -stage2(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) -{ - vlib_buffer_t * b0 = vlib_get_buffer(vm, buffer_index); - uword prefetch_target0, prefetch_target1; - u32 bucket = vnet_buffer(b0)->vcgn_uii.bucket; - - /* read the hash bucket */ - u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket - = cnat_in2out_hash[bucket].next; - - if (PREDICT_TRUE(db_index != EMPTY)) { - /* - * Prefetch database keys. We save space by not cache-line - * aligning the DB entries. We don't want to waste LSU - * bandwidth prefetching stuff we won't need. - */ - prefetch_target0 = (uword)(cnat_main_db + db_index); - CLIB_PREFETCH((void*)prefetch_target0, CLIB_CACHE_LINE_BYTES, LOAD); - /* Just beyond DB key #2 */ - prefetch_target1 = prefetch_target0 + - STRUCT_OFFSET_OF(cnat_main_db_entry_t, user_ports); - /* If the targets are in different lines, do the second prefetch */ - if (PREDICT_FALSE((prefetch_target0 & ~(SPP_CACHE_LINE_BYTES-1)) != - (prefetch_target1 & ~(SPP_CACHE_LINE_BYTES-1)))) { - CLIB_PREFETCH((void *)prefetch_target1, CLIB_CACHE_LINE_BYTES, LOAD); - } - } -} - -static inline void -stage3(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) -{ - cnat_main_db_entry_t *db; - vlib_buffer_t * b0 = vlib_get_buffer(vm, buffer_index); - u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket; - - /* - * Note: if the search already failed (empty bucket), - * the answer is already in the pipeline context structure - */ - if (PREDICT_TRUE(db_index != EMPTY)) { - - /* - * Note: hash collisions suck. We can't easily prefetch around them. - * The first trip around the track will be fast. After that, maybe - * not so much... - */ - do { - db = cnat_main_db + db_index; - if (PREDICT_TRUE(db->in2out_key.key64 == - vnet_buffer(b0)->vcgn_uii.key.key64)) { - break; - } - db_index = db->in2out_hash.next; - } while (db_index != EMPTY); - - /* Stick the answer back into the pipeline context structure */ - vnet_buffer(b0)->vcgn_uii.bucket = db_index; - } -} - -static inline u32 last_stage (vlib_main_t *vm, vlib_node_runtime_t *node, - u32 bi) -{ - vlib_buffer_t *b0 = vlib_get_buffer (vm, bi); - u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket; - spp_ctx_t *ctx = (spp_ctx_t *) &vnet_buffer(b0)->vcgn_uii; - int disposition = CNAT_V4_ICMP_Q_I2O_T; - int counter = CNAT_V4_ICMP_Q_I2O_T_PKT; - - ipv4_header *ip = (ipv4_header *)vlib_buffer_get_current(b0); - u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; - icmp_v4_t *icmp = (icmp_v4_t *)((u8*)ip + ipv4_hdr_len); - vlib_node_t *n = vlib_get_node (vm, cnat_ipv4_icmp_q_inside_input_node.index); - u32 node_counter_base_index = n->error_heap_index; - vlib_error_main_t * em = &vm->error_main; - cnat_session_entry_t *session_db = NULL; - cnat_main_db_entry_t *db = NULL; - cnat_key_t dest_info; - - if (PLATFORM_HANDLE_TTL_DECREMENT) { - if (PREDICT_FALSE(ip->ttl <= 1)) { - /* Try to generate ICMP error msg, as TTL is <= 1 */ - - if (icmpv4_generate_with_throttling - (ctx, ip, ctx->ru.rx.uidb_index)) { - - /* Generated ICMP */ - disposition = CNAT_V4_ICMP_Q_I2O_T; - counter = CNAT_V4_ICMP_Q_I2O_TTL_GEN; - } else { - /* Could not generated ICMP - drop the packet */ - disposition = CNAT_V4_ICMP_Q_I2O_D; - counter = CNAT_V4_ICMP_Q_I2O_TTL_DROP; - } - goto drop_pkt; - } - } - - if (PREDICT_TRUE(db_index != EMPTY)) { - db = cnat_main_db + db_index; - dest_info.k.port = 0; - dest_info.k.ipv4 = clib_net_to_host_u32(ip->dest_addr); - - if(PREDICT_TRUE(!PLATFORM_DBL_SUPPORT)) { - - /* No DBL support, so just update the destn and proceed */ - db->dst_ipv4 = dest_info.k.ipv4; - db->dst_port = dest_info.k.port; - goto update_pkt; - } - - if(PREDICT_FALSE(db->dst_ipv4 != dest_info.k.ipv4)) { - if(PREDICT_TRUE(db->nsessions == 1)) { - /* Handle one to 2 dest scenarion */ - dest_info.k.vrf = db->in2out_key.k.vrf; - session_db = cnat_handle_1to2_session(db, &dest_info); - - if(PREDICT_FALSE(session_db == NULL)) { - disposition = CNAT_V4_ICMP_Q_I2O_D; - counter = CNAT_V4_ICMP_Q_I2O_NO_SESSION_DROP; - goto drop_pkt; - } - } else if (PREDICT_FALSE(db->nsessions == 0)) { - /* Should be a static entry - * Note this session as the first session and log - */ - cnat_add_dest_n_log(db, &dest_info); - } else { /* Many translations exist already */ - dest_info.k.vrf = db->in2out_key.k.vrf; - /* If session already exists, - * cnat_create_session_db_entry will return the existing db - * else create a new db - * If could not create, return NULL - */ - session_db = cnat_create_session_db_entry(&dest_info, - db, TRUE); - - if(PREDICT_FALSE(session_db == NULL)) { - disposition = CNAT_V4_ICMP_Q_I2O_D; - counter = CNAT_V4_ICMP_Q_I2O_NO_SESSION_DROP; - goto drop_pkt; - } - } - } - -update_pkt: - - if (PREDICT_FALSE(icmp_debug_flag)) { - printf("\nDUMPING ICMP PKT BEFORE\n"); - print_icmp_pkt(ip); - } - - if (PLATFORM_HANDLE_TTL_DECREMENT) { - /* - * Decrement TTL and update IPv4 checksum - */ - ipv4_decr_ttl_n_calc_csum(ip); - } - - /* - * 1. update src ipv4 addr and src icmp identifier - * 2. update ipv4 checksum and icmp checksum - */ - swap_ip_src_icmp_id(ip, icmp, db, db->in2out_key.k.vrf); - - if (PREDICT_FALSE(icmp_debug_flag)) { - printf("\nDUMPING ICMP PKT AFTER\n"); - print_icmp_pkt(ip); - } - - /* - * update db counter, timer - */ - - if(PREDICT_FALSE(session_db != 0)) { - CNAT_DB_TIMEOUT_RST(session_db); - } else { - CNAT_DB_TIMEOUT_RST(db); - } - db->in2out_pkts++; - in2out_forwarding_count++; - - } else { - disposition = CNAT_V4_ICMP_Q_I2O_E; - counter = CNAT_V4_ICMP_Q_I2O_MISS_PKT; - } - -drop_pkt: - - em->counters[node_counter_base_index + counter] += 1; - return disposition; -} - -#include - -static uword cnat_ipv4_icmp_q_inside_input_node_fn (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return dispatch_pipeline (vm, node, frame); -} - - -VLIB_REGISTER_NODE (cnat_ipv4_icmp_q_inside_input_node) = { - .function = cnat_ipv4_icmp_q_inside_input_node_fn, - .name = "vcgn-v4-icmp-q-i2o", - .vector_size = sizeof (u32), - .type = VLIB_NODE_TYPE_INTERNAL, - - .n_errors = ARRAY_LEN(cnat_ipv4_icmp_q_inside_input_error_strings), - .error_strings = cnat_ipv4_icmp_q_inside_input_error_strings, - - .n_next_nodes = CNAT_V4_ICMP_Q_I2O_NEXT, - - /* edit / add dispositions here */ - .next_nodes = { - [CNAT_V4_ICMP_Q_I2O_E] = "vcgn-v4-icmp-q-i2o-e", - [CNAT_V4_ICMP_Q_I2O_T] = "ip4-input", - [CNAT_V4_ICMP_Q_I2O_D] = "error-drop", - }, -}; - -clib_error_t *cnat_ipv4_icmp_q_inside_input_init (vlib_main_t *vm) -{ - cnat_ipv4_icmp_q_inside_input_main_t * mp = &cnat_ipv4_icmp_q_inside_input_main; - - mp->vlib_main = vm; - mp->vnet_main = vnet_get_main(); - - return 0; -} - -VLIB_INIT_FUNCTION (cnat_ipv4_icmp_q_inside_input_init); diff --git a/plugins/plugins/vcgn/cnat_ipv4_icmp_query_inside_input_exception.c b/plugins/plugins/vcgn/cnat_ipv4_icmp_query_inside_input_exception.c deleted file mode 100644 index 9b5e280e..00000000 --- a/plugins/plugins/vcgn/cnat_ipv4_icmp_query_inside_input_exception.c +++ /dev/null @@ -1,235 +0,0 @@ -/* - *--------------------------------------------------------------------------- - * cnat_ipv4_icmp_query_inside_input_exception.c - cnat_ipv4_icmp_query_inside_input_exception node pipeline stage functions - * - * Copyright (c) 2008-2014 Cisco and/or its affiliates. - * 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 -#include -#include -#include - -#include "cnat_ipv4_icmp.h" - -#define foreach_cnat_ipv4_icmp_q_inside_input_exc_error \ -_(CNAT_V4_ICMP_Q_I2O_E_T_PKT, "v4 icmp query i2o-e transmit") \ -_(CNAT_V4_ICMP_Q_I2O_E_G_PKT, "v4 icmp query i2o-e gen icmp msg") \ -_(CNAT_V4_ICMP_Q_I2O_E_D_PKT, "v4 icmp query i2o-e pkt drop") \ -_(CNAT_V4_ICMP_Q_I2O_E_DC_PKT, "v4 icmp query i2o-e drop (no config)") \ -_(CNAT_V4_ICMP_Q_I2O_E_DR_PKT, "v4 icmp query i2o-e drop (not in run state)") \ -_(CNAT_V4_ICMP_Q_I2O_E_DD_PKT, "v4 icmp query i2o-e drop (no direct port)") \ -_(CNAT_V4_ICMP_Q_I2O_E_DA_PKT, "v4 icmp query i2o-e drop (no any port)") \ -_(CNAT_V4_ICMP_Q_I2O_E_DO_PKT, "v4 icmp query i2o-e drop (out of port limit)") \ -_(CNAT_V4_ICMP_Q_I2O_E_DS_PKT, "v4 icmp query i2o_e drop (out of session db)") - -typedef enum { -#define _(sym,str) sym, - foreach_cnat_ipv4_icmp_q_inside_input_exc_error -#undef _ - CNAT_IPV4_ICMP_Q_INSIDE_INPUT_EXCEPTIONS_N_ERROR, -} cnat_ipv4_icmp_q_inside_input_exc_error_t; - - -static char * cnat_ipv4_icmp_q_inside_input_exc_error_strings[] = { -#define _(sym,string) string, - foreach_cnat_ipv4_icmp_q_inside_input_exc_error -#undef _ -}; - -typedef struct { - u32 cached_next_index; - /* $$$$ add data here */ - - /* convenience variables */ - vlib_main_t * vlib_main; - vnet_main_t * vnet_main; -} cnat_ipv4_icmp_q_inside_input_exc_main_t; - -typedef enum { - CNAT_V4_ICMP_Q_E_I2O_T, - //CNAT_V4_ICMP_Q_E_I2O_GEN, - CNAT_V4_ICMP_Q_E_I2O_D, - CNAT_V4_ICMP_Q_E_I2O_NEXT, -} cnat_ipv4_icmp_q_inside_input_exc_next_t; - -#define CNAT_V4_ICMP_Q_E_I2O_GEN CNAT_V4_ICMP_Q_E_I2O_T - -cnat_ipv4_icmp_q_inside_input_exc_main_t cnat_ipv4_icmp_q_inside_input_exc_main; -vlib_node_registration_t cnat_ipv4_icmp_q_inside_input_exc_node; - -#define NSTAGES 2 - -/* - * Use the generic buffer metadata + first line of packet data prefetch - * stage function from . This is usually a Good Idea. - */ -#define stage0 generic_stage0 - -static inline u32 last_stage (vlib_main_t *vm, vlib_node_runtime_t *node, - u32 bi) -{ - vlib_buffer_t *b0 = vlib_get_buffer (vm, bi); - int disposition = CNAT_V4_ICMP_Q_E_I2O_T; - int counter = CNAT_V4_ICMP_Q_I2O_E_T_PKT; - - ipv4_header *ip = (ipv4_header *)vlib_buffer_get_current(b0); - u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; - icmp_v4_t *icmp = (icmp_v4_t *)((u8*)ip + ipv4_hdr_len); - vlib_node_t *n = vlib_get_node (vm, cnat_ipv4_icmp_q_inside_input_exc_node.index); - u32 node_counter_base_index = n->error_heap_index; - vlib_error_main_t * em = &vm->error_main; - - cnat_key_t dest_info; - cnat_gen_icmp_info info; - cnat_db_key_bucket_t ki; - cnat_main_db_entry_t *db = NULL; - - PLATFORM_CNAT_SET_RX_VRF(vnet_buffer(b0)->sw_if_index[VLIB_RX], - ki.k.k.vrf, CNAT_ICMP) - - ki.k.k.ipv4 = - clib_net_to_host_u32(ip->src_addr); - ki.k.k.port = - clib_net_to_host_u16(icmp->identifier); - - dest_info.k.port = 0; - dest_info.k.ipv4 = clib_net_to_host_u32(ip->dest_addr); - PLATFORM_CNAT_SET_RX_VRF(vnet_buffer(b0)->sw_if_index[VLIB_RX], - dest_info.k.vrf, CNAT_ICMP) - - db = cnat_get_main_db_entry_v2(&ki, PORT_SINGLE, PORT_TYPE_DYNAMIC, - &info, &dest_info); - if (PREDICT_TRUE(db != 0)) { - - if (PREDICT_FALSE(icmp_debug_flag)) { - printf("\nDUMPING ICMP PKT BEFORE\n"); - print_icmp_pkt(ip); - } - - if (PLATFORM_HANDLE_TTL_DECREMENT) { - /* - * Decrement TTL and update IPv4 checksum - */ - ipv4_decr_ttl_n_calc_csum(ip); - } - - /* - * step 6 do nat before fwd pkt - */ - swap_ip_src_icmp_id(ip, icmp, db, db->in2out_key.k.vrf); - - if (PREDICT_FALSE(icmp_debug_flag)) { - printf("\nDUMPING ICMP PKT AFTER\n"); - print_icmp_pkt(ip); - } - - /* - * update db for this pkt - */ - CNAT_DB_UPDATE_IN2OUT_TIMER - in2out_forwarding_count++; - - } else { - switch (info.error) { - case (CNAT_NO_VRF_RUN): - counter = CNAT_V4_ICMP_Q_I2O_E_DR_PKT; - break; - case (CNAT_OUT_LIMIT): - counter = CNAT_V4_ICMP_Q_I2O_E_DO_PKT; - break; - case (CNAT_NO_PORT_ANY): - case (CNAT_NO_POOL_ANY): - case (CNAT_BAD_INUSE_ANY): - case (CNAT_NOT_FOUND_ANY): - counter = CNAT_V4_ICMP_Q_I2O_E_DA_PKT; - break; - case (CNAT_INV_PORT_DIRECT): - case (CNAT_DEL_PORT_DIRECT): - case (CNAT_BAD_INUSE_DIRECT): - case (CNAT_NOT_FOUND_DIRECT): - counter = CNAT_V4_ICMP_Q_I2O_E_DD_PKT; - break; - case (CNAT_ERR_NO_SESSION_DB): - counter = CNAT_V4_ICMP_Q_I2O_E_DS_PKT; - break; - default: - counter = CNAT_V4_ICMP_Q_I2O_E_DC_PKT; - break; - } - /* - * send to icmp msg generate node - */ - if (info.gen_icmp_msg == CNAT_ICMP_MSG) { - #if 0 - u32 *fd = (u32*)ctx->feature_data; - fd[0] = info.svi_addr; - fd[1] = CNAT_ICMP_DEST_UNREACHABLE; - #endif - disposition = CNAT_V4_ICMP_Q_E_I2O_GEN; - counter = CNAT_V4_ICMP_Q_I2O_E_G_PKT; - } else { - disposition = CNAT_V4_ICMP_Q_E_I2O_D; - counter = CNAT_V4_ICMP_Q_I2O_E_D_PKT; - } - DEBUG_I2O_DROP(CNAT_DEBUG_DROP_ICMP) - } - - em->counters[node_counter_base_index + counter] += 1; - - return disposition; -} - -#include - -static uword cnat_ipv4_icmp_q_inside_input_exc_node_fn (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return dispatch_pipeline (vm, node, frame); -} - -VLIB_REGISTER_NODE (cnat_ipv4_icmp_q_inside_input_exc_node) = { - .function = cnat_ipv4_icmp_q_inside_input_exc_node_fn, - .name = "vcgn-v4-icmp-q-i2o-e", - .vector_size = sizeof (u32), - .type = VLIB_NODE_TYPE_INTERNAL, - - .n_errors = ARRAY_LEN(cnat_ipv4_icmp_q_inside_input_exc_error_strings), - .error_strings = cnat_ipv4_icmp_q_inside_input_exc_error_strings, - - .n_next_nodes = CNAT_V4_ICMP_Q_E_I2O_NEXT, - - /* edit / add dispositions here */ - .next_nodes = { - //[CNAT_V4_ICMP_Q_E_I2O_GEN] = "icmp_msg_gen", /* Currently it will go - //to ip4-input node. We have to port icmp msg generator node */ - [CNAT_V4_ICMP_Q_E_I2O_T] = "ip4-input", - [CNAT_V4_ICMP_Q_E_I2O_D] = "error-drop", - }, -}; - - -clib_error_t *cnat_ipv4_icmp_q_inside_input_exc_init (vlib_main_t *vm) -{ - cnat_ipv4_icmp_q_inside_input_exc_main_t * mp = &cnat_ipv4_icmp_q_inside_input_exc_main; - - mp->vlib_main = vm; - mp->vnet_main = vnet_get_main(); - - return 0; -} - -VLIB_INIT_FUNCTION (cnat_ipv4_icmp_q_inside_input_exc_init); diff --git a/plugins/plugins/vcgn/cnat_ipv4_icmp_query_outside_input.c b/plugins/plugins/vcgn/cnat_ipv4_icmp_query_outside_input.c deleted file mode 100644 index 2c05e0b4..00000000 --- a/plugins/plugins/vcgn/cnat_ipv4_icmp_query_outside_input.c +++ /dev/null @@ -1,381 +0,0 @@ -/* - *--------------------------------------------------------------------------- - * cnat_ipv4_icmp_query_outside_input.c - cnat_ipv4_icmp_query_outside_input node pipeline stage functions - * - * - * Copyright (c) 2008-2014 Cisco and/or its affiliates. - * 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 -#include -#include -#include - -#include "cnat_ipv4_icmp.h" - -#define foreach_cnat_ipv4_icmp_q_outside_input_error \ -_(CNAT_V4_ICMP_Q_O2I_T_PKT, "cnat v4 icmp_q o2i packet transmit") \ -_(CNAT_V4_ICMP_Q_O2I_MISS_PKT, "cnat v4 icmp_q o2i drop") \ -_(CNAT_V4_ICMP_Q_O2I_TTL_GEN, "cnat v4 icmp_q o2i ttl generate") \ -_(CNAT_V4_ICMP_Q_O2I_TTL_DROP, "cnat v4 icmp_q o2i ttl drop") \ -_(CNAT_V4_ICMP_Q_O2I_NO_SESSION_DROP, "cnat v4 icmp_q o2i no session drop") - -typedef enum { -#define _(sym,str) sym, - foreach_cnat_ipv4_icmp_q_outside_input_error -#undef _ - CNAT_IPV4_ICMP_Q_OUTSIDE_INPUT_N_ERROR, -} cnat_ipv4_icmp_q_outside_input_t; - -static char * cnat_ipv4_icmp_q_outside_input_error_strings[] = { -#define _(sym,string) string, - foreach_cnat_ipv4_icmp_q_outside_input_error -#undef _ -}; - -typedef struct { - u32 cached_next_index; - /* $$$$ add data here */ - - /* convenience variables */ - vlib_main_t * vlib_main; - vnet_main_t * vnet_main; -} cnat_ipv4_icmp_q_outside_input_main_t; - -typedef enum { - CNAT_V4_ICMP_Q_O2I_T, - CNAT_V4_ICMP_Q_O2I_D, - CNAT_V4_ICMP_Q_O2I_NEXT, -} cnat_ipv4_icmp_q_outside_input_next_t; - -cnat_ipv4_icmp_q_outside_input_main_t cnat_ipv4_icmp_q_outside_input_main; -vlib_node_registration_t cnat_ipv4_icmp_q_outside_input_node; - -#define NSTAGES 5 - -inline void swap_ip_dst_icmp_id(ipv4_header *ip, - icmp_v4_t *icmp, - cnat_main_db_entry_t *db, u16 vrf) -{ -#if 0 - u32 postmap_ip; - u8 direction; - u32 old_ip; - u32 old_postmap_ip; - - if(is_static_dest_nat_enabled(vrf) == CNAT_SUCCESS) { - direction = 1; - if(cnat_static_dest_db_get_translation(ip->src_addr, &postmap_ip, vrf, direction) == CNAT_SUCCESS) { - CNAT_UPDATE_L3_CHECKSUM_DECLARE - - old_ip = spp_net_to_host_byte_order_32(&(ip->src_addr)); - old_postmap_ip = spp_net_to_host_byte_order_32(&postmap_ip); - - CNAT_UPDATE_L3_CHECKSUM(((u16)(old_ip & 0xFFFF)), - ((u16)(old_ip >> 16)), - (spp_net_to_host_byte_order_16(&(ip->checksum))), - ((u16)(old_postmap_ip & 0xFFFF)), - ((u16)(old_postmap_ip >> 16))) - ip->checksum = - spp_host_to_net_byte_order_16(new_l3_c); - ip->src_addr = postmap_ip; - } - } -#endif /* if 0 */ - /* - * declare variable - */ - CNAT_UPDATE_L3_L4_CHECKSUM_DECLARE - /* - * calculate checksum - */ - CNAT_UPDATE_L3_ICMP_CHECKSUM(((u16)(db->out2in_key.k.ipv4)), - ((u16)(db->out2in_key.k.ipv4 >> 16)), - (db->out2in_key.k.port), - (clib_net_to_host_u16(ip->checksum)), - (clib_net_to_host_u16(icmp->checksum)), - ((u16)(db->in2out_key.k.ipv4)), - ((u16)(db->in2out_key.k.ipv4 >> 16)), - (db->in2out_key.k.port)) - //set ip header - ip->dest_addr = - clib_host_to_net_u32(db->in2out_key.k.ipv4); - ip->checksum = - clib_host_to_net_u16(new_l3_c); - - //set icmp header - icmp->identifier = - clib_host_to_net_u16(db->in2out_key.k.port); - icmp->checksum = - clib_host_to_net_u16(new_l4_c); -} - -/* - * Use the generic buffer metadata + first line of packet data prefetch - * stage function from . This is usually a Good Idea. - */ -#define stage0 generic_stage0 - -static inline void -stage1(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) -{ - u64 a, b, c; - u32 bucket; - u8 *prefetch_target; - - vlib_buffer_t * b0 = vlib_get_buffer (vm, buffer_index); - ipv4_header *ip = vlib_buffer_get_current (b0); - u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; - icmp_v4_t *icmp = (icmp_v4_t *)((u8*)ip + ipv4_hdr_len); - - u64 tmp = 0; - tmp = vnet_buffer(b0)->vcgn_uii.key.k.ipv4 = - clib_net_to_host_u32(ip->dest_addr); - vnet_buffer(b0)->vcgn_uii.key.k.port = - clib_net_to_host_u16 (icmp->identifier); - - tmp |= ((u64)vnet_buffer(b0)->vcgn_uii.key.k.port) << 32; - - PLATFORM_CNAT_SET_RX_VRF(vnet_buffer(b0)->sw_if_index[VLIB_RX], - vnet_buffer(b0)->vcgn_uii.key.k.vrf, - CNAT_ICMP) - tmp |= ((u64)vnet_buffer(b0)->vcgn_uii.key.k.vrf) << 48; - - CNAT_V4_GET_HASH(tmp, bucket, CNAT_MAIN_HASH_MASK) - - prefetch_target = (u8 *)(&cnat_out2in_hash[bucket]); - vnet_buffer(b0)->vcgn_uii.bucket = bucket; - - /* Prefetch the hash bucket */ - CLIB_PREFETCH(prefetch_target, CLIB_CACHE_LINE_BYTES, LOAD); -} - -#define SPP_LOG2_CACHE_LINE_BYTES 6 -#define SPP_CACHE_LINE_BYTES (1 << SPP_LOG2_CACHE_LINE_BYTES) - -static inline void -stage2(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) -{ - vlib_buffer_t * b0 = vlib_get_buffer(vm, buffer_index); - uword prefetch_target0, prefetch_target1; - u32 bucket = vnet_buffer(b0)->vcgn_uii.bucket; - - /* read the hash bucket */ - u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket - = cnat_out2in_hash[bucket].next; - - if (PREDICT_TRUE(db_index != EMPTY)) { - /* - * Prefetch database keys. We save space by not cache-line - * aligning the DB entries. We don't want to waste LSU - * bandwidth prefetching stuff we won't need. - */ - prefetch_target0 = (uword)(cnat_main_db + db_index); - CLIB_PREFETCH((void*)prefetch_target0, CLIB_CACHE_LINE_BYTES, LOAD); - /* Just beyond DB key #2 */ - prefetch_target1 = prefetch_target0 + - STRUCT_OFFSET_OF(cnat_main_db_entry_t, user_ports); - /* If the targets are in different lines, do the second prefetch */ - if (PREDICT_FALSE((prefetch_target0 & ~(SPP_CACHE_LINE_BYTES-1)) != - (prefetch_target1 & ~(SPP_CACHE_LINE_BYTES-1)))) { - CLIB_PREFETCH((void *)prefetch_target1, CLIB_CACHE_LINE_BYTES, LOAD); - } - } -} - -static inline void -stage3(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) -{ - cnat_main_db_entry_t *db; - vlib_buffer_t * b0 = vlib_get_buffer(vm, buffer_index); - u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket; - - /* - * Note: if the search already failed (empty bucket), - * the answer is already in the pipeline context structure - */ - if (PREDICT_TRUE(db_index != EMPTY)) { - - /* - * Note: hash collisions suck. We can't easily prefetch around them. - * The first trip around the track will be fast. After that, maybe - * not so much... - */ - do { - db = cnat_main_db + db_index; - if (PREDICT_TRUE(db->out2in_key.key64 == - vnet_buffer(b0)->vcgn_uii.key.key64)) { - break; - } - db_index = db->out2in_hash.next; - } while (db_index != EMPTY); - - /* Stick the answer back into the pipeline context structure */ - vnet_buffer(b0)->vcgn_uii.bucket = db_index; - } -} - - -static inline u32 last_stage (vlib_main_t *vm, vlib_node_runtime_t *node, - u32 bi) -{ - - vlib_buffer_t *b0 = vlib_get_buffer (vm, bi); - u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket; - int disposition = CNAT_V4_ICMP_Q_O2I_T; - int counter = CNAT_V4_ICMP_Q_O2I_T_PKT; - - ipv4_header *ip = (ipv4_header *)vlib_buffer_get_current(b0); - u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; - icmp_v4_t *icmp = (icmp_v4_t *)((u8*)ip + ipv4_hdr_len); - vlib_node_t *n = vlib_get_node (vm, cnat_ipv4_icmp_q_outside_input_node.index); - u32 node_counter_base_index = n->error_heap_index; - vlib_error_main_t * em = &vm->error_main; - cnat_session_entry_t *session_db = NULL; - cnat_main_db_entry_t *db = NULL; - cnat_key_t dest_info; - cnat_vrfmap_t * vrf_map_p __attribute__((unused)) = NULL; - u32 vrf_index __attribute__((unused)) = 0; - - if (PREDICT_TRUE(db_index != EMPTY)) { - - db = cnat_main_db + db_index; - dest_info.k.port = 0; - dest_info.k.ipv4 = clib_net_to_host_u32(ip->src_addr); - - if (PREDICT_FALSE(icmp_debug_flag)) { - printf("\nDUMPING ICMP PKT BEFORE\n"); - print_icmp_pkt(ip); - } - - vrf_map_p = cnat_map_by_vrf + db->vrfmap_index; - vrf_index = (db->in2out_key.k.vrf & CNAT_VRF_MASK); - - if(PREDICT_TRUE(!PLATFORM_DBL_SUPPORT)) { - - /* No DBL support, so just update the destn and proceed */ - db->dst_ipv4 = dest_info.k.ipv4; - db->dst_port = dest_info.k.port; - goto update_pkt; - } - - if(PREDICT_FALSE(db->dst_ipv4 != dest_info.k.ipv4)) { - - if(PREDICT_TRUE(db->nsessions == 1)) { - /* Handle one to 2 dest scenarion */ - dest_info.k.vrf = db->in2out_key.k.vrf; - session_db = cnat_handle_1to2_session(db, &dest_info); - - if(PREDICT_FALSE(session_db == NULL)) { - disposition = CNAT_V4_ICMP_Q_O2I_D; - counter = CNAT_V4_ICMP_Q_O2I_NO_SESSION_DROP; - goto drop_pkt; - } - } else if (PREDICT_FALSE(db->nsessions == 0)) { - /* Should be a static entry - * Note this session as the first session and log - */ - cnat_add_dest_n_log(db, &dest_info); - } else { /* Many translations exist already */ - dest_info.k.vrf = db->in2out_key.k.vrf; - /* If session already exists, - * cnat_create_session_db_entry will return the existing db - * else create a new db - * If could not create, return NULL - */ - session_db = cnat_create_session_db_entry(&dest_info, - db, TRUE); - - if(PREDICT_FALSE(session_db == NULL)) { - disposition = CNAT_V4_ICMP_Q_O2I_D; - counter = CNAT_V4_ICMP_Q_O2I_NO_SESSION_DROP; - goto drop_pkt; - } - } - } - -update_pkt: - - if (PLATFORM_HANDLE_TTL_DECREMENT) { - /* - * Decrement TTL and update IPv4 checksum - */ - ipv4_decr_ttl_n_calc_csum(ip); - } - - /* - * 1. update dest ipv4 addr and icmp id - * 2. update ipv4 checksum and icmp checksum - */ - swap_ip_dst_icmp_id(ip, icmp, db, db->in2out_key.k.vrf); - - if (PREDICT_FALSE(icmp_debug_flag)) { - printf("\nDUMPING ICMP PKT AFTER\n"); - print_icmp_pkt(ip); - } - - db->out2in_pkts++; - - //nat44_dslite_global_stats[dslite_flag].out2in_forwarding_count++; - - } else { - disposition = CNAT_V4_ICMP_Q_O2I_D; - counter = CNAT_V4_ICMP_Q_O2I_MISS_PKT; - } - -drop_pkt: - em->counters[node_counter_base_index + counter] += 1; - return disposition; - -} - -#include - -static uword cnat_ipv4_icmp_q_outside_input_node_fn (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return dispatch_pipeline (vm, node, frame); -} - - -VLIB_REGISTER_NODE (cnat_ipv4_icmp_q_outside_input_node) = { - .function = cnat_ipv4_icmp_q_outside_input_node_fn, - .name = "vcgn-v4-icmp-q-o2i", - .vector_size = sizeof (u32), - .type = VLIB_NODE_TYPE_INTERNAL, - - .n_errors = ARRAY_LEN(cnat_ipv4_icmp_q_outside_input_error_strings), - .error_strings = cnat_ipv4_icmp_q_outside_input_error_strings, - - .n_next_nodes = CNAT_V4_ICMP_Q_O2I_NEXT, - - /* edit / add dispositions here */ - .next_nodes = { - [CNAT_V4_ICMP_Q_O2I_T] = "ip4-input", - [CNAT_V4_ICMP_Q_O2I_D] = "error-drop", - }, -}; - -clib_error_t *cnat_ipv4_icmp_q_outside_input_init (vlib_main_t *vm) -{ - cnat_ipv4_icmp_q_outside_input_main_t * mp = &cnat_ipv4_icmp_q_outside_input_main; - - mp->vlib_main = vm; - mp->vnet_main = vnet_get_main(); - - return 0; -} - -VLIB_INIT_FUNCTION (cnat_ipv4_icmp_q_outside_input_init); diff --git a/plugins/plugins/vcgn/cnat_ipv4_tcp_inside_input.c b/plugins/plugins/vcgn/cnat_ipv4_tcp_inside_input.c deleted file mode 100644 index 5bea7073..00000000 --- a/plugins/plugins/vcgn/cnat_ipv4_tcp_inside_input.c +++ /dev/null @@ -1,424 +0,0 @@ -/* - *--------------------------------------------------------------------------- - * cnat_ipv4_tcp_inside_input.c - cnat_ipv4_tcp_inside_input node pipeline - * stage functions - * - * - * Copyright (c) 2008-2014 Cisco and/or its affiliates. - * 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 -#include -#include -#include - -#include "cnat_db.h" -#include "tcp_header_definitions.h" -#include "cnat_config.h" -#include "cnat_global.h" -#include "cnat_v4_functions.h" - -#define foreach_cnat_ipv4_tcp_inside_input_error \ -_(CNAT_V4_TCP_I2O_PKT_IN, "tcp i2o packets received") \ -_(CNAT_V4_TCP_I2O_PKT_T, "tcp i2o packets natted") \ -_(CNAT_V4_TCP_I2O_EXCEPTION, "packets to tcp i2o exception") \ -_(CNAT_V4_TCP_I2O_TTL_GEN, "generated TTL expiry ICMP packets") \ -_(CNAT_V4_TCP_I2O_TTL_GEN_DROP, "could not generate TTL expiry ICMP packets") \ -_(CNAT_V4_TCP_I2O_SESSION_DROP, "could not generate session") \ -_(CNAT_V4_UDP_I2O_FRAG_DROP, "non-first fragment drop") - -typedef enum { -#define _(sym,str) sym, - foreach_cnat_ipv4_tcp_inside_input_error -#undef _ - CNAT_IPV4_TCP_INSIDE_INPUT_N_ERROR, -} cnat_ipv4_tcp_inside_input_t; - -static char * cnat_ipv4_tcp_inside_input_error_strings[] = { -#define _(sym,string) string, - foreach_cnat_ipv4_tcp_inside_input_error -#undef _ -}; - -typedef struct { - u32 cached_next_index; - /* $$$$ add data here */ - - /* convenience variables */ - vlib_main_t * vlib_main; - vnet_main_t * vnet_main; -} cnat_ipv4_tcp_inside_input_main_t; - -typedef enum { - CNAT_V4_TCP_I2O_E, - CNAT_V4_TCP_I2O_T, - CNAT_V4_TCP_I2O_D, - CNAT_V4_TCP_I2O_NEXT, -} cnat_ipv4_tcp_inside_input_next_t; - -#define CNAT_REWRITE_OUTPUT CNAT_V4_TCP_I2O_T -#define CNAT_V4_ICMP_GEN CNAT_V4_TCP_I2O_D - -//#define CNAT_V4_TCP_I2O_E CNAT_V4_TCP_I2O_D //remove it once exception node is created -cnat_ipv4_tcp_inside_input_main_t cnat_ipv4_tcp_inside_input_main; -vlib_node_registration_t cnat_ipv4_tcp_inside_input_node; - -#define NSTAGES 6 - -/* - * Use the generic buffer metadata + first line of packet data prefetch - * stage function from . This is usually a Good Idea. - */ -#define stage0 generic_stage0 - - -static inline void -stage1(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) -{ - u64 a, b, c; - u32 bucket; - u8 *prefetch_target; - //cnat_feature_data_t *fd = (cnat_feature_data_t *)ctx->feature_data; - - - vlib_buffer_t * b0 = vlib_get_buffer (vm, buffer_index); - ipv4_header *ip = vlib_buffer_get_current (b0); - u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; - tcp_hdr_type *tcp = (tcp_hdr_type *)((u8*)ip + ipv4_hdr_len); - - u64 tmp = 0; - tmp = vnet_buffer(b0)->vcgn_uii.key.k.ipv4 = - clib_net_to_host_u32(ip->src_addr); - vnet_buffer(b0)->vcgn_uii.key.k.port = - clib_net_to_host_u16 (tcp->src_port); - - tmp |= ((u64)vnet_buffer(b0)->vcgn_uii.key.k.port) << 32; - - PLATFORM_CNAT_SET_RX_VRF(vnet_buffer(b0)->sw_if_index[VLIB_RX], - vnet_buffer(b0)->vcgn_uii.key.k.vrf, - CNAT_TCP) - tmp |= ((u64)vnet_buffer(b0)->vcgn_uii.key.k.vrf) << 48; - - CNAT_V4_GET_HASH(tmp, bucket, CNAT_MAIN_HASH_MASK) - - prefetch_target = (u8 *)(&cnat_in2out_hash[bucket]); - vnet_buffer(b0)->vcgn_uii.bucket = bucket; - - /* Prefetch the hash bucket */ - CLIB_PREFETCH(prefetch_target, CLIB_CACHE_LINE_BYTES, LOAD); -} - -static inline void -stage2(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) -{ /* nothing */ } - - -#define SPP_LOG2_CACHE_LINE_BYTES 6 -#define SPP_CACHE_LINE_BYTES (1 << SPP_LOG2_CACHE_LINE_BYTES) - -static inline void -stage3(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) -{ - vlib_buffer_t * b0 = vlib_get_buffer(vm, buffer_index); - uword prefetch_target0, prefetch_target1; - u32 bucket = vnet_buffer(b0)->vcgn_uii.bucket; - - /* read the hash bucket */ - u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket - = cnat_in2out_hash[bucket].next; - - if (PREDICT_TRUE(db_index != EMPTY)) { - /* - * Prefetch database keys. We save space by not cache-line - * aligning the DB entries. We don't want to waste LSU - * bandwidth prefetching stuff we won't need. - */ - prefetch_target0 = (uword)(cnat_main_db + db_index); - CLIB_PREFETCH((void*)prefetch_target0, CLIB_CACHE_LINE_BYTES, LOAD); - /* Just beyond DB key #2 */ - prefetch_target1 = prefetch_target0 + - STRUCT_OFFSET_OF(cnat_main_db_entry_t, user_ports); - /* If the targets are in different lines, do the second prefetch */ - if (PREDICT_FALSE((prefetch_target0 & ~(SPP_CACHE_LINE_BYTES-1)) != - (prefetch_target1 & ~(SPP_CACHE_LINE_BYTES-1)))) { - CLIB_PREFETCH((void *)prefetch_target1, CLIB_CACHE_LINE_BYTES, LOAD); - } - } -} - -static inline void -stage4(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) -{ - cnat_main_db_entry_t *db; - vlib_buffer_t * b0 = vlib_get_buffer(vm, buffer_index); - u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket; - - /* - * Note: if the search already failed (empty bucket), - * the answer is already in the pipeline context structure - */ - if (PREDICT_TRUE(db_index != EMPTY)) { - - /* - * Note: hash collisions suck. We can't easily prefetch around them. - * The first trip around the track will be fast. After that, maybe - * not so much... - */ - do { - db = cnat_main_db + db_index; - if (PREDICT_TRUE(db->in2out_key.key64 == - vnet_buffer(b0)->vcgn_uii.key.key64)) { - break; - } - db_index = db->in2out_hash.next; - } while (db_index != EMPTY); - - /* Stick the answer back into the pipeline context structure */ - vnet_buffer(b0)->vcgn_uii.bucket = db_index; - } -} - - -static inline u32 last_stage (vlib_main_t *vm, vlib_node_runtime_t *node, - u32 bi) -{ - vlib_buffer_t *b0 = vlib_get_buffer (vm, bi); - u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket; - spp_ctx_t *ctx = (spp_ctx_t *) &vnet_buffer(b0)->vcgn_uii; - int disposition = CNAT_V4_TCP_I2O_T; - int counter = CNAT_V4_TCP_I2O_PKT_T; - - ipv4_header *ip = (ipv4_header *)vlib_buffer_get_current(b0); - u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; - tcp_hdr_type *tcp = (tcp_hdr_type *)((u8*)ip + ipv4_hdr_len); - vlib_node_t *n = vlib_get_node (vm, cnat_ipv4_tcp_inside_input_node.index); - u32 node_counter_base_index = n->error_heap_index; - vlib_error_main_t * em = &vm->error_main; - cnat_session_entry_t *session_db = NULL; - cnat_main_db_entry_t *db = NULL; - cnat_key_t dest_info; - u32 window; - u8 scale; - - - INCREMENT_NODE_COUNTER(CNAT_V4_TCP_I2O_PKT_IN); - - if (PLATFORM_HANDLE_TTL_DECREMENT) { - if (PREDICT_FALSE(ip->ttl <= 1)) { - /* Try to generate ICMP error msg, as TTL is <= 1 */ - - if (icmpv4_generate_with_throttling - (ctx, ip, ctx->ru.rx.uidb_index)) { - - /* Generated ICMP */ - disposition = CNAT_REWRITE_OUTPUT; - counter = CNAT_V4_TCP_I2O_TTL_GEN; - } else { - /* Could not generated ICMP - drop the packet */ - disposition = CNAT_V4_TCP_I2O_D; - counter = CNAT_V4_TCP_I2O_TTL_GEN_DROP; - } - goto drop_pkt; - } - } - - if (PREDICT_FALSE(db_index == EMPTY)) { - /* Deleted fragment code from here */ - disposition = CNAT_V4_TCP_I2O_E; - counter = CNAT_V4_TCP_I2O_EXCEPTION; - } else { - db = cnat_main_db + db_index; - - /* Handle destination sessions */ - dest_info.k.port = clib_net_to_host_u16(tcp->dest_port); - dest_info.k.ipv4 = clib_net_to_host_u32(ip->dest_addr); - - if(PREDICT_TRUE(!PLATFORM_DBL_SUPPORT)) { - - /* No DBL support, so just update the destn and proceed */ - db->dst_ipv4 = dest_info.k.ipv4; - db->dst_port = dest_info.k.port; - goto update_pkt; - } - - if(PREDICT_FALSE(db->dst_ipv4 != dest_info.k.ipv4 || - db->dst_port != dest_info.k.port)) { - if(PREDICT_TRUE(db->nsessions == 0)) { - /* Should be a static entry - * Note this session as the first session and log - */ - cnat_add_dest_n_log(db, &dest_info); - } else if(PREDICT_FALSE(db->nsessions == 1)) { - /* Destn is not same as in main db. Multiple session - * scenario - */ - dest_info.k.vrf = db->in2out_key.k.vrf; - session_db = cnat_handle_1to2_session(db, &dest_info); - if(PREDICT_FALSE(session_db == NULL)) { - disposition = CNAT_V4_TCP_I2O_D; - counter = CNAT_V4_TCP_I2O_SESSION_DROP; - goto drop_pkt; - } - } else { /* There are already multiple destinations */ - dest_info.k.vrf = db->in2out_key.k.vrf; - /* If session already exists, - * cnat_create_session_db_entry will return the existing db - * else create a new db - * If could not create, return NULL - */ - session_db = cnat_create_session_db_entry(&dest_info, - db, TRUE); - if(PREDICT_FALSE(session_db == NULL)) { - disposition = CNAT_V4_TCP_I2O_D; - counter = CNAT_V4_TCP_I2O_SESSION_DROP; - goto drop_pkt; - } - } - if(PREDICT_TRUE(session_db != 0)) { - /* Have to repeat the window size check for new destinations */ - window = (u32)clib_net_to_host_u16(tcp->window_size); - window = window << session_db->scale; - if(PREDICT_TRUE(!session_db->window)) { - calculate_window_scale(tcp, &scale); - session_db->scale = scale; - session_db->window = window; - } else if (PREDICT_FALSE(session_db->window < - window)) { - /* Update the db entry with window option from packet */ - session_db->window = window; - } else { - /* Do nothing */ - } - session_db->tcp_seq_num = clib_net_to_host_u32(tcp->seq_num); - session_db->ack_no = clib_net_to_host_u32(tcp->ack_num); -#if DEBUG > 1 - printf("\n In2out SDB stages seq no = %u," - " ack no = %u, window = %u\n", - session_db->tcp_seq_num, - session_db->ack_no, - session_db->window); -#endif - - } - } else { - //Update the seq no and ack no for subsequent communication - //after connection establishment - //No need to update window here. Window is already updated - //during connection establishment - window = (u32)clib_net_to_host_u16(tcp->window_size); - window = window << db->scale; - if(PREDICT_FALSE(!ALG_ENABLED_DB(db))) { - //This check is done since proto_data is part of union in main - //db entry - db->proto_data.tcp_seq_chk.seq_no = - clib_net_to_host_u32(tcp->seq_num); - db->proto_data.tcp_seq_chk.ack_no = - clib_net_to_host_u32(tcp->ack_num); - } - if (PREDICT_FALSE(db->diff_window < window)) { - /* Update the db entry with window option from packet */ - db->diff_window = window; - } -#if DEBUG > 1 - printf("\n In2out MainDB seq no = %u," - "\n ack no = %u\n", - db->proto_data.tcp_seq_chk.seq_no, - db->proto_data.tcp_seq_chk.ack_no); - printf("\n In2out MAINDB window = %u\n", - db->diff_window); -#endif - } -update_pkt: - - counter = CNAT_V4_TCP_I2O_PKT_T; - disposition = CNAT_V4_TCP_I2O_T; - - /* NO FRAGMENT & ALG HANDLING. DELETING THE CODE */ - - if (PLATFORM_HANDLE_TTL_DECREMENT) { - /* - * Decrement TTL and update IPv4 checksum - */ - ipv4_decr_ttl_n_calc_csum(ip); - } - - tcp_in2out_nat_mss_n_checksum(ip, - tcp, - db->out2in_key.k.ipv4, - db->out2in_key.k.port, - db - /*, db->in2out_key.k.vrf */); - - /* update transaltion counters */ - db->in2out_pkts++; - in2out_forwarding_count++; - - /* update the timer for good mode, or evil mode dst_ip match */ - - if(PREDICT_FALSE(session_db != NULL)) { - V4_TCP_UPDATE_SESSION_DB_FLAG(session_db, tcp); - CNAT_DB_TIMEOUT_RST(session_db); - } else { - V4_TCP_UPDATE_SESSION_FLAG(db, tcp); - CNAT_DB_TIMEOUT_RST(db); - } - } - -drop_pkt: - - em->counters[node_counter_base_index + counter] += 1; - return disposition; -} - -#include - -static uword cnat_ipv4_tcp_inside_input_node_fn (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return dispatch_pipeline (vm, node, frame); -} - - -VLIB_REGISTER_NODE (cnat_ipv4_tcp_inside_input_node) = { - .function = cnat_ipv4_tcp_inside_input_node_fn, - .name = "vcgn-v4-tcp-i2o", - .vector_size = sizeof (u32), - .type = VLIB_NODE_TYPE_INTERNAL, - - .n_errors = ARRAY_LEN(cnat_ipv4_tcp_inside_input_error_strings), - .error_strings = cnat_ipv4_tcp_inside_input_error_strings, - - .n_next_nodes = CNAT_V4_TCP_I2O_NEXT, - - /* edit / add dispositions here */ - .next_nodes = { - [CNAT_V4_TCP_I2O_E] = "vcgn-v4-tcp-i2o-e", - [CNAT_V4_TCP_I2O_T] = "ip4-input", - [CNAT_V4_TCP_I2O_D] = "error-drop", - }, -}; - -clib_error_t *cnat_ipv4_tcp_inside_input_init (vlib_main_t *vm) -{ - cnat_ipv4_tcp_inside_input_main_t * mp = &cnat_ipv4_tcp_inside_input_main; - - mp->vlib_main = vm; - mp->vnet_main = vnet_get_main(); - - return 0; -} - -VLIB_INIT_FUNCTION (cnat_ipv4_tcp_inside_input_init); diff --git a/plugins/plugins/vcgn/cnat_ipv4_tcp_inside_input_exceptions.c b/plugins/plugins/vcgn/cnat_ipv4_tcp_inside_input_exceptions.c deleted file mode 100644 index bc1bebb0..00000000 --- a/plugins/plugins/vcgn/cnat_ipv4_tcp_inside_input_exceptions.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - *--------------------------------------------------------------------------- - * cnat_ipv4_tcp_inside_input_exceptions.c - - * cnat_ipv4_tcp_inside_input_exceptions node pipeline stage functions - * - * - * Copyright (c) 2008-2014 Cisco and/or its affiliates. - * 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 -#include -#include -#include - -#include "cnat_db.h" -#include "tcp_header_definitions.h" -#include "cnat_config.h" -#include "cnat_global.h" -#include "cnat_v4_functions.h" - - -#define foreach_cnat_ipv4_tcp_inside_input_exc_error \ -_(CNAT_V4_TCP_I2O_E_T_PKT, "v4 tcp i2o-e transmit natted pkt") \ -_(CNAT_V4_TCP_I2O_E_D_NON_SYN_PKT, "v4 tcp i2o-e non syn drop") \ -_(CNAT_V4_TCP_I2O_E_D_INVALID_PKT, "v4 tcp i2o-e invalid pkt drop") \ -_(CNAT_V4_TCP_I2O_E_DROP, "v4 tcp i2o-e drop") \ -_(CNAT_V4_TCP_I2O_E_GEN_ICMP, "v4 tcp i2o-e gen icmp msg") \ -_(CNAT_V4_TCP_I2O_E_D_NO_SESSION, "v4 tcp i2o-e no session db entry drop") - -typedef enum { -#define _(sym,str) sym, - foreach_cnat_ipv4_tcp_inside_input_exc_error -#undef _ - CNAT_IPV4_TCP_INSIDE_INPUT_EXCEPTIONS_N_ERROR, -} cnat_ipv4_tcp_inside_input_exc_error_t; - - -static char * cnat_ipv4_tcp_inside_input_exc_error_strings[] = { -#define _(sym,string) string, - foreach_cnat_ipv4_tcp_inside_input_exc_error -#undef _ -}; - -typedef struct { - u32 cached_next_index; - /* $$$$ add data here */ - - /* convenience variables */ - vlib_main_t * vlib_main; - vnet_main_t * vnet_main; -} cnat_ipv4_tcp_inside_input_exc_main_t; - -typedef enum { - CNAT_V4_TCP_I2O_E_T, - //CNAT_V4_TCP_I2O_E_ICMP, - CNAT_V4_TCP_I2O_E_D, - CNAT_V4_TCP_I2O_E_NEXT, -} cnat_ipv4_udp_inside_input_exc_next_t; - -#define CNAT_V4_TCP_I2O_E_ICMP CNAT_V4_TCP_I2O_E_D - -cnat_ipv4_tcp_inside_input_exc_main_t cnat_ipv4_tcp_inside_input_exc_main; -vlib_node_registration_t cnat_ipv4_tcp_inside_input_exc_node; - -#define NSTAGES 2 - -/* - * Use the generic buffer metadata + first line of packet data prefetch - * stage function from . This is usually a Good Idea. - */ -#define stage0 generic_stage0 - - -static inline u32 last_stage (vlib_main_t *vm, vlib_node_runtime_t *node, - u32 bi) -{ - vlib_buffer_t *b0 = vlib_get_buffer (vm, bi); - vlib_node_t *n = - vlib_get_node (vm, cnat_ipv4_tcp_inside_input_exc_node.index); - u32 node_counter_base_index = n->error_heap_index; - vlib_error_main_t * em = &vm->error_main; - - cnat_gen_icmp_info info; - cnat_db_key_bucket_t ki; - cnat_main_db_entry_t *db = NULL; - ipv4_header *ip = (ipv4_header *)vlib_buffer_get_current(b0); - u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; - tcp_hdr_type *tcp = (tcp_hdr_type *)((u8*)ip + ipv4_hdr_len); - int disposition = CNAT_V4_TCP_I2O_E_T; - int counter = CNAT_V4_TCP_I2O_E_T_PKT; - cnat_key_t dest_info; - u32 window; - u8 scale; - - window = (u32)clib_net_to_host_u16(tcp->window_size); - calculate_window_scale(tcp, &scale); - - dest_info.k.port = clib_net_to_host_u16(tcp->dest_port); - dest_info.k.ipv4 = clib_net_to_host_u32(ip->dest_addr); - - PLATFORM_CNAT_SET_RX_VRF(vnet_buffer(b0)->sw_if_index[VLIB_RX], - dest_info.k.vrf, CNAT_TCP) - - /* for TCP if not SYN or if src_port is 0, silently drop the packet */ - if (PREDICT_FALSE(!((tcp->flags & TCP_FLAG_SYN) && (tcp->src_port)))) { - - /* - * If the packet is dropped due to both reasons, - * count it as invalid packet drop - */ - if (!tcp->src_port) { - counter = CNAT_V4_TCP_I2O_E_D_INVALID_PKT; - } else { - counter = CNAT_V4_TCP_I2O_E_D_NON_SYN_PKT; - } - disposition = CNAT_V4_TCP_I2O_E_D; - goto in2out_e; - } - - PLATFORM_CNAT_SET_RX_VRF(vnet_buffer(b0)->sw_if_index[VLIB_RX], - ki.k.k.vrf, CNAT_TCP) - - ki.k.k.ipv4 = clib_net_to_host_u32(ip->src_addr); - ki.k.k.port = clib_net_to_host_u16(tcp->src_port); - - db = cnat_get_main_db_entry_v2(&ki, PORT_SINGLE, PORT_TYPE_DYNAMIC, &info, - &dest_info); - - -#if DEBUG > 1 - if(PREDICT_TRUE(db)) { - printf("create db %x ip %x->%x port %x->%x dst_ip %x\n", db, - db->in2out_key.k.ipv4, db->out2in_key.k.ipv4, - db->in2out_key.k.port, db->out2in_key.k.port, db->dst_ipv4); - } -#endif - - - if (PREDICT_FALSE(db == 0)) { - /* failed to create new db entry due to either no more port, or user limit reached, - * need to generate ICMP type=3,code=13 msg here, - */ - - /* - * we rate limit the icmp msg per private user, - * so we don't flood a user with icmp msg - * in case the per user port limit reached - */ - if (PREDICT_TRUE(info.gen_icmp_msg == CNAT_ICMP_MSG)) { - /* KEEPING THINGS COMMENTED HERE..MAY NEED TO REVISIT AGAIN */ - #if 0 - u32 *fd = (u32*)ctx->feature_data; - fd[0] = info.svi_addr; - fd[1] = CNAT_ICMP_DEST_UNREACHABLE; - - /* - * Let's reverse the direction from i2o to o2i. - * This will help using the correct VRF in the fib lookup (AVSM) - * especially for the o2i_vrf_override case - */ - ctx->ru.rx.direction = 0; // 0 - o2i, 1 - i2o - #endif - disposition = CNAT_V4_TCP_I2O_E_ICMP; - counter = CNAT_V4_TCP_I2O_E_GEN_ICMP; - - } else { - disposition = CNAT_V4_TCP_I2O_E_D; - counter = CNAT_V4_TCP_I2O_E_DROP; - } - //DEBUG_I2O_DROP(CNAT_DEBUG_DROP_TCP) - } else { - - if (PLATFORM_HANDLE_TTL_DECREMENT) { - /* - * Decrement TTL and update IPv4 checksum - */ - ipv4_decr_ttl_n_calc_csum(ip); - } - - /* NAT the packet and fix checksum */ - - tcp_in2out_nat_mss_n_checksum(ip, - tcp, - db->out2in_key.k.ipv4, - db->out2in_key.k.port, - db - /*, db->in2out_key.k.vrf */); - - /* this must be inside to outside SYN, do mss here */ - - /* update translation counters */ - db->in2out_pkts++; - - /* set keepalive timer */ - - if(PREDICT_TRUE((dest_info.k.ipv4 == db->dst_ipv4) && - (dest_info.k.port == db->dst_port))) { - if(PREDICT_FALSE(!ALG_ENABLED_DB(db))) { - //This check is done since proto_data is part of union in main - //db entry - - db->proto_data.tcp_seq_chk.seq_no = - clib_net_to_host_u32(tcp->seq_num); - db->proto_data.tcp_seq_chk.ack_no = - clib_net_to_host_u32(tcp->ack_num); - db->scale = scale; - db->diff_window = window; - } -#if DEBUG > 1 - PLATFORM_DEBUG_PRINT("\nMain DB seq no = %u," - "ack no = %u, window = %u," - "scale = %u", - db->proto_data.tcp_seq_chk.seq_no, - db->proto_data.tcp_seq_chk.ack_no, - db->diff_window - db->scale); -#endif - V4_TCP_UPDATE_SESSION_FLAG(db, tcp); - /* Check timeout db if there is config for this */ - (void) query_and_update_db_timeout((void *)db, MAIN_DB_TYPE); - db->entry_expires = cnat_current_time; - } else { - /* Got to find out the session entry corresponding to this..*/ - cnat_session_entry_t *sdb; - sdb = cnat_session_db_lookup_entry( - &dest_info, db - cnat_main_db); - if(PREDICT_FALSE(sdb == NULL)) { - disposition = CNAT_V4_TCP_I2O_E_D; - counter = CNAT_V4_TCP_I2O_E_D_NO_SESSION; - goto in2out_e; - } - sdb->tcp_seq_num = clib_net_to_host_u32(tcp->seq_num); - sdb->ack_no = clib_net_to_host_u32(tcp->ack_num); - sdb->scale = scale; - sdb->window = window; - -#if DEBUG > 1 - PLATFORM_DEBUG_PRINT("\nSDB seq no = %u, ack no = %u, window = %u" - "\nSDB scale = %u" , - sdb->tcp_seq_num, - sdb->ack_no, - sdb->window, - sdb->scale); -#endif - V4_TCP_UPDATE_SESSION_DB_FLAG(sdb, tcp); - /* Check timeout db if there is config for this */ - (void) query_and_update_db_timeout((void *)sdb, SESSION_DB_TYPE); - sdb->entry_expires = cnat_current_time; - } - - //PLATFORM_CNAT_SET_TX_VRF(ctx,db->out2in_key.k.vrf) - - counter = CNAT_V4_TCP_I2O_E_T_PKT; - in2out_forwarding_count++; - } - -in2out_e: - - em->counters[node_counter_base_index + counter] += 1; - - return disposition; -} - -#include - -static uword cnat_ipv4_tcp_inside_input_exc_node_fn (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return dispatch_pipeline (vm, node, frame); -} - -VLIB_REGISTER_NODE (cnat_ipv4_tcp_inside_input_exc_node) = { - .function = cnat_ipv4_tcp_inside_input_exc_node_fn, - .name = "vcgn-v4-tcp-i2o-e", - .vector_size = sizeof (u32), - .type = VLIB_NODE_TYPE_INTERNAL, - - .n_errors = ARRAY_LEN(cnat_ipv4_tcp_inside_input_exc_error_strings), - .error_strings = cnat_ipv4_tcp_inside_input_exc_error_strings, - - .n_next_nodes = CNAT_V4_TCP_I2O_E_NEXT, - - /* edit / add dispositions here */ - .next_nodes = { - [CNAT_V4_TCP_I2O_E_T] = "ip4-input", - [CNAT_V4_TCP_I2O_E_D] = "error-drop", - }, -}; - - -clib_error_t *cnat_ipv4_tcp_inside_input_exc_init (vlib_main_t *vm) -{ - cnat_ipv4_tcp_inside_input_exc_main_t * mp = &cnat_ipv4_tcp_inside_input_exc_main; - - mp->vlib_main = vm; - mp->vnet_main = vnet_get_main(); - - return 0; -} - -VLIB_INIT_FUNCTION (cnat_ipv4_tcp_inside_input_exc_init); diff --git a/plugins/plugins/vcgn/cnat_ipv4_tcp_outside_input.c b/plugins/plugins/vcgn/cnat_ipv4_tcp_outside_input.c deleted file mode 100644 index bcf132b1..00000000 --- a/plugins/plugins/vcgn/cnat_ipv4_tcp_outside_input.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - *--------------------------------------------------------------------------- - * cnat_ipv4_tcp_outside_input.c - cnat_v4_tcp_out2in node pipeline stage functions - * - * - * Copyright (c) 2008-2014 Cisco and/or its affiliates. - * 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 -#include -#include -#include - -#include "cnat_db.h" -#include "tcp_header_definitions.h" -#include "cnat_config.h" -#include "cnat_global.h" -#include "cnat_ipv4_udp.h" -#include "cnat_v4_functions.h" - - -#define foreach_cnat_ipv4_tcp_outside_input_error \ -_(CNAT_V4_TCP_O2I_R_PKT, "v4 tcp o2i pkt received") \ -_(CNAT_V4_TCP_O2I_T_PKT, "v4 tcp o2i pkt natted & transmitted") \ -_(CNAT_V4_TCP_O2I_LOOKUP_FAILED, "v4 tcp o2i lookup failed") \ -_(CNAT_V4_TCP_O2I_TTL_GEN, "v4 tcp o2i generated TTL Expiry ICMP packet") \ -_(CNAT_V4_TCP_O2I_TTL_DROP, "v4 tcp o2i drop due to failure in creating TTL expiry ICMP msg") \ -_(CNAT_V4_TCP_O2I_PTB_GEN, "v4 tcp o2i PTB ICMP pkt generation") \ -_(CNAT_V4_UDP_O2I_PTB_DROP, "v4 tcp o2i drop due to failure in creating PTB ICMP pkt") \ -_(CNAT_V4_TCP_O2I_SESSION_DROP, "v4 tcp o2i drop due to failure in creating session db") \ -_(CNAT_V4_TCP_O2I_SEQ_MISMATCH_DROP, "v4 tcp o2i drop due to TCP sequence mismatch") \ -_(CNAT_V4_TCP_O2I_FILTER_DROP, "v4 tcp o2i drop due to endpoint filtering") \ -_(CNAT_V4_TCP_O2I_NON_SYN_RST_DROP, "v4 tcp o2i drop due no syn/rst flag") \ -_(CNAT_V4_TCP_O2I_FIRST_FRAG_DROP, "v4 tcp o2i first fragment drop") \ -_(CNAT_V4_TCP_O2I_SUB_FRAG_NO_DB_DROP, "v4 tcp o2i subsequest frag no DB drop") - -typedef enum { -#define _(sym,str) sym, - foreach_cnat_ipv4_tcp_outside_input_error -#undef _ - CNAT_IPV4_TCP_OUTSIDE_INPUT_N_ERROR, -} cnat_ipv4_tcp_outside_input_t; - -static char * cnat_ipv4_tcp_outside_input_error_strings[] = { -#define _(sym,string) string, - foreach_cnat_ipv4_tcp_outside_input_error -#undef _ -}; - -typedef struct { - u32 cached_next_index; - /* $$$$ add data here */ - - /* convenience variables */ - vlib_main_t * vlib_main; - vnet_main_t * vnet_main; -} cnat_ipv4_tcp_outside_input_main_t; - -typedef enum { - //CNAT_V4_TCP_O2I_E, - CNAT_V4_TCP_O2I_T, - CNAT_V4_TCP_O2I_D, - CNAT_V4_TCP_O2I_NEXT, -} cnat_ipv4_tcp_outside_input_next_t; - -cnat_ipv4_tcp_outside_input_main_t cnat_ipv4_tcp_outside_input_main; -vlib_node_registration_t cnat_ipv4_tcp_outside_input_node; - -#define NSTAGES 6 - -/* - * Use the generic buffer metadata + first line of packet data prefetch - * stage function from . This is usually a Good Idea. - */ -#define stage0 generic_stage0 - - -static inline void -stage1(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) -{ - u64 a, b, c; - u32 bucket; - u8 *prefetch_target; - - - vlib_buffer_t * b0 = vlib_get_buffer (vm, buffer_index); - ipv4_header *ip = vlib_buffer_get_current (b0); - u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; - tcp_hdr_type *tcp = (tcp_hdr_type *)((u8*)ip + ipv4_hdr_len); - - u64 tmp = 0; - tmp = vnet_buffer(b0)->vcgn_uii.key.k.ipv4 = - clib_net_to_host_u32(ip->dest_addr); - vnet_buffer(b0)->vcgn_uii.key.k.port = - clib_net_to_host_u16 (tcp->dest_port); - - tmp |= ((u64)vnet_buffer(b0)->vcgn_uii.key.k.port) << 32; - - PLATFORM_CNAT_SET_RX_VRF(vnet_buffer(b0)->sw_if_index[VLIB_RX], - vnet_buffer(b0)->vcgn_uii.key.k.vrf, - CNAT_TCP) - tmp |= ((u64)vnet_buffer(b0)->vcgn_uii.key.k.vrf) << 48; - - CNAT_V4_GET_HASH(tmp, bucket, CNAT_MAIN_HASH_MASK) - - prefetch_target = (u8 *)(&cnat_out2in_hash[bucket]); - vnet_buffer(b0)->vcgn_uii.bucket = bucket; - - /* Prefetch the hash bucket */ - CLIB_PREFETCH(prefetch_target, CLIB_CACHE_LINE_BYTES, LOAD); -} - -static inline void -stage2(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) -{ /* nothing */ } - -#define SPP_LOG2_CACHE_LINE_BYTES 6 -#define SPP_CACHE_LINE_BYTES (1 << SPP_LOG2_CACHE_LINE_BYTES) - -static inline void -stage3(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) -{ - vlib_buffer_t * b0 = vlib_get_buffer(vm, buffer_index); - uword prefetch_target0, prefetch_target1; - u32 bucket = vnet_buffer(b0)->vcgn_uii.bucket; - - /* read the hash bucket */ - u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket - = cnat_out2in_hash[bucket].next; - - if (PREDICT_TRUE(db_index != EMPTY)) { - /* - * Prefetch database keys. We save space by not cache-line - * aligning the DB entries. We don't want to waste LSU - * bandwidth prefetching stuff we won't need. - */ - prefetch_target0 = (uword)(cnat_main_db + db_index); - CLIB_PREFETCH((void*)prefetch_target0, CLIB_CACHE_LINE_BYTES, STORE); - /* Just beyond DB key #2 */ - prefetch_target1 = prefetch_target0 + - STRUCT_OFFSET_OF(cnat_main_db_entry_t, user_ports); - /* If the targets are in different lines, do the second prefetch */ - if (PREDICT_FALSE((prefetch_target0 & ~(SPP_CACHE_LINE_BYTES-1)) != - (prefetch_target1 & ~(SPP_CACHE_LINE_BYTES-1)))) { - CLIB_PREFETCH((void *)prefetch_target1, CLIB_CACHE_LINE_BYTES, STORE); - } - } -} - -static inline void -stage4(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) -{ - cnat_main_db_entry_t *db; - vlib_buffer_t * b0 = vlib_get_buffer(vm, buffer_index); - u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket; - - /* - * Note: if the search already failed (empty bucket), - * the answer is already in the pipeline context structure - */ - if (PREDICT_TRUE(db_index != EMPTY)) { - - /* - * Note: hash collisions suck. We can't easily prefetch around them. - * The first trip around the track will be fast. After that, maybe - * not so much... - */ - do { - db = cnat_main_db + db_index; - if (PREDICT_TRUE(db->out2in_key.key64 == - vnet_buffer(b0)->vcgn_uii.key.key64)) { - break; - } - db_index = db->out2in_hash.next; - } while (db_index != EMPTY); - - /* Stick the answer back into the pipeline context structure */ - vnet_buffer(b0)->vcgn_uii.bucket = db_index; - } -} - -static inline u32 last_stage (vlib_main_t *vm, vlib_node_runtime_t *node, - u32 bi) -{ - vlib_buffer_t *b0 = vlib_get_buffer (vm, bi); - u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket; - spp_ctx_t *ctx = (spp_ctx_t *) &vnet_buffer(b0)->vcgn_uii; - int disposition = CNAT_V4_TCP_O2I_T; - int counter = CNAT_V4_TCP_O2I_T_PKT; - - ipv4_header *ip = (ipv4_header *)vlib_buffer_get_current(b0); - u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; - tcp_hdr_type *tcp = (tcp_hdr_type *)((u8*)ip + ipv4_hdr_len); - vlib_node_t *n = vlib_get_node (vm, cnat_ipv4_tcp_outside_input_node.index); - u32 node_counter_base_index = n->error_heap_index; - vlib_error_main_t * em = &vm->error_main; - cnat_session_entry_t *session_db = NULL; - cnat_main_db_entry_t *db = NULL; - cnat_key_t dest_info; - - INCREMENT_NODE_COUNTER(CNAT_V4_TCP_O2I_R_PKT); - - if (PREDICT_FALSE(db_index == EMPTY)) { - nat44_dslite_common_stats[0].no_translation_entry_drops ++; - counter = CNAT_V4_TCP_O2I_LOOKUP_FAILED; - disposition = CNAT_V4_TCP_O2I_D; - } else { - if (PLATFORM_HANDLE_TTL_DECREMENT) { - if (PREDICT_FALSE(ip->ttl <= 1)) { - /* Try to generate ICMP error msg, as TTL is <= 1 */ - if (icmpv4_generate_with_throttling(ctx, - ip, ctx->ru.rx.uidb_index)) { - /* Generated ICMP */ - disposition = CNAT_V4_TCP_O2I_T_PKT; //CNAT_REWRITE_OUTPUT; - counter = CNAT_V4_TCP_O2I_TTL_GEN; - } else { - /* Could not generated ICMP - drop the packet */ - disposition = CNAT_V4_TCP_O2I_D; - counter = CNAT_V4_TCP_O2I_TTL_DROP; - } - goto drop_pkt; - } - } - db = cnat_main_db + db_index; -#if 0 - window = db->diff_window; - stored_seq_no = db->proto_data.tcp_seq_chk.seq_no; - stored_ack_no = db->proto_data.tcp_seq_chk.ack_no; - vrf_map_p = cnat_map_by_vrf + db->vrfmap_index; - vrf_index = (db->in2out_key.k.vrf & CNAT_VRF_MASK); -#endif - /* For Out2In packet, the dest info is src address and port */ - dest_info.k.port = clib_net_to_host_u16(tcp->src_port); - dest_info.k.ipv4 = clib_net_to_host_u32(ip->src_addr); - - if(PREDICT_TRUE(!PLATFORM_DBL_SUPPORT)) { - - /* No DBL support, so just update the destn and proceed */ - db->dst_ipv4 = dest_info.k.ipv4; - db->dst_port = dest_info.k.port; - goto update_pkt; - } - - - if(PREDICT_FALSE(db->dst_ipv4 != dest_info.k.ipv4 || - db->dst_port != dest_info.k.port)) { - - if(PREDICT_TRUE(db->nsessions == 0)) { - /* Should be a static entry - * Note this session as the first session and log - */ - cnat_add_dest_n_log(db, &dest_info); - //goto packet_upd; - } else if(PREDICT_FALSE(db->nsessions == 1)) { - /* Destn is not same as in main db. Multiple session - * scenario - */ - dest_info.k.vrf = db->in2out_key.k.vrf; - session_db = cnat_handle_1to2_session(db, &dest_info); - if(PREDICT_FALSE(session_db == NULL)) { - disposition = CNAT_V4_TCP_O2I_D; - counter = CNAT_V4_TCP_O2I_SESSION_DROP; - goto drop_pkt; - } - } else { /* There are already multiple destinations */ - dest_info.k.vrf = db->in2out_key.k.vrf; - /* If session already exists, - * cnat_create_session_db_entry will return the existing db - * else create a new db - * If could not create, return NULL - */ - session_db = cnat_create_session_db_entry(&dest_info, db, TRUE); - if(PREDICT_FALSE(session_db == NULL)) { - disposition = CNAT_V4_TCP_O2I_D; - counter = CNAT_V4_TCP_O2I_SESSION_DROP; - goto drop_pkt; - } - } - /* useful for ALG only */ - #if 0 - if(PREDICT_TRUE(session_db)) { - stored_seq_no = session_db->tcp_seq_num; - stored_ack_no = session_db->ack_no; - window = session_db->window; - } - #endif - } - - -update_pkt: - - counter = CNAT_V4_TCP_O2I_T_PKT; - - if (PLATFORM_HANDLE_TTL_DECREMENT) { - /* - * Decrement TTL and update IPv4 checksum - */ - ipv4_decr_ttl_n_calc_csum(ip); - } - - /* update ip checksum, newchecksum = ~(~oldchecksum + ~old + new) */ - cnat_v4_recalculate_tcp_checksum(ip, tcp, - &(ip->dest_addr), - &(tcp->dest_port), - db->in2out_key.k.ipv4, - db->in2out_key.k.port); - - /* CNAT_PPTP_ALG_SUPPORT */ - db->out2in_pkts++; - - nat44_dslite_global_stats[0].out2in_forwarding_count++;; - - V4_TCP_UPDATE_SESSION_FLAG(db, tcp); - - - if(PREDICT_FALSE(session_db != NULL)) { - V4_TCP_UPDATE_SESSION_DB_FLAG(session_db, tcp); - CNAT_DB_TIMEOUT_RST(session_db); - } else { - V4_TCP_UPDATE_SESSION_FLAG(db, tcp); - CNAT_DB_TIMEOUT_RST(db); - } - - } - -drop_pkt: - em->counters[node_counter_base_index + counter] += 1; - return disposition; -} - -#include - -static uword cnat_ipv4_tcp_outside_input_node_fn (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return dispatch_pipeline (vm, node, frame); -} - - -VLIB_REGISTER_NODE (cnat_ipv4_tcp_outside_input_node) = { - .function = cnat_ipv4_tcp_outside_input_node_fn, - .name = "vcgn-v4-tcp-o2i", - .vector_size = sizeof (u32), - .type = VLIB_NODE_TYPE_INTERNAL, - - .n_errors = ARRAY_LEN(cnat_ipv4_tcp_outside_input_error_strings), - .error_strings = cnat_ipv4_tcp_outside_input_error_strings, - - .n_next_nodes = CNAT_V4_TCP_O2I_NEXT, - - /* edit / add dispositions here */ - .next_nodes = { - //[CNAT_V4_TCP_O2I_E] = "vcgn-v4-tcp-o2i-e", - [CNAT_V4_TCP_O2I_T] = "ip4-input", - [CNAT_V4_TCP_O2I_D] = "error-drop", - }, -}; - -clib_error_t *cnat_ipv4_tcp_outside_input_init (vlib_main_t *vm) -{ - cnat_ipv4_tcp_outside_input_main_t * mp = &cnat_ipv4_tcp_outside_input_main; - - mp->vlib_main = vm; - mp->vnet_main = vnet_get_main(); - - return 0; -} - -VLIB_INIT_FUNCTION (cnat_ipv4_tcp_outside_input_init); diff --git a/plugins/plugins/vcgn/cnat_ipv4_udp.h b/plugins/plugins/vcgn/cnat_ipv4_udp.h deleted file mode 100644 index 1ccf74a0..00000000 --- a/plugins/plugins/vcgn/cnat_ipv4_udp.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - *----------------------------------------------------------------------------- - * - * Filename: cnat_ipv4_udp.h - * - * Description: common functions for udp node - * - * Assumptions and Constraints: - * - * Copyright (c) 2000-2009 Cisco and/or its affiliates. - * 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 __CNAT_IPV4_UDP_H__ -#define __CNAT_IPV4_UDP_H__ - -#include "tcp_header_definitions.h" -#include "cnat_db.h" -#include "cnat_v4_functions.h" -#include "cnat_global.h" -#include "cnat_config.h" - -extern void swap_ip_src_udp_port(ipv4_header *ip, - udp_hdr_type_t *udp, - cnat_main_db_entry_t *db); -extern void swap_ip_dst_udp_port(ipv4_header *ip, - udp_hdr_type_t *udp, - cnat_main_db_entry_t *db, - u16 vrf); -#endif /* __CNAT_IPV4_UDP_H__ */ diff --git a/plugins/plugins/vcgn/cnat_ipv4_udp_inside_input.c b/plugins/plugins/vcgn/cnat_ipv4_udp_inside_input.c deleted file mode 100644 index 657c5f1e..00000000 --- a/plugins/plugins/vcgn/cnat_ipv4_udp_inside_input.c +++ /dev/null @@ -1,508 +0,0 @@ -/* - *--------------------------------------------------------------------------- - * cnat_ipv4_udp_inside_input.c - cnat_ipv4_udp_inside_input node functions - * - * - * Copyright (c) 2008-2014 Cisco and/or its affiliates. - * 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 -#include -#include -#include - -#include "cnat_global.h" -#include "cnat_db.h" -#include "cnat_ipv4_udp.h" -#include "cnat_pcp_server.h" - - -#define foreach_cnat_ipv4_udp_inside_input_error \ -_(CNAT_V4_UDP_I2O_T_PKT, "v4 udp i2o transmit") \ -_(CNAT_V4_UDP_I2O_MISS_PKT, "v4 udp i2o db miss") \ -_(CNAT_V4_UDP_I2O_TTL_GEN, "v4 udp i2o TTL gen") \ -_(CNAT_V4_UDP_I2O_TTL_DROP, "v4 udp i2o TTL drop") \ -_(CNAT_V4_PCP_PKT, "v4 pcp pkt") \ -_(CNAT_V4_UDP_I2O_SESSION_DROP, "v4 udp i2o session drop") - -typedef enum { -#define _(sym,str) sym, - foreach_cnat_ipv4_udp_inside_input_error -#undef _ - CNAT_IPV4_UDP_INSIDE_INPUT_N_ERROR, -} cnat_ipv4_udp_inside_input_t; - -static char * cnat_ipv4_udp_inside_input_error_strings[] = { -#define _(sym,string) string, - foreach_cnat_ipv4_udp_inside_input_error -#undef _ -}; - -typedef struct { - u32 cached_next_index; - /* $$$$ add data here */ - - /* convenience variables */ - vlib_main_t * vlib_main; - vnet_main_t * vnet_main; -} cnat_ipv4_udp_inside_input_main_t; - -typedef enum { - CNAT_V4_I2O_FIXME, - CNAT_V4_UDP_I2O_E, - CNAT_REWRITE_OUTPUT, - CNAT_V4_UDP_I2O_T = CNAT_REWRITE_OUTPUT, - CNAT_N_NEXT, -} cnat_ipv4_udp_inside_input_next_t; - -#define CNAT_V4_UDP_I2O_D CNAT_V4_I2O_FIXME -#define CNAT_V4_PCP_T CNAT_V4_I2O_FIXME - -cnat_ipv4_udp_inside_input_main_t cnat_ipv4_udp_inside_input_main; -vlib_node_registration_t cnat_ipv4_udp_inside_input_node; - -#define NSTAGES 6 - -/* - * Use the generic buffer metadata + first line of packet data prefetch - * stage function from . This is usually a Good Idea. - */ -#define stage0 generic_stage0 - -#ifndef TOBE_PORTED -static inline u32 -is_pcp_pkt(u32 addr, u16 port) -{ - return CNAT_NO_CONFIG; -} -#else -static inline u32 -is_pcp_pkt(spp_ctx_t *ctx, u32 addr, u16 port) -{ - cnat_vrfmap_t *my_vrfmap = NULL; - u16 my_vrfmap_index; - - my_vrfmap_index = vrf_map_array[ctx->ru.rx.uidb_index]; - - if (PREDICT_TRUE(my_vrfmap_index != VRF_MAP_ENTRY_EMPTY)) { - - my_vrfmap = cnat_map_by_vrf + my_vrfmap_index; - - if (PREDICT_FALSE( port == my_vrfmap->pcp_server_port)) { - if(PREDICT_TRUE(addr == my_vrfmap->pcp_server_addr)) { - return CNAT_SUCCESS; - } - } - } - - return CNAT_NO_CONFIG; -} -#endif - -inline void swap_ip_src_udp_port(ipv4_header *ip, - udp_hdr_type_t *udp, - cnat_main_db_entry_t *db) -{ - /* - * declare varibale - */ - CNAT_UPDATE_L3_L4_CHECKSUM_DECLARE - /* - * calculate checksum - */ - CNAT_UPDATE_L3_L4_CHECKSUM(((u16)(db->in2out_key.k.ipv4)), - ((u16)(db->in2out_key.k.ipv4 >> 16)), - (db->in2out_key.k.port), - (clib_net_to_host_u16(ip->checksum)), - (clib_net_to_host_u16(udp->udp_checksum)), - ((u16)(db->out2in_key.k.ipv4)), - ((u16)(db->out2in_key.k.ipv4 >> 16)), - (db->out2in_key.k.port)) - -/* #define UDP_PACKET_DEBUG 1 */ - -// Temporary debugs which will be suppressed later -#ifdef UDP_PACKET_DEBUG - if (PREDICT_FALSE(udp_inside_packet_dump_enable)) { - printf("\nIn2Out UDP packet before translation"); - print_udp_pkt(ip); - } -#endif - - //set ip header - ip->src_addr = - clib_host_to_net_u32(db->out2in_key.k.ipv4); - ip->checksum = - clib_host_to_net_u16(new_l3_c); - - u16 frag_offset = - clib_net_to_host_u16(ip->frag_flags_offset); - - if(PREDICT_FALSE(frag_offset & IP_FRAG_OFFSET_MASK)) { - return; /* No need to update UDP fields */ - } - //set udp header - udp->src_port = - clib_host_to_net_u16(db->out2in_key.k.port); - - /* - * No easy way to avoid this if check except by using - * complex logic - may not be worth it. - */ - if (PREDICT_TRUE(udp->udp_checksum)) { - udp->udp_checksum = - clib_host_to_net_u16(new_l4_c); - } - -// Temporary debugs which will be suppressed later -#ifdef UDP_PACKET_DEBUG - if (PREDICT_FALSE(udp_inside_checksum_disable)) { - printf("\nIn2Out UDP checksum 0x%x disabled by force", new_l4_c); - udp->udp_checksum = 0; - } - if (PREDICT_FALSE(udp_inside_packet_dump_enable)) { - printf("\nIn2Out UDP packet after translation"); - print_udp_pkt(ip); - } -#endif -} - -static inline void -stage1(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) -{ - u64 a, b, c; - u32 bucket; - u8 *prefetch_target; - - vlib_buffer_t * b0 = vlib_get_buffer (vm, buffer_index); - ipv4_header *ip = vlib_buffer_get_current (b0); - u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; - udp_hdr_type_t *udp = (udp_hdr_type_t *)((u8*)ip + ipv4_hdr_len); - - u64 tmp = 0; - tmp = vnet_buffer(b0)->vcgn_uii.key.k.ipv4 = - clib_net_to_host_u32(ip->src_addr); - vnet_buffer(b0)->vcgn_uii.key.k.port = - clib_net_to_host_u16 (udp->src_port); - - tmp |= ((u64)vnet_buffer(b0)->vcgn_uii.key.k.port) << 32; - - PLATFORM_CNAT_SET_RX_VRF(vnet_buffer(b0)->sw_if_index[VLIB_RX], - vnet_buffer(b0)->vcgn_uii.key.k.vrf, - CNAT_UDP) - tmp |= ((u64)vnet_buffer(b0)->vcgn_uii.key.k.vrf) << 48; - - CNAT_V4_GET_HASH(tmp, bucket, CNAT_MAIN_HASH_MASK) - - prefetch_target = (u8 *)(&cnat_in2out_hash[bucket]); - vnet_buffer(b0)->vcgn_uii.bucket = bucket; - - /* Prefetch the hash bucket */ - CLIB_PREFETCH(prefetch_target, CLIB_CACHE_LINE_BYTES, LOAD); -} - -static inline void -stage2(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) -{ /* nothing */ } - -#define SPP_LOG2_CACHE_LINE_BYTES 6 -#define SPP_CACHE_LINE_BYTES (1 << SPP_LOG2_CACHE_LINE_BYTES) - -static inline void -stage3(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) -{ - vlib_buffer_t * b0 = vlib_get_buffer(vm, buffer_index); - uword prefetch_target0, prefetch_target1; - u32 bucket = vnet_buffer(b0)->vcgn_uii.bucket; - - /* read the hash bucket */ - u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket - = cnat_in2out_hash[bucket].next; - - if (PREDICT_TRUE(db_index != EMPTY)) { - /* - * Prefetch database keys. We save space by not cache-line - * aligning the DB entries. We don't want to waste LSU - * bandwidth prefetching stuff we won't need. - */ - prefetch_target0 = (uword)(cnat_main_db + db_index); - CLIB_PREFETCH((void*)prefetch_target0, CLIB_CACHE_LINE_BYTES, LOAD); - /* Just beyond DB key #2 */ - prefetch_target1 = prefetch_target0 + - STRUCT_OFFSET_OF(cnat_main_db_entry_t, user_ports); - /* If the targets are in different lines, do the second prefetch */ - if (PREDICT_FALSE((prefetch_target0 & ~(SPP_CACHE_LINE_BYTES-1)) != - (prefetch_target1 & ~(SPP_CACHE_LINE_BYTES-1)))) { - CLIB_PREFETCH((void *)prefetch_target1, CLIB_CACHE_LINE_BYTES, LOAD); - } - } -} - -static inline void -stage4(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) -{ - cnat_main_db_entry_t *db; - vlib_buffer_t * b0 = vlib_get_buffer(vm, buffer_index); - u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket; - - /* - * Note: if the search already failed (empty bucket), - * the answer is already in the pipeline context structure - */ - if (PREDICT_TRUE(db_index != EMPTY)) { - - /* - * Note: hash collisions suck. We can't easily prefetch around them. - * The first trip around the track will be fast. After that, maybe - * not so much... - */ - do { - db = cnat_main_db + db_index; - if (PREDICT_TRUE(db->in2out_key.key64 == - vnet_buffer(b0)->vcgn_uii.key.key64)) { - break; - } - db_index = db->in2out_hash.next; - } while (db_index != EMPTY); - - /* Stick the answer back into the pipeline context structure */ - vnet_buffer(b0)->vcgn_uii.bucket = db_index; - } -} - -static u64 pkt_num = 0; -static inline u32 last_stage (vlib_main_t *vm, vlib_node_runtime_t *node, - u32 bi) -{ - vlib_buffer_t *b0 = vlib_get_buffer (vm, bi); - u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket; - spp_ctx_t *ctx = (spp_ctx_t *) &vnet_buffer(b0)->vcgn_uii; - int disposition = CNAT_V4_UDP_I2O_T; - int counter = CNAT_V4_UDP_I2O_T_PKT; - ipv4_header *ip = (ipv4_header *)vlib_buffer_get_current(b0); - u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; - udp_hdr_type_t *udp = (udp_hdr_type_t *)((u8*)ip + ipv4_hdr_len); - vlib_node_t *n = vlib_get_node (vm, cnat_ipv4_udp_inside_input_node.index); - u32 node_counter_base_index = n->error_heap_index; - vlib_error_main_t * em = &vm->error_main; - cnat_session_entry_t *session_db = NULL; - cnat_key_t dest_info; - - pkt_num++; - - if(PREDICT_FALSE(is_pcp_pkt(ip->dest_addr, udp->dest_port) == - CNAT_SUCCESS)) - { - PCP_INCR(input); - disposition = CNAT_V4_PCP_T; - counter = CNAT_V4_PCP_PKT; - - goto pcp_pkt; - } - - if (PLATFORM_HANDLE_TTL_DECREMENT) { - if (PREDICT_FALSE(ip->ttl <= 1)) { - /* Try to generate ICMP error msg, as TTL is <= 1 */ - - if (icmpv4_generate_with_throttling - (ctx, ip, ctx->ru.rx.uidb_index)) { - /* Generated ICMP */ - disposition = CNAT_REWRITE_OUTPUT; - counter = CNAT_V4_UDP_I2O_TTL_GEN; - } else { - /* Could not generated ICMP - drop the packet */ - disposition = CNAT_V4_UDP_I2O_D; - counter = CNAT_V4_UDP_I2O_TTL_DROP; - } - goto drop_pkt; - } - } - if (PREDICT_TRUE(db_index != EMPTY)) { - cnat_main_db_entry_t *db = cnat_main_db + db_index; - - dest_info.k.ipv4 = clib_net_to_host_u32(ip->dest_addr); - - /* MUST revisit: it seems farg is set to 1 for few packets & because of - * this the port is not updated & it becomes 0. Commenting teporarily - * this fargment check & setting dst port with udp dst port value */ - dest_info.k.port = clib_net_to_host_u16(udp->dest_port); - #if 0 // DONOT REMOVE THIS if 0 - if(PREDICT_FALSE(ctx->ru.rx.frag)) { -#ifdef TOBE_PORTED - /* Must have routed through cnat_v4_frag_in2out node */ - u16 *feature_data_ports = (u16 *)&ctx->feature_data[4]; - dest_info.k.port = *feature_data_ports; -#endif - } else { - dest_info.k.port = clib_net_to_host_u16(udp->dest_port); - } - #endif - - - if (PLATFORM_HANDLE_TTL_DECREMENT) { - /* - * Decrement TTL and update IPv4 checksum - */ - ipv4_decr_ttl_n_calc_csum(ip); - } - - if(PREDICT_TRUE(!PLATFORM_DBL_SUPPORT)) { - - /* No DBL support, so just update the destn and proceed */ - db->dst_ipv4 = dest_info.k.ipv4; - db->dst_port = dest_info.k.port; - CNAT_DB_TIMEOUT_RST(db); - goto update_pkt; - } - - if(PREDICT_TRUE((db->dst_ipv4 == dest_info.k.ipv4) && - (db->dst_port == dest_info.k.port))) { - - CNAT_DB_TIMEOUT_RST(db); - goto update_pkt; - } else { - if (PREDICT_FALSE(db->nsessions == 0)) { - /* Should be a static entry - * Note this session as the first session and log - */ - cnat_add_dest_n_log(db, &dest_info); - /* - * update db counter, timer - */ - - CNAT_DB_TIMEOUT_RST(db); - - } else if(PREDICT_TRUE(db->nsessions == 1)) { - /* Destn is not same as in main db. Multiple session - * scenario - */ - //printf(">>> [pkt# %lu] src_ip: 0x%x, db ip: 0x%x, db port: %u; dest ip: 0x%x, dest port: %u\n", - // pkt_num, ntohl(ip->src_addr), db->dst_ipv4, db->dst_port, dest_info.k.ipv4, dest_info.k.port); - - dest_info.k.vrf = db->in2out_key.k.vrf; - session_db = cnat_handle_1to2_session(db, &dest_info); - - if(PREDICT_TRUE(session_db != NULL)) { - /* session exists */ - CNAT_DB_TIMEOUT_RST(session_db); - } else { - /* could not create session db - drop packet */ - disposition = CNAT_V4_UDP_I2O_D; - counter = CNAT_V4_UDP_I2O_SESSION_DROP; - goto drop_pkt; - } - - } else { - /* More than 2 sessions exists */ - - dest_info.k.vrf = db->in2out_key.k.vrf; - - /* If session already exists, - * cnat_create_session_db_entry will return the existing db - * else create a new db - * If could not create, return NULL - */ - session_db = cnat_create_session_db_entry(&dest_info, - db, TRUE); - - if(PREDICT_FALSE(session_db != NULL)) { - /* session exists */ - CNAT_DB_TIMEOUT_RST(session_db); - } else { - /* could not create session db - drop packet */ - disposition = CNAT_V4_UDP_I2O_D; - counter = CNAT_V4_UDP_I2O_SESSION_DROP; - goto drop_pkt; - } - } - } - -update_pkt: - /* - * 1. update src ipv4 addr and src udp port - * 2. update ipv4 checksum and udp checksum - */ - swap_ip_src_udp_port(ip, udp, db); - /* - * update db counter, timer - */ - - db->in2out_pkts++; - - /* - * need to set outside vrf - * from db->out2in_key.k.vrf - */ - - /* Temporarily keeping this commented */ - //PLATFORM_CNAT_SET_TX_VRF(vnet_buffer(b0)->sw_if_index[VLIB_TX], - // db->out2in_key.k.vrf) - - in2out_forwarding_count++; - - } else { - disposition = CNAT_V4_UDP_I2O_E; - counter = CNAT_V4_UDP_I2O_MISS_PKT; - } - -drop_pkt: -pcp_pkt: - - em->counters[node_counter_base_index + counter] += 1; - - return disposition; -} - -#include - -static uword cnat_ipv4_udp_inside_input_node_fn (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return dispatch_pipeline (vm, node, frame); -} - - -VLIB_REGISTER_NODE (cnat_ipv4_udp_inside_input_node) = { - .function = cnat_ipv4_udp_inside_input_node_fn, - .name = "vcgn-v4-udp-i2o", - .vector_size = sizeof (u32), - .type = VLIB_NODE_TYPE_INTERNAL, - - .n_errors = ARRAY_LEN(cnat_ipv4_udp_inside_input_error_strings), - .error_strings = cnat_ipv4_udp_inside_input_error_strings, - - .n_next_nodes = CNAT_N_NEXT, - - /* edit / add dispositions here */ - .next_nodes = { - [CNAT_V4_I2O_FIXME] = "error-drop", - // [CNAT_V4_UDP_I2O_T] = "ip4-input", - [CNAT_V4_UDP_I2O_E] = "vcgn-v4-udp-i2o-e", - [CNAT_REWRITE_OUTPUT] = "ip4-input", - }, -}; - -clib_error_t *cnat_ipv4_udp_inside_input_init (vlib_main_t *vm) -{ - cnat_ipv4_udp_inside_input_main_t * mp = &cnat_ipv4_udp_inside_input_main; - - mp->vlib_main = vm; - mp->vnet_main = vnet_get_main(); - - return 0; -} - -VLIB_INIT_FUNCTION (cnat_ipv4_udp_inside_input_init); diff --git a/plugins/plugins/vcgn/cnat_ipv4_udp_inside_input_exceptions.c b/plugins/plugins/vcgn/cnat_ipv4_udp_inside_input_exceptions.c deleted file mode 100644 index f078c8d4..00000000 --- a/plugins/plugins/vcgn/cnat_ipv4_udp_inside_input_exceptions.c +++ /dev/null @@ -1,283 +0,0 @@ -/* - *--------------------------------------------------------------------------- - * cnat_ipv4_udp_inside_input_exception_stages.c - cnat_ipv4_udp_inside_input_exception node pipeline stage functions - * - * - * Copyright (c) 2008-2014 Cisco and/or its affiliates. - * 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 -#include -#include -#include - -#include "cnat_global.h" -#include "cnat_db.h" -#include "cnat_ipv4_udp.h" - -/* - * Dump these counters via the "show error" CLI command - */ - -#define foreach_cnat_ipv4_udp_inside_input_exc_error \ -_(CNAT_V4_UDP_I2O_T_PKT, "v4 udp i2o transmit") \ -_(CNAT_V4_UDP_I2O_D_PKT, "v4 udp i2o drop") \ -_(CNAT_V4_ICMP_G_I2O_T_PKT, "v4 udp i2o icmp msg gen") \ -_(CNAT_V4_UDP_I2O_DC_PKT, "v4 udp i2o (no config) drop") \ -_(CNAT_V4_UDP_I2O_DR_PKT, "v4 udp i2o (not in run state) drop") \ -_(CNAT_V4_UDP_I2O_DD_PKT, "v4 udp i2o (no direct port) drop") \ -_(CNAT_V4_UDP_I2O_DA_PKT, "v4 udp i2o (no any port) drop") \ -_(CNAT_V4_UDP_I2O_DO_PKT, "v4 udp i2o (out of port limit) drop") \ -_(CNAT_V4_UDP_I2O_DI_PKT, "v4 udp i2o (invalid packet) drop") \ -_(CNAT_V4_UDP_I2O_DS_PKT, "v4 udp i2o (no sessoon db) drop") - -typedef enum { -#define _(sym,str) sym, - foreach_cnat_ipv4_udp_inside_input_exc_error -#undef _ - CNAT_IPV4_UDP_INSIDE_INPUT_EXCEPTIONS_N_ERROR, -} cnat_ipv4_udp_inside_input_exc_error_t; - - -static char * cnat_ipv4_udp_inside_input_exc_error_strings[] = { -#define _(sym,string) string, - foreach_cnat_ipv4_udp_inside_input_exc_error -#undef _ -}; - -typedef struct { - u32 cached_next_index; - /* $$$$ add data here */ - - /* convenience variables */ - vlib_main_t * vlib_main; - vnet_main_t * vnet_main; -} cnat_ipv4_udp_inside_input_exc_main_t; - -typedef enum { - CNAT_V4_UDP_I2O_T, - CNAT_V4_UDP_I2O_D, - CNAT_V4_ICMP_G_I2O_T = CNAT_V4_UDP_I2O_D, /* TOBE_PORTED */ - CNAT_V4_UDP_INSIDE_INPUT_EXC_N_NEXT, -} cnat_ipv4_udp_inside_input_exc_next_t; - -cnat_ipv4_udp_inside_input_exc_main_t cnat_ipv4_udp_inside_input_exc_main; -vlib_node_registration_t cnat_ipv4_udp_inside_input_exc_node; - -#define NSTAGES 2 - -/* - * Use the generic buffer metadata + first line of packet data prefetch - * stage function from . This is usually a Good Idea. - */ -#define stage0 generic_stage0 - -static inline u32 last_stage (vlib_main_t *vm, vlib_node_runtime_t *node, - u32 bi) -{ - vlib_buffer_t *b0 = vlib_get_buffer (vm, bi); - vlib_node_t *n = - vlib_get_node (vm, cnat_ipv4_udp_inside_input_exc_node.index); - u32 node_counter_base_index = n->error_heap_index; - vlib_error_main_t * em = &vm->error_main; - - cnat_gen_icmp_info info; - cnat_db_key_bucket_t ki; - spp_ctx_t *ctx __attribute__((unused)) - = (spp_ctx_t *) &vnet_buffer(b0)->vcgn_uii; - cnat_main_db_entry_t *db = NULL; - ipv4_header *ip = (ipv4_header *)vlib_buffer_get_current(b0); - u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; - udp_hdr_type_t *udp = (udp_hdr_type_t *)((u8*)ip + ipv4_hdr_len); - int disposition = CNAT_V4_UDP_I2O_T; - int counter = CNAT_V4_UDP_I2O_T_PKT; - - cnat_key_t dest_info; - - PLATFORM_CNAT_SET_RX_VRF(vnet_buffer(b0)->sw_if_index[VLIB_RX], - vnet_buffer(b0)->vcgn_uii.key.k.vrf, - CNAT_UDP) - - vnet_buffer(b0)->vcgn_uii.key.k.ipv4 = clib_net_to_host_u32(ip->src_addr); - - PLATFORM_CNAT_SET_RX_VRF(vnet_buffer(b0)->sw_if_index[VLIB_RX], - ki.k.k.vrf, CNAT_UDP) - - ki.k.k.ipv4 = clib_net_to_host_u32(ip->src_addr); - - - /* MUST REVISIT: commentting frag check. Unconditional destination port - * update. DONOT remove this #if 0 */ - ki.k.k.port = - clib_net_to_host_u16(udp->src_port); - dest_info.k.port = - clib_net_to_host_u16(udp->dest_port); -#if 0 - if(PREDICT_FALSE(ctx->ru.rx.frag)) { -#ifdef TOBE_PORTED - /* Must have routed through cnat_v4_frag_in2out node */ - u16 *feature_data_ports = (u16 *)&ctx->feature_data[2]; - ki.k.k.port = *feature_data_ports; - feature_data_ports++; - dest_info.k.port = *feature_data_ports; -#endif - } else { - ki.k.k.port = - clib_net_to_host_u16(udp->src_port); - dest_info.k.port = - clib_net_to_host_u16(udp->dest_port); - } -#endif /* if 0 */ - - dest_info.k.ipv4 = clib_net_to_host_u32(ip->dest_addr); - PLATFORM_CNAT_SET_RX_VRF(vnet_buffer(b0)->sw_if_index[VLIB_RX], - dest_info.k.vrf, CNAT_UDP) - - if (PREDICT_TRUE(ki.k.k.port)) { - if (ki.k.k.port & 0x1) { - db = cnat_get_main_db_entry_v2(&ki, PORT_S_ODD, PORT_TYPE_DYNAMIC, - &info, &dest_info); - } else { - db = cnat_get_main_db_entry_v2(&ki, PORT_S_EVEN, PORT_TYPE_DYNAMIC, - &info, &dest_info); - } - } else { - /* - * No UDP port value of 0 - drop it - */ - db = NULL; - info.error = CNAT_ERR_BAD_TCP_UDP_PORT; - } - - if (PREDICT_TRUE((u64)db)) { - - if (PLATFORM_HANDLE_TTL_DECREMENT) { - /* - * Decrement TTL and update IPv4 checksum - */ - ipv4_decr_ttl_n_calc_csum(ip); - } - - /* - * step 6 do nat before fwd pkt - */ - swap_ip_src_udp_port(ip, udp, db); - /* - * update db for this pkt - */ - CNAT_DB_UPDATE_IN2OUT_TIMER - - /* Check timeout db if there is config for this */ - (void) query_and_update_db_timeout((void *)db, MAIN_DB_TYPE); - -/* Temporarily keeping it commented */ - //PLATFORM_CNAT_SET_TX_VRF(vnet_buffer(b0)->sw_if_index[VLIB_TX], - // db->out2in_key.k.vrf) - in2out_forwarding_count++; - - } else { - switch (info.error) { - case (CNAT_NO_VRF_RUN): - em->counters[node_counter_base_index + CNAT_V4_UDP_I2O_DR_PKT] += 1; - break; - case (CNAT_OUT_LIMIT): - em->counters[node_counter_base_index + CNAT_V4_UDP_I2O_DO_PKT] += 1; - break; - case (CNAT_NO_PORT_ANY): - case (CNAT_NO_POOL_ANY): - case (CNAT_BAD_INUSE_ANY): - case (CNAT_NOT_FOUND_ANY): - em->counters[node_counter_base_index + CNAT_V4_UDP_I2O_DA_PKT] += 1; - break; - case (CNAT_INV_PORT_DIRECT): - case (CNAT_DEL_PORT_DIRECT): - case (CNAT_BAD_INUSE_DIRECT): - case (CNAT_NOT_FOUND_DIRECT): - em->counters[node_counter_base_index + CNAT_V4_UDP_I2O_DD_PKT] += 1; - break; - case (CNAT_ERR_BAD_TCP_UDP_PORT): - em->counters[node_counter_base_index + CNAT_V4_UDP_I2O_DI_PKT] += 1; - break; - case (CNAT_ERR_NO_SESSION_DB): - em->counters[node_counter_base_index + CNAT_V4_UDP_I2O_DS_PKT] += 1; - break; - default: - em->counters[node_counter_base_index + CNAT_V4_UDP_I2O_DC_PKT] += 1; - break; - } - /* - * send to icmp msg generate node - */ - if (info.gen_icmp_msg == CNAT_ICMP_MSG) { -#ifdef TOBE_PORTED - u32 *fd = (u32*)ctx->feature_data; - fd[0] = info.svi_addr; - fd[1] = CNAT_ICMP_DEST_UNREACHABLE; -#endif - disposition = CNAT_V4_ICMP_G_I2O_T; - counter = CNAT_V4_ICMP_G_I2O_T_PKT; - } else { - disposition = CNAT_V4_UDP_I2O_D; - counter = CNAT_V4_UDP_I2O_D_PKT; - } - DEBUG_I2O_DROP(CNAT_DEBUG_DROP_UDP) - } - - em->counters[node_counter_base_index + counter] += 1; - - return disposition; -} - - -#include - -static uword cnat_ipv4_udp_inside_input_exc_node_fn (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return dispatch_pipeline (vm, node, frame); -} - -VLIB_REGISTER_NODE (cnat_ipv4_udp_inside_input_exc_node) = { - .function = cnat_ipv4_udp_inside_input_exc_node_fn, - .name = "vcgn-v4-udp-i2o-e", - .vector_size = sizeof (u32), - .type = VLIB_NODE_TYPE_INTERNAL, - - .n_errors = ARRAY_LEN(cnat_ipv4_udp_inside_input_exc_error_strings), - .error_strings = cnat_ipv4_udp_inside_input_exc_error_strings, - - .n_next_nodes = CNAT_V4_UDP_INSIDE_INPUT_EXC_N_NEXT, - - /* edit / add dispositions here */ - .next_nodes = { - [CNAT_V4_UDP_I2O_T] = "ip4-input", - [CNAT_V4_UDP_I2O_D] = "error-drop", - }, -}; - - -clib_error_t *cnat_ipv4_udp_inside_input_exc_init (vlib_main_t *vm) -{ - cnat_ipv4_udp_inside_input_exc_main_t * mp = &cnat_ipv4_udp_inside_input_exc_main; - - mp->vlib_main = vm; - mp->vnet_main = vnet_get_main(); - - return 0; -} - -VLIB_INIT_FUNCTION (cnat_ipv4_udp_inside_input_exc_init); - diff --git a/plugins/plugins/vcgn/cnat_ipv4_udp_outside_input.c b/plugins/plugins/vcgn/cnat_ipv4_udp_outside_input.c deleted file mode 100644 index 5a24a111..00000000 --- a/plugins/plugins/vcgn/cnat_ipv4_udp_outside_input.c +++ /dev/null @@ -1,605 +0,0 @@ - -/* - *--------------------------------------------------------------------------- - * cnat_ipv4_udp_outside_input_stages.c - cnat_ipv4_udp_outside_input node pipeline stage functions - * - * - * Copyright (c) 2008-2014 Cisco and/or its affiliates. - * 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 -#include -#include -#include - -#include "cnat_ipv4_udp.h" -#include "dslite_db.h" -#include "cnat_db.h" -#include "cnat_v4_functions.h" - -//#include -//#include -//#include "cnat_va_db.h" - -#define foreach_cnat_ipv4_udp_outside_input_error \ -_(CNAT_V4_UDP_O2I_T_PKT, "v4 udp o2i transmit") \ -_(CNAT_V4_DSLITE_ENCAP_CTR, "to dslite encap") \ -_(CNAT_V4_UDP_O2I_MISS_PKT, "v4 udp o2i db miss drop") \ -_(CNAT_V4_UDP_O2I_TTL_GEN, "v4 udp o2i TTL gen") \ -_(CNAT_V4_UDP_O2I_TTL_DROP, "v4 udp o2i TTL drop") \ -_(CNAT_V4_UDP_O2I_PTB_GEN, "v4 ptb gen") \ -_(CNAT_V4_UDP_O2I_PTB_DROP, "v4 ptb throttle drop") \ -_(CNAT_V4_UDP_O2I_SESSION_DROP, "v4 udp o2i session drop") \ -_(CNAT_V4_UDP_O2I_FILTER_DROP, "v4 udp o2i drop: end point filtering") \ -_(CNAT_V4_UDP_O2I_SUB_FRAG_NO_DB_DROP, "v4 udp o2i subsequent frag no DB drop") \ -_(CNAT_V4_UDP_O2I_1ST_FRAG_FILTER_DROP, "v4 udp i2o 1st frag filter drop") - -typedef enum { -#define _(sym,str) sym, - foreach_cnat_ipv4_udp_outside_input_error -#undef _ - CNAT_IPV4_UDP_OUTSIDE_INPUT_N_ERROR, -} cnat_ipv4_udp_outside_input_t; - -static char * cnat_ipv4_udp_outside_input_error_strings[] = { -#define _(sym,string) string, - foreach_cnat_ipv4_udp_outside_input_error -#undef _ -}; - -typedef struct { - u32 cached_next_index; - /* $$$$ add data here */ - - /* convenience variables */ - vlib_main_t * vlib_main; - vnet_main_t * vnet_main; -} cnat_ipv4_udp_outside_input_main_t; - -typedef enum { - //CNAT_V4_O2I_FIXME, - CNAT_V4_UDP_O2I_E, - CNAT_V4_UDP_O2I_T, - CNAT_V4_UDP_O2I_NEXT, -} cnat_ipv4_udp_outside_input_next_t; - -//#define CNAT_V4_DSLITE_ENCAP CNAT_V4_O2I_FIXME -//#define CNAT_V4_UDP_O2I_E CNAT_V4_O2I_FIXME - -cnat_ipv4_udp_outside_input_main_t cnat_ipv4_udp_outside_input_main; -vlib_node_registration_t cnat_ipv4_udp_outside_input_node; - -#define NSTAGES 6 - -/* - * Use the generic buffer metadata + first line of packet data prefetch - * stage function from . This is usually a Good Idea. - */ -#define stage0 generic_stage0 - - -#if 0 -typedef struct cnat_ipv4_udp_outside_input_pipeline_data_ { - //spp_node_main_vector_t *nmv; - dslite_common_pipeline_data_t common_data; - /* Add additional pipeline stage data here... */ - u32 bucket; -#ifdef DSLITE_DEF - u32 user_bucket; - dslite_v4_to_v6_udp_counter_t *udp_counter; - dslite_icmp_gen_counter_t *icmp_gen_counter; - -#endif - cnat_key_t ki; - udp_hdr_type_t *udp; - u8 frag_pkt; -} cnat_ipv4_udp_outside_input_pipeline_data_t; - -#endif - -#define CNAT_UDP_OUTSIDE_UPDATE_FLAG_TIMER(db,dslite_nat44_inst_id) \ - if (PREDICT_FALSE(!(db->flags & CNAT_DB_FLAG_UDP_ACTIVE))) { \ - db->flags |= CNAT_DB_FLAG_UDP_ACTIVE; \ - CNAT_DB_TIMEOUT_RST(db); \ - } else if (PREDICT_FALSE(db->flags & CNAT_DB_DSLITE_FLAG)) { \ - if (PREDICT_TRUE(dslite_table_db_ptr[dslite_nat44_inst_id].mapping_refresh_both_direction)) { \ - CNAT_DB_TIMEOUT_RST(db); \ - } \ - } else if (PREDICT_TRUE(mapping_refresh_both_direction)) { \ - CNAT_DB_TIMEOUT_RST(db); \ - } \ - -#if 0 -static cnat_ipv4_udp_outside_input_pipeline_data_t pctx_data[SPP_MAXDISPATCH]; -#define EXTRA_PIPELINE_ARGS_PROTO , cnat_ipv4_udp_outside_input_pipeline_data_t *pctx -#define EXTRA_PIPELINE_ARGS , pctx - -#endif - -/*inline u32 -is_static_dest_nat_enabled(u16 vrf) -{ - if(static_dest_vrf_map_array[vrf] == 1) { - return CNAT_SUCCESS; - } - return CNAT_NO_CONFIG; -}*/ - -static inline void __attribute__((unused)) -swap_ip_dst(ipv4_header *ip, cnat_main_db_entry_t *db, u16 vrf) -{ - - CNAT_UPDATE_L3_CHECKSUM_DECLARE - /* - * calculate checksum - */ - CNAT_UPDATE_L3_CHECKSUM(((u16)(db->out2in_key.k.ipv4)), - ((u16)(db->out2in_key.k.ipv4 >> 16)), - (clib_host_to_net_u16(ip->checksum)), - ((u16)(db->in2out_key.k.ipv4)), - ((u16)(db->in2out_key.k.ipv4 >> 16))) - //set ip header - ip->dest_addr = - clib_host_to_net_u32(db->in2out_key.k.ipv4); - ip->checksum = - clib_host_to_net_u16(new_l3_c); - -#if 0 - - if(is_static_dest_nat_enabled(vrf) == CNAT_SUCCESS) { - direction = 1; - if(cnat_static_dest_db_get_translation(ip->src_addr, &postmap_ip, vrf, direction) == CNAT_SUCCESS) { - old_ip = spp_net_to_host_byte_order_32(&(ip->src_addr)); - old_postmap_ip = spp_net_to_host_byte_order_32(&postmap_ip); - - CNAT_UPDATE_L3_CHECKSUM(((u16)(old_ip & 0xFFFF)), - ((u16)(old_ip >> 16)), - (spp_net_to_host_byte_order_16(&(ip->checksum))), - ((u16)(old_postmap_ip & 0xFFFF)), - ((u16)(old_postmap_ip >> 16))) - ip->checksum = - clib_host_to_net_u16(new_l3_c); - ip->src_addr = postmap_ip; - } - } -#endif -} - -inline void swap_ip_dst_udp_port(ipv4_header *ip, - udp_hdr_type_t *udp, - cnat_main_db_entry_t *db, u16 vrf) -{ - -#define UDP_PACKET_DEBUG 1 - -// Temporary debugs which will be suppressed later -#ifdef UDP_PACKET_DEBUG - if (PREDICT_FALSE(udp_outside_packet_dump_enable)) { - printf("\nOut2In UDP packet before translation"); - print_udp_pkt(ip); - } -#endif - -#if 0 - if(is_static_dest_nat_enabled(vrf) == CNAT_SUCCESS) { - direction = 1; - if(cnat_static_dest_db_get_translation(ip->src_addr, &postmap_ip, vrf, direction) == CNAT_SUCCESS) { - - CNAT_UPDATE_L3_L4_CHECKSUM_DECLARE - - old_ip = spp_net_to_host_byte_order_32(&(ip->src_addr)); - old_postmap_ip = spp_net_to_host_byte_order_32(&postmap_ip); - - CNAT_UPDATE_L3_L4_CHECKSUM(((u16)(old_ip & 0xFFFF)), - ((u16)(old_ip >> 16)), - (spp_net_to_host_byte_order_16(&(udp->src_port))), - (spp_net_to_host_byte_order_16(&(ip->checksum))), - (spp_net_to_host_byte_order_16(&(udp->udp_checksum))), - ((u16)(old_postmap_ip & 0xFFFF)), - ((u16)(old_postmap_ip >> 16)), - (spp_net_to_host_byte_order_16(&(udp->src_port)))) - - ip->checksum = - clib_host_to_net_u16(new_l3_c); - ip->src_addr = postmap_ip; - if (PREDICT_TRUE(udp->udp_checksum)) { - udp->udp_checksum = clib_host_to_net_u16(new_l4_c); - } - } - } -#endif - /* - * declare variable - */ - CNAT_UPDATE_L3_L4_CHECKSUM_DECLARE - /* - * calculate checksum - */ - CNAT_UPDATE_L3_L4_CHECKSUM(((u16)(db->out2in_key.k.ipv4)), - ((u16)(db->out2in_key.k.ipv4 >> 16)), - (db->out2in_key.k.port), - (clib_net_to_host_u16(ip->checksum)), - (clib_net_to_host_u16(udp->udp_checksum)), - ((u16)(db->in2out_key.k.ipv4)), - ((u16)(db->in2out_key.k.ipv4 >> 16)), - (db->in2out_key.k.port)) - - - - - //set ip header - ip->dest_addr = - clib_host_to_net_u32(db->in2out_key.k.ipv4); - ip->checksum = - clib_host_to_net_u16(new_l3_c); - - //set udp header - udp->dest_port = - clib_host_to_net_u16(db->in2out_key.k.port); - - /* - * No easy way to avoid this if check except by using - * complex logic - may not be worth it. - */ - if (PREDICT_TRUE(udp->udp_checksum)) { - udp->udp_checksum = clib_host_to_net_u16(new_l4_c); - } - - - -// Temporary debugs which will be suppressed later -#ifdef UDP_PACKET_DEBUG - if (PREDICT_FALSE(udp_outside_checksum_disable)) { - printf("\nOut2In UDP checksum 0x%x disabled by force", new_l4_c); - udp->udp_checksum = 0; - } - if (PREDICT_FALSE(udp_outside_packet_dump_enable)) { - printf("\nOut2In UDP packet after translation"); - print_udp_pkt(ip); - } -#endif -} - -static inline void -stage1(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) -{ - u64 a, b, c; - u32 bucket; - u8 *prefetch_target; - - vlib_buffer_t * b0 = vlib_get_buffer (vm, buffer_index); - ipv4_header *ip = vlib_buffer_get_current (b0); - u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; - udp_hdr_type_t *udp = (udp_hdr_type_t *)((u8*)ip + ipv4_hdr_len); - - u64 tmp = 0; - tmp = vnet_buffer(b0)->vcgn_uii.key.k.ipv4 = - clib_net_to_host_u32(ip->dest_addr); - vnet_buffer(b0)->vcgn_uii.key.k.port = - clib_net_to_host_u16 (udp->dest_port); - - tmp |= ((u64)vnet_buffer(b0)->vcgn_uii.key.k.port) << 32; - - PLATFORM_CNAT_SET_RX_VRF(vnet_buffer(b0)->sw_if_index[VLIB_RX], - vnet_buffer(b0)->vcgn_uii.key.k.vrf, - CNAT_UDP) - tmp |= ((u64)vnet_buffer(b0)->vcgn_uii.key.k.vrf) << 48; - - CNAT_V4_GET_HASH(tmp, bucket, CNAT_MAIN_HASH_MASK) - - prefetch_target = (u8 *)(&cnat_out2in_hash[bucket]); - vnet_buffer(b0)->vcgn_uii.bucket = bucket; - - /* Prefetch the hash bucket */ - CLIB_PREFETCH(prefetch_target, CLIB_CACHE_LINE_BYTES, LOAD); -} - -static inline void -stage2(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) -{ /* nothing */ } - -#define SPP_LOG2_CACHE_LINE_BYTES 6 -#define SPP_CACHE_LINE_BYTES (1 << SPP_LOG2_CACHE_LINE_BYTES) - -static inline void -stage3(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) -{ - vlib_buffer_t * b0 = vlib_get_buffer(vm, buffer_index); - uword prefetch_target0, prefetch_target1; - u32 bucket = vnet_buffer(b0)->vcgn_uii.bucket; - - /* read the hash bucket */ - u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket - = cnat_out2in_hash[bucket].next; - - if (PREDICT_TRUE(db_index != EMPTY)) { - /* - * Prefetch database keys. We save space by not cache-line - * aligning the DB entries. We don't want to waste LSU - * bandwidth prefetching stuff we won't need. - */ - prefetch_target0 = (uword)(cnat_main_db + db_index); - CLIB_PREFETCH((void*)prefetch_target0, CLIB_CACHE_LINE_BYTES, STORE); - /* Just beyond DB key #2 */ - prefetch_target1 = prefetch_target0 + - STRUCT_OFFSET_OF(cnat_main_db_entry_t, user_ports); - /* If the targets are in different lines, do the second prefetch */ - if (PREDICT_FALSE((prefetch_target0 & ~(SPP_CACHE_LINE_BYTES-1)) != - (prefetch_target1 & ~(SPP_CACHE_LINE_BYTES-1)))) { - CLIB_PREFETCH((void *)prefetch_target1, CLIB_CACHE_LINE_BYTES, STORE); - } - } -} - -static inline void -stage4(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) -{ - cnat_main_db_entry_t *db; - vlib_buffer_t * b0 = vlib_get_buffer(vm, buffer_index); - u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket; - - /* - * Note: if the search already failed (empty bucket), - * the answer is already in the pipeline context structure - */ - if (PREDICT_TRUE(db_index != EMPTY)) { - - /* - * Note: hash collisions suck. We can't easily prefetch around them. - * The first trip around the track will be fast. After that, maybe - * not so much... - */ - do { - db = cnat_main_db + db_index; - if (PREDICT_TRUE(db->out2in_key.key64 == - vnet_buffer(b0)->vcgn_uii.key.key64)) { - break; - } - db_index = db->out2in_hash.next; - } while (db_index != EMPTY); - - /* Stick the answer back into the pipeline context structure */ - vnet_buffer(b0)->vcgn_uii.bucket = db_index; - } -} - -#if 0 - -ALWAYS_INLINE( -static inline void -stage5(spp_ctx_t **ctxs, int index, spp_node_t *np, - u8 *disp_used EXTRA_PIPELINE_ARGS_PROTO)) -{ - spp_ctx_t *ctx = ctxs[index]; - u32 db_index = pctx[index].bucket; - /* for nat44, dslite_id will be 1 */ - u16 dslite_id = *(pctx[index].common_data.dslite_id_ptr); - - DSLITE_PREFETCH_COUNTER(pctx[index].udp_counter, - &dslite_all_counters[dslite_id].v46_udp_counters, - dslite_v4_to_v6_udp_counter_t, - v4_to_v6_udp_output_count, - "V4_TO_V6_UDP") - - DSLITE_PREFETCH_COUNTER(pctx[index].icmp_gen_counter, - &dslite_all_counters[dslite_id].dslite_icmp_gen_counters, - dslite_icmp_gen_counter_t, - v6_icmp_gen_count, - "V4_TO_V6_icmp") - -if (PREDICT_TRUE(db_index != EMPTY)) { - cnat_main_db_entry_t *db = cnat_main_db + db_index; - - u32 user_db_index = db->user_index; - DSLITE_PRINTF(1, "UDP o2i, db entry found %u %u %u\n", - db_index, user_db_index, - db->dslite_nat44_inst_id); - uword prefetch_target0 = (uword)(cnat_user_db + user_db_index); - SPP_PREFETCH(prefetch_target0, 0, LOAD); - pctx[index].user_bucket = user_db_index; - DSLITE_PRINTF(1, "UDP: Done with prefetch..\n"); -} else { - DSLITE_PRINTF(1, "UDP: Stage 5, db_index empty...\n"); -} -} - -#endif - - -static inline u32 last_stage (vlib_main_t *vm, vlib_node_runtime_t *node, - u32 bi) -{ - - vlib_buffer_t *b0 = vlib_get_buffer (vm, bi); - u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket; - //spp_ctx_t *ctx = (spp_ctx_t *) &vnet_buffer(b0)->vcgn_uii; - int disposition = CNAT_V4_UDP_O2I_T; - int counter = CNAT_V4_UDP_O2I_T_PKT; - ipv4_header *ip = (ipv4_header *)vlib_buffer_get_current(b0); - u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; - udp_hdr_type_t *udp = (udp_hdr_type_t *)((u8*)ip + ipv4_hdr_len); - vlib_node_t *n = vlib_get_node (vm, cnat_ipv4_udp_outside_input_node.index); - u32 node_counter_base_index = n->error_heap_index; - vlib_error_main_t * em = &vm->error_main; - cnat_session_entry_t *session_db = NULL; - cnat_main_db_entry_t *db = NULL; - cnat_key_t dest_info; - u16 dslite_nat44_inst_id __attribute__((unused)) = 0; - - dest_info.k.port = clib_net_to_host_u16(udp->src_port); - dest_info.k.ipv4 = clib_net_to_host_u32(ip->src_addr); - - if (PREDICT_TRUE(db_index != EMPTY)) { - /* TTL gen was disabled for nat44 earlier - * But since dslite has got integrated in this - * TTL gen is enabled - */ - - db = cnat_main_db + db_index; - if (PLATFORM_HANDLE_TTL_DECREMENT) { - /* - * Decrement TTL and update IPv4 checksum - */ - ipv4_decr_ttl_n_calc_csum(ip); - } - if(PREDICT_TRUE(!PLATFORM_DBL_SUPPORT)) { - - /* No DBL support, so just update the destn and proceed */ - db->dst_ipv4 = dest_info.k.ipv4; - db->dst_port = dest_info.k.port; - CNAT_UDP_OUTSIDE_UPDATE_FLAG_TIMER(db, 0) - goto update_pkt; - } - - - if(PREDICT_TRUE((db->dst_ipv4 == dest_info.k.ipv4) && - (db->dst_port == dest_info.k.port))) { - - CNAT_UDP_OUTSIDE_UPDATE_FLAG_TIMER(db, 0) - goto update_pkt; - } else { - /* The session entries belonging to this entry are checked to find - * if an entry exist whose destination IP and port match with the - * source IP and port of the packet being processed - */ - dest_info.k.vrf = db->in2out_key.k.vrf; - - if (PREDICT_FALSE(db->nsessions == 0)) { - /* Should be a static entry - * Note this session as the first session and log - */ - cnat_add_dest_n_log(db, &dest_info); - CNAT_UDP_OUTSIDE_UPDATE_FLAG_TIMER(db, 0) - - } else if(PREDICT_TRUE(db->nsessions == 1)) { - - /* Destn is not same as in main db. Multiple session - * scenario - */ - dest_info.k.vrf = db->in2out_key.k.vrf; - session_db = cnat_handle_1to2_session(db, &dest_info); - - if(PREDICT_FALSE(session_db == NULL)) { - disposition = CNAT_V4_UDP_O2I_E; - counter = CNAT_V4_UDP_O2I_SESSION_DROP; - goto drop_pkt; - } - - /* update session_db(cur packet) timer */ - CNAT_UDP_OUTSIDE_UPDATE_FLAG_TIMER(session_db, 0) - } else { - /* More 2 sessions exists */ - - dest_info.k.vrf = db->in2out_key.k.vrf; - - /* If session already exists, - * cnat_create_session_db_entry will return the existing db - * else create a new db - * If could not create, return NULL - */ - session_db = cnat_create_session_db_entry(&dest_info, - db, TRUE); - - if(PREDICT_FALSE(session_db != NULL)) { - /* session exists */ - CNAT_UDP_OUTSIDE_UPDATE_FLAG_TIMER(session_db, 0) - } else { - /* could not create session db - drop packet */ - disposition = CNAT_V4_UDP_O2I_E; - counter = CNAT_V4_UDP_O2I_SESSION_DROP; - goto drop_pkt; - } - } - } - -update_pkt: - - /* - * 1. update dest ipv4 addr and dest udp port - * 2. update ipv4 checksum and udp checksum - */ - //swap_ip_dst(ip, db, db->in2out_key.k.vrf); - swap_ip_dst_udp_port(ip, udp, db, db->in2out_key.k.vrf); - //DSLITE_PRINTF(1, "Done with swap_ip_dst_udp_port..\n"); - - db->out2in_pkts++; - - nat44_dslite_global_stats[0].out2in_forwarding_count++; - - /* #### Temporarily COMMENTED FOR IP ROUTE LOOKUP ISSUE #### */ - - //PLATFORM_CNAT_SET_TX_VRF(vnet_buffer(b0)->sw_if_index[VLIB_TX], - // db->in2out_key.k.vrf) - } else { - disposition = CNAT_V4_UDP_O2I_E; - counter = CNAT_V4_UDP_O2I_MISS_PKT; - /* for NAT44 dslite_id would be 1 */ - nat44_dslite_common_stats[0].no_translation_entry_drops ++; - } - -drop_pkt: - - em->counters[node_counter_base_index + counter] += 1; - return disposition; -} - -#include - -static uword cnat_ipv4_udp_outside_input_node_fn (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return dispatch_pipeline (vm, node, frame); -} - - -VLIB_REGISTER_NODE (cnat_ipv4_udp_outside_input_node) = { - .function = cnat_ipv4_udp_outside_input_node_fn, - .name = "vcgn-v4-udp-o2i", - .vector_size = sizeof (u32), - .type = VLIB_NODE_TYPE_INTERNAL, - - .n_errors = ARRAY_LEN(cnat_ipv4_udp_outside_input_error_strings), - .error_strings = cnat_ipv4_udp_outside_input_error_strings, - - .n_next_nodes = CNAT_V4_UDP_O2I_NEXT, - - /* edit / add dispositions here */ -#if 0 - .next_nodes = { - //[CNAT_V4_O2I_FIXME] = "error-drop", - //[CNAT_V4_UDP_O2I_E] = "vcgn-v4-udp-o2i-e", - [CNAT_V4_UDP_O2I_E] = "vcgn-v4-udp-o2i-e", - [CNAT_V4_UDP_O2I_T] = "ip4-input", - }, -#endif - .next_nodes = { - [CNAT_V4_UDP_O2I_E] = "error-drop", - [CNAT_V4_UDP_O2I_T] = "ip4-input", - }, - -}; - -clib_error_t *cnat_ipv4_udp_outside_input_init (vlib_main_t *vm) -{ - cnat_ipv4_udp_outside_input_main_t * mp = &cnat_ipv4_udp_outside_input_main; - - mp->vlib_main = vm; - mp->vnet_main = vnet_get_main(); - - return 0; -} - -VLIB_INIT_FUNCTION (cnat_ipv4_udp_outside_input_init); diff --git a/plugins/plugins/vcgn/cnat_log_api.h b/plugins/plugins/vcgn/cnat_log_api.h deleted file mode 100644 index 60cf6836..00000000 --- a/plugins/plugins/vcgn/cnat_log_api.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - *------------------------------------------------------------------ - * cnat_log_api.h - * Declraes the common APIs for logging (both syslog and NFV9) - * Copyright (c) 2013, 20122 Cisco and/or its affiliates. - * 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 __CNAT_LOG_API_H__ -#define __CNAT_LOG_API_H__ - -#include "cnat_logging.h" - -static inline void cnat_log_ds_lite_mapping_delete(cnat_main_db_entry_t *db, - dslite_table_entry_t *dslite_entry -#ifndef NO_BULK_LOGGING - , int bulk_alloc -#endif - ) -{ - return; -} - -static inline void cnat_log_ds_lite_mapping_create(cnat_main_db_entry_t *db, - dslite_table_entry_t *dslite_entry -#ifndef NO_BULK_LOGGING - , int bulk_alloc -#endif - ) -{ - return; -} - -static inline void cnat_log_ds_lite_port_limit_exceeded( - dslite_key_t * key, - dslite_table_entry_t *dslite_entry_ptr) -{ - return; - -} - -static inline void cnat_log_nat44_port_limit_exceeded( - cnat_key_t * key, - cnat_vrfmap_t *vrfmap) -{ - return; -} -static inline void cnat_log_nat44_mapping_create(cnat_main_db_entry_t *db, - cnat_vrfmap_t *vrfmap -#ifndef NO_BULK_LOGGING - , int bulk_alloc -#endif - ) -{ - return; -} - -static inline void cnat_log_nat44_mapping_delete(cnat_main_db_entry_t *db, - cnat_vrfmap_t *vrfmap -#ifndef NO_BULK_LOGGING - , int bulk_alloc -#endif - ) -{ - return; -} - -/* Session Logging API for nat44 */ -static inline void cnat_session_log_nat44_mapping_create ( - cnat_main_db_entry_t *db, - cnat_session_entry_t *sdb, - cnat_vrfmap_t *vrfmap ) -{ - return; -} - -static inline void cnat_session_log_nat44_mapping_delete ( - cnat_main_db_entry_t *db, - cnat_session_entry_t *sdb, - cnat_vrfmap_t *vrfmap ) -{ - return; -} - -/* Session Logging API for dslite */ -static inline void cnat_session_log_ds_lite_mapping_create ( - cnat_main_db_entry_t *db, - dslite_table_entry_t *dslite_entry, - cnat_session_entry_t *sdb ) -{ - return; -} - -static inline void cnat_session_log_ds_lite_mapping_delete ( - cnat_main_db_entry_t *db, - dslite_table_entry_t *dslite_entry, - cnat_session_entry_t *sdb ) -{ - return; -} - -#endif /* #ifndef __CNAT_LOG_API_H__ */ - diff --git a/plugins/plugins/vcgn/cnat_log_common.h b/plugins/plugins/vcgn/cnat_log_common.h deleted file mode 100644 index 52731bc0..00000000 --- a/plugins/plugins/vcgn/cnat_log_common.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - *------------------------------------------------------------------ - * cnat_log_common.h - * Contains macros and definitions that are common to both syslog and nfv9 - * Copyright (c) 2011-2012 Cisco and/or its affiliates. - * 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 __CNAT_LOG_COMMON_H__ -#define __CNAT_LOG_COMMON_H__ - -#include -#include -#include - -#include "cnat_db.h" -#include "nat64_db.h" -#include "spp_timers.h" -#include "spp_ctx.h" - -/* - * This corresponds to the length of the IMETRO SHIM Header for RODDICK - * For non-roddick cases, introduce an Ethernet header as well - */ -#if 0 - #if defined(TARGET_RODDICK) - #define CNAT_NFV9_SHIM_HDR_OFFSET 8 - #define CNAT_NFV9_L2_ENCAPS_OFFSET 0 - #else - #define CNAT_NFV9_SHIM_HDR_OFFSET 0 - #define CNAT_NFV9_L2_ENCAPS_OFFSET 16 - #endif -#endif - - #define CNAT_NFV9_IP_HDR_OFFSET 0 - - #define CNAT_NFV9_UDP_HDR_OFFSET \ - (CNAT_NFV9_IP_HDR_OFFSET + sizeof(ipv4_header)) - - #define CNAT_NFV9_HDR_OFFSET \ - (CNAT_NFV9_UDP_HDR_OFFSET + sizeof(udp_hdr_type_t)) - -u32 cnat_get_sys_up_time_in_ms(void); -u32 cnat_get_unix_time_in_seconds(void); -void cnat_dump_time_change_logs(void); -void cnat_handle_sys_time_change (time_t current_unix_time); -/* - * Maximum number of time log changes we maintain - */ - -#define MAX_TIME_CHANGE_LOGS (8) - -typedef struct { - /* - * A timer structure to periodically send NFv9 & syslog logging packets - * that have been waiting to be full for a long time. This will - * ensure add/delete events don't get delayed too much before they - * are sent to the collector. - */ - spp_timer_t log_timer; - - /* - * Whether we have initialized the NFv9 information - */ - u8 cnat_log_init_done; -} cnat_log_global_info_t; - -#endif /* __CNAT_LOG_COMMON_H__ */ diff --git a/plugins/plugins/vcgn/cnat_logging.c b/plugins/plugins/vcgn/cnat_logging.c deleted file mode 100644 index 50805d11..00000000 --- a/plugins/plugins/vcgn/cnat_logging.c +++ /dev/null @@ -1,3518 +0,0 @@ -/* - *------------------------------------------------------------------ - * cnat_logging.c - * - * Copyright (c) 2009-2013 Cisco and/or its affiliates. - * 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 -#include -#include -#include -#include -#include -#include -#include -#include - - -#include "cnat_config.h" -#include "cnat_global.h" -#include "cnat_v4_functions.h" -#include "tcp_header_definitions.h" -#include "cnat_v4_ftp_alg.h" -#include "cnat_logging.h" -#include "platform_common.h" - -#define CNAT_NFV9_DEBUG_CODE 2 -#if CNAT_NFV9_DEBUG_CODE > 3 - -#define NFV9_COND if ((my_instance_number != 0) && (my_instance_number != 15)) - -#define NFV9_DEBUG_PRINTF1(a) NFV9_COND printf(a); -#define NFV9_DEBUG_PRINTF2(a, b) NFV9_COND printf(a, b); -#define NFV9_DEBUG_PRINTF3(a, b, c) NFV9_COND printf(a, b, c); -#define NFV9_DEBUG_PRINTF4(a, b, c, d) NFV9_COND printf(a, b, c, d); - -#else - -#define NFV9_DEBUG_PRINTF1(a) -#define NFV9_DEBUG_PRINTF2(a, b) -#define NFV9_DEBUG_PRINTF3(a, b, c) -#define NFV9_DEBUG_PRINTF4(a, b, c, d) - -#endif - -static void cnat_nfv9_insert_ingress_vrfid_name_record(cnat_nfv9_logging_info_t *nfv9_logging_info, u16 index); -void cnat_nfv9_ingress_vrfid_name_mapping_create( - cnat_nfv9_logging_info_t *nfv9_logging_info); - - -cnat_nfv9_global_info_t cnat_nfv9_global_info; - -cnat_nfv9_template_t cnat_nfv9_template_info; - -#define CNAT_NFV9_OPTION_TEMPLATE cnat_nfv9_template_info.cnat_nfv9_option_template - -u16 cnat_template_id[MAX_RECORDS] = - {0, CNAT_NFV9_ADD_TEMPLATE_ID, CNAT_NFV9_DEL_TEMPLATE_ID, - CNAT_NFV9_NAT64_ADD_BIB_TEMPLATE_ID,CNAT_NFV9_NAT64_DEL_BIB_TEMPLATE_ID, - CNAT_NFV9_NAT64_ADD_SESSION_TEMPLATE_ID, - CNAT_NFV9_NAT64_DEL_SESSION_TEMPLATE_ID, - CNAT_NFV9_DS_LITE_ADD_TEMPLATE_ID, - CNAT_NFV9_DS_LITE_DEL_TEMPLATE_ID -#ifndef NO_BULK_LOGGING - , CNAT_NFV9_NAT44_BULK_ADD_TEMPLATE_ID, - CNAT_NFV9_NAT44_BULK_DEL_TEMPLATE_ID, - CNAT_NFV9_DS_LITE_BULK_ADD_TEMPLATE_ID, - CNAT_NFV9_DS_LITE_BULK_DEL_TEMPLATE_ID -#endif /* #ifndef NO_BULK_LOGGING */ - , CNAT_NFV9_INGRESS_VRF_ID_NAME_TEMPLATE_ID, - CNAT_NFV9_NAT44_ADD_SESSION_TEMPLATE_ID, - CNAT_NFV9_NAT44_DEL_SESSION_TEMPLATE_ID, - CNAT_NFV9_DS_LITE_ADD_SESSION_TEMPLATE_ID, - CNAT_NFV9_DS_LITE_DEL_SESSION_TEMPLATE_ID - }; - -/* - * Logging information structures - */ -cnat_nfv9_logging_info_t cnat_default_nfv9_logging_info; -cnat_nfv9_logging_info_t *cnat_nfv9_logging_info_pool; -#define NFV9_SERVER_POOL_SIZE 16 -nfv9_server_info_t *nfv9_server_info_pool; - -u32 nfv9_src_id = 0; - -u32 -cnat_get_sys_up_time_in_ms (void) -{ - vlib_main_t * vm = vlib_get_main(); - u32 cnat_curr_time; - - cnat_curr_time = (u32)vlib_time_now (vm); - return cnat_curr_time; -} - -void -cnat_dump_time_change_logs (void) -{ - return; -} - -inline void cnat_nfv9_handle_sys_time_change(time_t current_unix_time) -{ - return; - #if 0 - cnat_handle_sys_time_change(current_unix_time); - #endif -} - -void cnat_nfv9_update_sys_time_change() -{ - cnat_nfv9_logging_info_t *my_nfv9_logging_info = NULL; - pool_foreach (my_nfv9_logging_info, cnat_nfv9_logging_info_pool, ({ - nfv9_server_info_t *server = nfv9_server_info_pool + - my_nfv9_logging_info->server_index; - server->last_template_sent_time = 0; - })); -} - -void nfv9_params_show(u32 logging_index) -{ - cnat_nfv9_logging_info_t *log_info; - if(logging_index == EMPTY) { - PLATFORM_DEBUG_PRINT("\nNetflow logging not configured\n"); - return; - } - - log_info = cnat_nfv9_logging_info_pool + logging_index; - nfv9_server_info_t *server __attribute__((unused)) - = nfv9_server_info_pool + log_info->server_index; - - - PLATFORM_DEBUG_PRINT("\nNetflow parameters --\n"); - PLATFORM_DEBUG_PRINT("Server index %d IPV4 address: %x, port %d, max log size %d\n", - log_info->server_index, server->ipv4_address, - server->port, log_info->max_length_minus_max_record_size); - - PLATFORM_DEBUG_PRINT("Server ref count %d Refresh rate %d timeout rate %d\n", - server->ref_count, server->refresh_rate, - server->timeout_rate); - -} - -/* - * Code to dump NFV9 packets before they are sent - */ -void -cnat_nfv9_dump_logging_context (u32 value1, - cnat_nfv9_logging_info_t *nfv9_logging_info, - u32 value2) -{ - u8 *pkt_ptr; - u32 i; - u32 next_nfv9_template_data_index = 0xffff; - u32 next_data_flow_index = 0xffff; - u32 next_data_record = 0xffff; - u32 data_record_size = 0; - vlib_main_t *vm = vlib_get_main(); - - nfv9_server_info_t *server = nfv9_server_info_pool + - nfv9_logging_info->server_index; - - vlib_cli_output(vm,"\nDumping %s packet at locn %d: time 0x%x", - (value2 == 1) ? "CURRENT" : "QUEUED", - value1, - cnat_nfv9_get_unix_time_in_seconds()); - - vlib_cli_output(vm, "\ni_vrf 0x%x, ip_address 0x%x, port %d", - nfv9_logging_info->i_vrf, - server->ipv4_address, - server->port); - - vlib_cli_output(vm,"\nseq_num %d", - server->sequence_num); - - vlib_cli_output(vm,"\nlast_template_sent time 0x%x, pkts_since_last_template %d", - server->last_template_sent_time, - server->pkts_since_last_template); - - vlib_cli_output(vm, "\npkt_len %d, add_rec_len %d, del_rec_len %d, total_rec_count %d", - nfv9_logging_info->pkt_length, - nfv9_logging_info->record_length[NAT44_ADD_RECORD], - nfv9_logging_info->record_length[NAT44_DEL_RECORD], - nfv9_logging_info->total_record_count); - - vlib_cli_output(vm,"\nbulk_add_rec_len %d, bulk_del_rec_len %d", - nfv9_logging_info->record_length[NAT44_BULK_ADD_RECORD], - nfv9_logging_info->record_length[NAT44_BULK_DEL_RECORD]); - - vlib_cli_output(vm,"\ncurr_logging_ctx 0x%p, timestamp 0x%x, queued_logging_ctx 0x%p", - nfv9_logging_info->current_logging_context, - nfv9_logging_info->current_logging_context_timestamp, - nfv9_logging_info->queued_logging_context); - - vlib_cli_output(vm,"\nnfv9_hdr 0x%p, tmpl_hdr 0x%p, dataflow_hdr 0x%p", - nfv9_logging_info->nfv9_header, - nfv9_logging_info->nfv9_template_header, - nfv9_logging_info->dataflow_header); - - vlib_cli_output(vm,"\nadd_rec 0x%p, del_rec 0x%p, next_data_ptr 0x%p", - nfv9_logging_info->record[NAT44_ADD_RECORD], - nfv9_logging_info->record[NAT44_DEL_RECORD], - nfv9_logging_info->next_data_ptr); - - vlib_cli_output(vm,"\n"); - - pkt_ptr = vlib_buffer_get_current(nfv9_logging_info->current_logging_context); - /* - * Dump along with 8 bytes of SHIM header - */ - for (i = 0; i < (nfv9_logging_info->pkt_length + CNAT_NFV9_IP_HDR_OFFSET); - i = i + 1) { - u8 c1, c2, c3; - if (i == CNAT_NFV9_IP_HDR_OFFSET) { - vlib_cli_output(vm,"\nIP_HEADER: \n"); - } else if (i == CNAT_NFV9_UDP_HDR_OFFSET) { - vlib_cli_output(vm,"\nUDP_HEADER: \n"); - } else if (i == CNAT_NFV9_HDR_OFFSET) { - vlib_cli_output(vm,"\nNFV9 Header: Version:Count: \n"); - } else if (i == (CNAT_NFV9_HDR_OFFSET+4)) { - vlib_cli_output(vm,"\nBoot_Up_Time_In_ms: \n"); - } else if (i == (CNAT_NFV9_HDR_OFFSET+8)) { - vlib_cli_output(vm, "\nUNIX_Time: \n"); - } else if (i == (CNAT_NFV9_HDR_OFFSET+12)) { - vlib_cli_output(vm,"\nSeq_Num: \n"); - } else if (i == (CNAT_NFV9_HDR_OFFSET+16)) { - vlib_cli_output(vm,"\nSource ID: \n"); - } else if (i == (CNAT_NFV9_HDR_OFFSET+20)) { - if (nfv9_logging_info->nfv9_template_header) { - vlib_cli_output(vm,"\nNFV9 TEMPLATE HDR: \n"); - next_nfv9_template_data_index = i + 4; - } else { - next_data_flow_index = i; - } - } else if (i == (CNAT_NFV9_TEMPLATE_OFFSET+CNAT_NFV9_TEMPLATE_LENGTH)) { - if (nfv9_logging_info->nfv9_template_header) { - next_data_flow_index = i; - } - } - - if (i == next_nfv9_template_data_index) { - vlib_cli_output(vm,"\nNFV9 TEMPLATE DATA: \n"); - } else if (i == next_data_flow_index) { - if (*(pkt_ptr + i) == 0x01) { - if (*(pkt_ptr + i + 1) == 0x00) { - data_record_size = 21; - next_data_record = i + 4; - next_data_flow_index = i + *(pkt_ptr + i + 3) + - *(pkt_ptr + i + 2)*0x100; - vlib_cli_output(vm,"\nADD_RECORD (total %d): next_data_flow_index (%d->%d)\n", (next_data_flow_index - i), i, next_data_flow_index); - } else if (*(pkt_ptr + i + 1) == 0x01) { - data_record_size = 11; - next_data_record = i + 4; - next_data_flow_index = i + *(pkt_ptr + i + 3) + - *(pkt_ptr + i + 2)*0x100; - vlib_cli_output(vm,"\nDEL_RECORD (total %d) : next_data_flow_index (%d->%d)\n", (next_data_flow_index - i), i, next_data_flow_index); - } else if (*(pkt_ptr + i + 1) == 0x09) { - data_record_size = 20; - next_data_record = i + 4; - next_data_flow_index = i + *(pkt_ptr + i + 3) + - *(pkt_ptr + i + 2)*0x100; - vlib_cli_output(vm,"\nBULK_ADD_RECORD (total %d) : next_data_flow_index (%d->%d)\n", (next_data_flow_index - i), i, next_data_flow_index); - } else if (*(pkt_ptr + i + 1) == 0x0a) { - data_record_size = 10; - next_data_record = i + 4; - next_data_flow_index = i + *(pkt_ptr + i + 3) + - *(pkt_ptr + i + 2)*0x100; - vlib_cli_output(vm,"\nBULK_DEL_RECORD (total %d) : next_data_flow_index (%d->%d)\n", (next_data_flow_index - i), i, next_data_flow_index); - } - - } - } else if (i == next_data_record) { - vlib_cli_output(vm,"\n"); - next_data_record += data_record_size; - } - - c3 = *(pkt_ptr + i); - - c2 = c3 & 0xf; - c1 = (c3 >> 4) & 0xf; - - - vlib_cli_output(vm,"%c%c ", - ((c1 <= 9) ? (c1 + '0') : (c1 - 10 + 'a')), - ((c2 <= 9) ? (c2 + '0') : (c2 - 10 + 'a'))); - - } - vlib_cli_output(vm,"\n"); -} - -/* - * edt: * * cnat_nfv9_pad_added_to_an_addr - * - * Returns the difference (no# of bytes) between new_addr - * & org_addr - * - * Argument: u8 *new_addr, u8 *org_addr - * returns the difference - */ - -static inline -int cnat_nfv9_pad_added_to_an_addr(u8 *new_addr, u8 *org_addr) -{ - uword addr1 = (uword) new_addr; - uword addr2 = (uword) org_addr; - return (addr1 - addr2); -} - -/* - * edt: * * cnat_nfv9_add_end_of_record_padding - * - * Tries to add padding to data_ptr to ensure it is word aligned - * - * Argument: u8 * data_ptr - * pointer to the data pointer - */ - -static inline -u8 *cnat_nfv9_add_end_of_record_padding (u8 *data_ptr) -{ - uword tmp = (uword) data_ptr; - uword pad_value = (uword) NFV9_PAD_VALUE; - - tmp = (tmp + pad_value) & (~pad_value); - - return ((u8 *) tmp); -} - -/* - * edt: * * cnat_nfv9_pad_end_of_record_length - * - * Tries to add padding to data_ptr to ensure it is word aligned - * - * Argument: u8 * data_ptr - * pointer to the data pointer - */ - -static inline -u16 cnat_nfv9_pad_end_of_record_length (u16 record_length) -{ - u16 pad_value = NFV9_PAD_VALUE; - - return ((record_length + pad_value) & (~pad_value)); -} - -/* get first interface address */ -static ip4_address_t * -ip4_interface_first_address (ip4_main_t * im, u32 sw_if_index) -{ - ip_lookup_main_t * lm = &im->lookup_main; - ip_interface_address_t * ia = 0; - ip4_address_t * result = 0; - - foreach_ip_interface_address (lm, ia, sw_if_index, - 1 /* honor unnumbered */, - ({ - ip4_address_t * a = ip_interface_address_get_address (lm, ia); - result = a; - break; - })); - return result; -} - -void fill_ip_n_udp_hdr (u32 ipv4_addr, u16 port, - cnat_nfv9_logging_info_t *nfv9_logging_info) -{ - vlib_buffer_t * b0 = nfv9_logging_info->current_logging_context; - ipv4_header *ip_header = vlib_buffer_get_current(b0); - udp_hdr_type_t *udp_header = (udp_hdr_type_t *)((u8*)ip_header + sizeof(ipv4_header)); - vlib_main_t *vm = vlib_get_main(); - u16 ip_length __attribute__((unused)); - u16 pkt_len = nfv9_logging_info->pkt_length; - ip4_address_t *ia0 = 0; - u16 src_port = 0x0a0a; - - /* - * Clear the SHIM header fields. The PD nodes will set it - * appropriately. - */ - PLATFORM_MEMSET_CNAT_LOG_PKT_DATA - - /* - * Don't need a special define for 0x45 - IP version and hdr len - */ - ip_header->version_hdr_len_words = 0x45; - ip_header->tos = 0; - ip_header->frag_flags_offset = 0; - ip_header->ttl = 0xff; - ip_header->protocol = UDP_PROT; - ip_header->dest_addr = clib_host_to_net_u32(ipv4_addr); - ip_length = vlib_buffer_length_in_chain (vm, b0); - ip_header->total_len_bytes = clib_host_to_net_u16(pkt_len); - ia0 = ip4_interface_first_address(&ip4_main, nfv9_logging_info->i_vrf_id); - ip_header->src_addr = ia0->as_u32; - udp_header->src_port = clib_host_to_net_u16(src_port); - udp_header->dest_port = clib_host_to_net_u16(port); - udp_header->udp_checksum = 0; - udp_header->udp_length = - clib_host_to_net_u16(pkt_len - sizeof(ipv4_header)); - ip_header->checksum = ip4_header_checksum((ip4_header_t *)ip_header); -} - -/* - * edt: * * cnat_nfv9_fill_nfv9_ip_header - * - * Tries to fill the fields of the IP header before it - * is sent to the L3 infra node. - * - * Argument: cnat_nfv9_logging_info_t *nfv9_logging_info - * structure that contains the packet context - */ - -static inline -void cnat_nfv9_fill_nfv9_ip_header (cnat_nfv9_logging_info_t *nfv9_logging_info) -{ - u16 new_record_length = 0; - u16 orig_record_length = 0; - vlib_buffer_t * b0 = nfv9_logging_info->current_logging_context; - - /* - * Fill in the IP header and port number of the Netflow collector - * The L3 Infra node will fill in the rest of the fields - */ - - nfv9_logging_info->nfv9_header->count = - clib_host_to_net_u16(nfv9_logging_info->total_record_count); - - /* - * Pad the last add/del record to ensure multiple of 4 bytes - */ - - if(nfv9_logging_info->last_record != RECORD_INVALID) { - - orig_record_length = - nfv9_logging_info->record_length[nfv9_logging_info->last_record]; - - new_record_length = cnat_nfv9_pad_end_of_record_length( - orig_record_length); - - nfv9_logging_info->dataflow_header->dataflow_length = - clib_host_to_net_u16(new_record_length); - } - - /* - * If the record is padded, ensure the padded bytes are ZERO - */ - if (PREDICT_TRUE(new_record_length - orig_record_length)) { - u8 *pkt_ptr = (u8 *) (b0 + nfv9_logging_info->pkt_length); - - /* - * Blindly copy 3 bytes of data to Zero to avoid for loops - * We have sufficient padding bytes for safety and we won't - * go over buffer limits - */ - *pkt_ptr++ = 0; - *pkt_ptr++ = 0; - *pkt_ptr++ = 0; - - nfv9_logging_info->pkt_length += - (new_record_length - orig_record_length); - } - nfv9_server_info_t *server = nfv9_server_info_pool + - nfv9_logging_info->server_index; - fill_ip_n_udp_hdr(server->ipv4_address, - server->port, nfv9_logging_info); - /* - * It is important to set the sw_if_index for the new buffer create - */ - vnet_buffer(b0)->sw_if_index[VLIB_TX] = (u32)~0; - -} - -/* - * edt: * * cnat_nfv9_send_queued_pkt - * - * Tries to send a logging pkt that has been queued earlier - * because it could not be sent due to downstream constipation - * - * Argument: cnat_nfv9_logging_info_t *nfv9_logging_info - * structure that contains the packet context - */ - -static inline -void cnat_nfv9_send_queued_pkt (cnat_nfv9_logging_info_t *nfv9_logging_info) -{ - return; -} - -/* - * edt: * * cnat_nfv9_send_pkt - * - * Tries to send a logging pkt. If the packet cannot be sent - * because of rewrite_output node cannot process it, queue - * it temporarily and try to send it later. - * - * Argument: cnat_nfv9_logging_info_t *nfv9_logging_info - * structure that contains the packet context - */ - -static inline -void cnat_nfv9_send_pkt (cnat_nfv9_logging_info_t *nfv9_logging_info) -{ - cnat_nfv9_fill_nfv9_ip_header(nfv9_logging_info); - - nfv9_server_info_t *server = nfv9_server_info_pool + - nfv9_logging_info->server_index; - - /* Update sequence number just before sending. - * So that, multiple NAT44/NAT64/DSLite instances sharing a - * a single server instance can stamp the sequence number - * in the right sequence (as seen by the server). - */ - server->sequence_num += 1; - nfv9_logging_info->nfv9_header->sequence_num = - clib_host_to_net_u32(server->sequence_num); - -#if DEBUG - cnat_nfv9_dump_logging_context (2, nfv9_logging_info, 1); -#endif -#if 0 /* commented out below */ - send_vpp3_nfv9_pkt(nfv9_logging_info); -#endif - nfv9_logging_info->current_logging_context = NULL; - /* - * Increase last packet sent count - */ - server->pkts_since_last_template++; - - /* - * If we are sending an nfv9 tempate with this packet - * log this timestamp - */ - if (nfv9_logging_info->nfv9_template_header) { - server->last_template_sent_time = - cnat_nfv9_get_unix_time_in_seconds(); - server->pkts_since_last_template = 0; - } - - return; -} - -/* - * send_vpp3_nfv9_pkt: to send multiple b0 in a frame - */ - -static inline -void send_vpp3_nfv9_pkt (cnat_nfv9_logging_info_t *nfv9_logging_info) -{ - vlib_node_t *output_node; - vlib_main_t *vm = vlib_get_main(); - vlib_frame_t *f; - vlib_buffer_t *b0; - u32 *to_next; - u32 bi=0; - ipv4_header *ip; - - //Lets check and send it to ip4-lookup node - output_node = vlib_get_node_by_name (vm, (u8 *) "ip4-lookup"); - f = vlib_get_frame_to_node (vm, output_node->index); - - if ( nfv9_logging_info->current_logging_context != NULL) { - /* Build a pkt from whole cloth */ - b0 = nfv9_logging_info->current_logging_context; - ip = vlib_buffer_get_current(b0); - to_next = vlib_frame_vector_args (f); - bi = vlib_get_buffer_index (vm, b0); - to_next[0] = bi; - - f->n_vectors = 1; - b0->current_length = clib_net_to_host_u16(ip->total_len_bytes); - vlib_put_frame_to_node (vm, output_node->index, f); - } - return; -} -/* - * edt: * * cnat_nfv9_send_pkt_always_success - * - * Tries to send a logging pkt. This cannot fail due to downstream - * constipation because we have already checked if the rewrite_output - * node can accept it. - * - * Argument: cnat_nfv9_logging_info_t *nfv9_logging_info - * structure that contains the packet context - * - * Argument: vlib_node_t *output_node - * vlib_node_t structure for rewrite_output node - */ - -static inline -void cnat_nfv9_send_pkt_always_success ( - cnat_nfv9_logging_info_t *nfv9_logging_info, - vlib_node_t *output_node) -{ - nfv9_server_info_t *server = nfv9_server_info_pool + - nfv9_logging_info->server_index; - vlib_main_t * vm = vlib_get_main(); - - /* - * At this point we either have a current or queued logging context - */ - if (PREDICT_TRUE(nfv9_logging_info->current_logging_context != NULL)) { - server->sequence_num += 1; - nfv9_logging_info->nfv9_header->sequence_num = - clib_host_to_net_u32(server->sequence_num); - cnat_nfv9_fill_nfv9_ip_header(nfv9_logging_info); - - nfv9_logging_info->current_logging_context->current_length = - nfv9_logging_info->pkt_length; - vlib_cli_output(vm, "\nNFV9: 3. Sending Current packet\n"); -#if DEBUG - cnat_nfv9_dump_logging_context (3, nfv9_logging_info, 1); -#endif - send_vpp3_nfv9_pkt(nfv9_logging_info); - nfv9_logging_info->current_logging_context = NULL; - } else { - /* - * For queued logging context, nfv9_header-> count is already set - */ - nfv9_logging_info->queued_logging_context->current_length = - nfv9_logging_info->pkt_length; - vlib_cli_output(vm,"\nNFV9: 4. Sending Queued packet\n"); -#if DEBUG - cnat_nfv9_dump_logging_context (4, nfv9_logging_info, 2); -#endif - send_vpp3_nfv9_pkt(nfv9_logging_info); - - nfv9_logging_info->queued_logging_context = NULL; - } - - /* - * NF Logging info already deleted, just free it and return - */ - if (PREDICT_FALSE(nfv9_logging_info->deleted)) { - pool_put(cnat_nfv9_logging_info_pool, nfv9_logging_info); - return; - } - - /* - * Increase last packet sent count and timestamp - */ - server->pkts_since_last_template++; - - /* - * If we are sending an nfv9 tempate with this packet - * log this timestamp - */ - if (nfv9_logging_info->nfv9_template_header) { - server->last_template_sent_time = - cnat_nfv9_get_unix_time_in_seconds(); - server->pkts_since_last_template = 0; - } -} - -/* - * edt: * * cnat_nfv9_create_logging_context - * - * Tries to create a logging context with packet buffer - * to send a new logging packet - * - * Argument: cnat_nfv9_logging_info_t *nfv9_logging_info - * structure that contains the nfv9 logging info and will store - * the packet context as well. - */ - -static inline -void cnat_nfv9_create_logging_context ( - cnat_nfv9_logging_info_t *nfv9_logging_info, - cnat_nfv9_template_add_flag_t template_flag) -{ - vlib_main_t *vm = vlib_get_main(); - vlib_buffer_t *b0; - static u32 bi; - u8 i; - - /* - * If queued_logging_context_index is non-EMPTY, we already have a logging - * packet queued to be sent. First try sending this before allocating - * a new context. We can have only one active packet context per - * nfv9_logging_info structure - */ - if (PREDICT_FALSE(nfv9_logging_info->queued_logging_context != NULL)) { - cnat_nfv9_send_queued_pkt(nfv9_logging_info); - /* - * If we cannot still send the queued pkt, just return - * Downstream Constipation count would have increased anyway - */ - if (nfv9_logging_info->queued_logging_context != NULL) { - cnat_global_counters.nfv9_logging_context_creation_deferred_count++; - return; - } - } - - - /* - * No context can be allocated, return silently - * calling routine will handle updating the error counters - */ - if (vlib_buffer_alloc (vm, &bi, 1) != 1) { - vlib_cli_output(vm, "buffer allocation failure"); - return; - } - /* Build a pkt from whole cloth */ - b0 = vlib_get_buffer (vm, bi); - b0->current_data = 0; - - nfv9_server_info_t *server = nfv9_server_info_pool + - nfv9_logging_info->server_index; - - nfv9_logging_info->current_logging_context = b0; - nfv9_logging_info->current_logging_context_timestamp = - cnat_nfv9_get_sys_up_time_in_ms(); - - - nfv9_logging_info->nfv9_header = - (nfv9_header_t *) (vlib_buffer_get_current(b0) + - (sizeof(ipv4_header)) + - (sizeof(udp_hdr_type_t))); - - nfv9_logging_info->nfv9_header->version = - clib_host_to_net_u16(CNAT_NFV9_VERSION_NUMBER); - - nfv9_logging_info->nfv9_header->sys_up_time = - clib_host_to_net_u32(cnat_nfv9_get_sys_up_time_in_ms()); - - nfv9_logging_info->nfv9_header->timestamp = - clib_host_to_net_u32(cnat_nfv9_get_unix_time_in_seconds()); - - - nfv9_logging_info->nfv9_header->source_id = - clib_host_to_net_u32(nfv9_src_id); - - nfv9_logging_info->dataflow_header = 0; - - for(i = 0; i < MAX_RECORDS;i++) { - nfv9_logging_info->record[i] = NULL; - nfv9_logging_info->record_length[i] = 0; - } - nfv9_logging_info->last_record = 0; - - - nfv9_logging_info->nfv9_template_header = 0; - nfv9_logging_info->next_data_ptr = - (u8 *) (vlib_buffer_get_current(b0) + - sizeof(ipv4_header) + sizeof(udp_hdr_type_t) + - sizeof(nfv9_header_t)); - - nfv9_logging_info->pkt_length = (CNAT_NFV9_TEMPLATE_OFFSET - - CNAT_NFV9_IP_HDR_OFFSET); - - - /* - * Now we have 0 records to start with - */ - - nfv9_logging_info->total_record_count = 0; - - if ((template_flag == cnat_nfv9_template_add_always) || - (server->pkts_since_last_template > - server->refresh_rate) || - ((cnat_nfv9_get_unix_time_in_seconds() - - server->last_template_sent_time) > - server->timeout_rate)) { - - /* - * Send a new template - */ - nfv9_logging_info->nfv9_template_header = - (cnat_nfv9_template_t *) nfv9_logging_info->next_data_ptr; - - clib_memcpy(nfv9_logging_info->nfv9_template_header, - &cnat_nfv9_template_info, - sizeof(cnat_nfv9_template_info)); - - /* - * Templates are sent irrespective of particular service-type config - */ - nfv9_logging_info->total_record_count = MAX_RECORDS - 1; - - nfv9_logging_info->pkt_length += CNAT_NFV9_TEMPLATE_LENGTH; - - /* - * Set the data pointer beyond the template field - */ - nfv9_logging_info->next_data_ptr = - (u8 *) (nfv9_logging_info->nfv9_template_header + 1); - /* - * Setting template_sent flag as TRUE. this will be checked in - * handle_vrfid_name_mapping() - */ - server->template_sent = TEMPLATE_SENT_TRUE; - } -} - -void cnat_nfv9_record_create ( - cnat_nfv9_logging_info_t *nfv9_logging_info, u16 cur_record) -{ - int byte_diff = 0; - u16 last_record = nfv9_logging_info->last_record; - - if(last_record != 0 && last_record != cur_record) { - u16 orig_length, new_length; - - orig_length = nfv9_logging_info->record_length[last_record]; - new_length = cnat_nfv9_pad_end_of_record_length(orig_length); - - /* - * The padding bytes are required after the last record - * Ensure length of last record accounts for padding bytes - */ - nfv9_logging_info->dataflow_header->dataflow_length = - clib_host_to_net_u16(new_length); - - /* - * Since we are working on the del record, set add record to 0 - */ - nfv9_logging_info->record[last_record] = 0; - - nfv9_logging_info->record_length[last_record] = 0; - - nfv9_logging_info->last_record = 0; - } - - nfv9_logging_info->last_record = cur_record; - - /* - * The padding bytes are required after the last record - * Ensure that we skip over the padding bytes - */ - nfv9_logging_info->dataflow_header = (nfv9_dataflow_record_header_t *) - cnat_nfv9_add_end_of_record_padding(nfv9_logging_info->next_data_ptr); - /* - * Get the difference - */ - byte_diff = cnat_nfv9_pad_added_to_an_addr( - (u8 *)nfv9_logging_info->dataflow_header, - nfv9_logging_info->next_data_ptr); - if(byte_diff > 0) { - /* - * Update the packet length to account for the pad bytes - */ - nfv9_logging_info->pkt_length += byte_diff; - u8 *pkt_ptr = nfv9_logging_info->next_data_ptr; - - /* - * Blindly copy 3 bytes of data to Zero to avoid for loops - * We have sufficient padding bytes for safety and we won't - * go over buffer limits - */ - *pkt_ptr++ = 0; - *pkt_ptr++ = 0; - *pkt_ptr++ = 0; - } - /* - * Initialize the template_id and the length of the add record - */ - nfv9_logging_info->dataflow_header->dataflow_template_id = - clib_host_to_net_u16(cnat_template_id[cur_record]); - - nfv9_logging_info->record[cur_record] = - (u8 *) (nfv9_logging_info->dataflow_header + 1); - - nfv9_logging_info->record_length[cur_record] = - CNAT_NFV9_DATAFLOW_RECORD_HEADER_LENGTH; - - /* - * Update the length of the total NFV9 record - */ - nfv9_logging_info->pkt_length += - CNAT_NFV9_DATAFLOW_RECORD_HEADER_LENGTH; - - /* - * Set the data pointer beyond the dataflow header field - */ - nfv9_logging_info->next_data_ptr = - (u8 *) (nfv9_logging_info->dataflow_header + 1); - -} - -static void cnat_nfv9_insert_add_record( - cnat_nfv9_logging_info_t *nfv9_logging_info, - cnat_main_db_entry_t *db, - cnat_vrfmap_t *vrfmap) -{ - u16 my_proto_mask; - u8 my_protocol; - nfv9_add_record_t nfv9_logging_add_record; - if (PREDICT_FALSE(nfv9_logging_info->record[NAT44_ADD_RECORD] == NULL)) { - cnat_nfv9_record_create(nfv9_logging_info, NAT44_ADD_RECORD); - } - - /* - * We should definitely have add_record now, no need to sanitize - */ - - nfv9_logging_add_record.inside_vrf_id = - clib_host_to_net_u32(vrfmap->i_vrf_id); - - nfv9_logging_add_record.outside_vrf_id = - clib_host_to_net_u32(vrfmap->o_vrf_id); - - nfv9_logging_add_record.inside_ip_addr = - clib_host_to_net_u32(db->in2out_key.k.ipv4); - nfv9_logging_add_record.outside_ip_addr = - clib_host_to_net_u32(db->out2in_key.k.ipv4); - - nfv9_logging_add_record.inside_ip_port = - clib_host_to_net_u16(db->in2out_key.k.port); - nfv9_logging_add_record.outside_ip_port = - clib_host_to_net_u16(db->out2in_key.k.port); - - my_proto_mask = db->in2out_key.k.vrf & CNAT_PRO_MASK; - my_protocol = ((my_proto_mask == CNAT_UDP) ? UDP_PROT : - ((my_proto_mask == CNAT_TCP) ? TCP_PROT : - ((my_proto_mask == CNAT_ICMP) ? ICMP_PROT : GRE_PROT))); - - nfv9_logging_add_record.protocol = my_protocol; - - clib_memcpy(nfv9_logging_info->record[NAT44_ADD_RECORD], - &nfv9_logging_add_record, CNAT_NFV9_ADD_RECORD_LENGTH); - - nfv9_logging_info->record_length[NAT44_ADD_RECORD] - += CNAT_NFV9_ADD_RECORD_LENGTH; - - nfv9_logging_info->pkt_length += CNAT_NFV9_ADD_RECORD_LENGTH; - - nfv9_logging_info->record[NAT44_ADD_RECORD] - += CNAT_NFV9_ADD_RECORD_LENGTH; - nfv9_logging_info->next_data_ptr = - nfv9_logging_info->record[NAT44_ADD_RECORD]; - - nfv9_logging_info->dataflow_header->dataflow_length = - clib_host_to_net_u32( - nfv9_logging_info->record_length[NAT44_ADD_RECORD]); - -} - - -static void cnat_nfv9_ds_lite_insert_add_record( - cnat_nfv9_logging_info_t *nfv9_logging_info, - cnat_main_db_entry_t *db, - dslite_table_entry_t *dslite_entry) -{ - - nfv9_ds_lite_add_record_t nfv9_logging_add_record = {0}; - cnat_user_db_entry_t *udb = NULL; - u16 my_proto_mask; - u8 my_protocol; - - udb = cnat_user_db + db->user_index; - if (PREDICT_FALSE(!udb)) { - return; - } - if (PREDICT_FALSE(nfv9_logging_info->record[DS_LITE_ADD_RECORD] == NULL)) { - cnat_nfv9_record_create(nfv9_logging_info, DS_LITE_ADD_RECORD); - } - /* - * We should definitely have add_record now, no need to sanitize - */ - nfv9_logging_add_record.inside_vrf_id = - clib_host_to_net_u32(dslite_entry->i_vrf_id); - nfv9_logging_add_record.outside_vrf_id = - clib_host_to_net_u32(dslite_entry->o_vrf_id); - -#ifdef DSLITE_USER_IPV4 - nfv9_logging_add_record.inside_ip_addr = - clib_host_to_net_u32(db->in2out_key.k.ipv4); -#else - /* - * Inside ipv4 address is sent as 0.0.0.0 for ds-lite case as - * ipv6 is user here. - */ - nfv9_logging_add_record.inside_ip_addr = 0; -#endif - - nfv9_logging_add_record.inside_v6_src_addr[0] = - clib_host_to_net_u32(udb->ipv6[0]); - nfv9_logging_add_record.inside_v6_src_addr[1] = - clib_host_to_net_u32(udb->ipv6[1]); - nfv9_logging_add_record.inside_v6_src_addr[2] = - clib_host_to_net_u32(udb->ipv6[2]); - nfv9_logging_add_record.inside_v6_src_addr[3] = - clib_host_to_net_u32(udb->ipv6[3]); - - nfv9_logging_add_record.outside_ip_addr = - clib_host_to_net_u32(db->out2in_key.k.ipv4); - - nfv9_logging_add_record.inside_ip_port = - clib_host_to_net_u16(db->in2out_key.k.port); - nfv9_logging_add_record.outside_ip_port = - clib_host_to_net_u16(db->out2in_key.k.port); - - my_proto_mask = db->in2out_key.k.vrf & CNAT_PRO_MASK; - - my_protocol = ((my_proto_mask == CNAT_UDP) ? UDP_PROT : - ((my_proto_mask == CNAT_TCP) ? TCP_PROT : - ((my_proto_mask == CNAT_ICMP) ? ICMP_PROT : 0))); - nfv9_logging_add_record.protocol = my_protocol; - - clib_memcpy(nfv9_logging_info->record[DS_LITE_ADD_RECORD], - &nfv9_logging_add_record, CNAT_NFV9_DS_LITE_ADD_RECORD_LENGTH); - - nfv9_logging_info->record_length[DS_LITE_ADD_RECORD] - += CNAT_NFV9_DS_LITE_ADD_RECORD_LENGTH; - - nfv9_logging_info->pkt_length += CNAT_NFV9_DS_LITE_ADD_RECORD_LENGTH; - nfv9_logging_info->total_record_count += 1; - - nfv9_logging_info->record[DS_LITE_ADD_RECORD] - += CNAT_NFV9_DS_LITE_ADD_RECORD_LENGTH; - nfv9_logging_info->next_data_ptr = - nfv9_logging_info->record[DS_LITE_ADD_RECORD]; - - nfv9_logging_info->dataflow_header->dataflow_length = - clib_host_to_net_u32( - nfv9_logging_info->record_length[DS_LITE_ADD_RECORD]); -} - - -static void cnat_nfv9_ds_lite_insert_del_record( - cnat_nfv9_logging_info_t *nfv9_logging_info, - cnat_main_db_entry_t *db, - dslite_table_entry_t *dslite_entry) -{ - - nfv9_ds_lite_del_record_t nfv9_logging_del_record = {0}; - cnat_user_db_entry_t *udb = NULL; - u16 my_proto_mask; - u8 my_protocol; - - udb = cnat_user_db + db->user_index; - if (PREDICT_FALSE(!udb)) { - return; - } - if (PREDICT_FALSE(nfv9_logging_info->record[DS_LITE_DEL_RECORD] == NULL)) { - cnat_nfv9_record_create(nfv9_logging_info, DS_LITE_DEL_RECORD); - } - /* - * We should definitely have a del record now. - * No need to sanitize - */ - nfv9_logging_del_record.inside_vrf_id = - clib_host_to_net_u32(dslite_entry->i_vrf_id); - -#ifdef DSLITE_USER_IPV4 - nfv9_logging_del_record.inside_ip_addr = - clib_host_to_net_u32(db->in2out_key.k.ipv4); -#else - /* - * Inside ipv4 address is sent as 0.0.0.0 for ds-lite case as - * ipv6 is user here. - */ - nfv9_logging_del_record.inside_ip_addr = 0; -#endif - - nfv9_logging_del_record.inside_v6_src_addr[0] = - clib_host_to_net_u32(udb->ipv6[0]); - nfv9_logging_del_record.inside_v6_src_addr[1] = - clib_host_to_net_u32(udb->ipv6[1]); - nfv9_logging_del_record.inside_v6_src_addr[2] = - clib_host_to_net_u32(udb->ipv6[2]); - nfv9_logging_del_record.inside_v6_src_addr[3] = - clib_host_to_net_u32(udb->ipv6[3]); - - nfv9_logging_del_record.inside_ip_port = - clib_host_to_net_u16(db->in2out_key.k.port); - - my_proto_mask = db->in2out_key.k.vrf & CNAT_PRO_MASK; - - my_protocol = ((my_proto_mask == CNAT_UDP) ? UDP_PROT : - ((my_proto_mask == CNAT_TCP) ? TCP_PROT : - ((my_proto_mask == CNAT_ICMP) ? ICMP_PROT : 0))); - nfv9_logging_del_record.protocol = my_protocol; - - clib_memcpy(nfv9_logging_info->record[DS_LITE_DEL_RECORD], - &nfv9_logging_del_record, CNAT_NFV9_DS_LITE_DEL_RECORD_LENGTH); - - nfv9_logging_info->record_length[DS_LITE_DEL_RECORD] += - CNAT_NFV9_DS_LITE_DEL_RECORD_LENGTH; - - nfv9_logging_info->pkt_length += CNAT_NFV9_DS_LITE_DEL_RECORD_LENGTH; - nfv9_logging_info->total_record_count += 1; - - nfv9_logging_info->record[DS_LITE_DEL_RECORD] - += CNAT_NFV9_DS_LITE_DEL_RECORD_LENGTH; - nfv9_logging_info->next_data_ptr = - nfv9_logging_info->record[DS_LITE_DEL_RECORD]; - - nfv9_logging_info->dataflow_header->dataflow_length = - clib_host_to_net_u32( - nfv9_logging_info->record_length[DS_LITE_DEL_RECORD]); -} - -#ifndef NO_BULK_LOGGING -static void cnat_nfv9_insert_bulk_add_record( - cnat_nfv9_logging_info_t *nfv9_logging_info, - cnat_main_db_entry_t *db, - cnat_vrfmap_t *vrfmap, - int bulk_alloc_start_port) -{ - nfv9_bulk_add_record_t nfv9_logging_bulk_add_record; - bulk_alloc_size_t bulk_size = BULKSIZE_FROM_VRFMAP(vrfmap); - if (PREDICT_FALSE(nfv9_logging_info->record[NAT44_BULK_ADD_RECORD] == NULL)) { - cnat_nfv9_record_create(nfv9_logging_info, NAT44_BULK_ADD_RECORD); - } - - /* - * We should definitely have add_record now, no need to sanitize - */ - - nfv9_logging_bulk_add_record.inside_vrf_id = - clib_host_to_net_u32(vrfmap->i_vrf_id); - nfv9_logging_bulk_add_record.outside_vrf_id = - clib_host_to_net_u32(vrfmap->o_vrf_id); - - nfv9_logging_bulk_add_record.inside_ip_addr = - clib_host_to_net_u32(db->in2out_key.k.ipv4); - nfv9_logging_bulk_add_record.outside_ip_addr = - clib_host_to_net_u32(db->out2in_key.k.ipv4); - - nfv9_logging_bulk_add_record.outside_ip_port_start = - clib_host_to_net_u16(bulk_alloc_start_port); - nfv9_logging_bulk_add_record.outside_ip_port_end = - clib_host_to_net_u16(bulk_alloc_start_port + bulk_size -1); - - clib_memcpy(nfv9_logging_info->record[NAT44_BULK_ADD_RECORD], - &nfv9_logging_bulk_add_record, CNAT_NFV9_BULK_ADD_RECORD_LENGTH); - - nfv9_logging_info->record_length[NAT44_BULK_ADD_RECORD] - += CNAT_NFV9_BULK_ADD_RECORD_LENGTH; - - nfv9_logging_info->pkt_length += CNAT_NFV9_BULK_ADD_RECORD_LENGTH; - - nfv9_logging_info->record[NAT44_BULK_ADD_RECORD] - += CNAT_NFV9_BULK_ADD_RECORD_LENGTH; - nfv9_logging_info->next_data_ptr = - nfv9_logging_info->record[NAT44_BULK_ADD_RECORD]; - - nfv9_logging_info->dataflow_header->dataflow_length = - clib_host_to_net_u32( - nfv9_logging_info->record_length[NAT44_BULK_ADD_RECORD]); - -} - - -static void cnat_nfv9_ds_lite_insert_bulk_add_record( - cnat_nfv9_logging_info_t *nfv9_logging_info, - cnat_main_db_entry_t *db, - dslite_table_entry_t *dslite_entry, - int bulk_alloc_start_port) -{ - - nfv9_ds_lite_bulk_add_record_t nfv9_logging_bulk_add_record = {0}; - cnat_user_db_entry_t *udb = NULL; - bulk_alloc_size_t bulk_size = BULKSIZE_FROM_VRFMAP(dslite_entry); - - if (PREDICT_FALSE(nfv9_logging_info->record[DS_LITE_BULK_ADD_RECORD] == NULL)) { - cnat_nfv9_record_create(nfv9_logging_info, DS_LITE_BULK_ADD_RECORD); - } - udb = cnat_user_db + db->user_index; - if (PREDICT_FALSE(!udb)) { - return; - } - /* - * We should definitely have add_record now, no need to sanitize - */ - - nfv9_logging_bulk_add_record.inside_vrf_id = - clib_host_to_net_u32(dslite_entry->i_vrf_id); - nfv9_logging_bulk_add_record.outside_vrf_id = - clib_host_to_net_u32(dslite_entry->o_vrf_id); - -#ifdef DSLITE_USER_IPV4 - nfv9_logging_bulk_add_record.inside_ip_addr = - clib_host_to_net_u32(db->in2out_key.k.ipv4); -#else - /* - * Inside ipv4 address is sent as 0.0.0.0 for ds-lite case as - * ipv6 is user here. - */ - nfv9_logging_bulk_add_record.inside_ip_addr = 0; -#endif - - nfv9_logging_bulk_add_record.inside_v6_src_addr[0] = - clib_host_to_net_u32(udb->ipv6[0]); - nfv9_logging_bulk_add_record.inside_v6_src_addr[1] = - clib_host_to_net_u32(udb->ipv6[1]); - nfv9_logging_bulk_add_record.inside_v6_src_addr[2] = - clib_host_to_net_u32(udb->ipv6[2]); - nfv9_logging_bulk_add_record.inside_v6_src_addr[3] = - clib_host_to_net_u32(udb->ipv6[3]); - - nfv9_logging_bulk_add_record.outside_ip_addr = - clib_host_to_net_u32(db->out2in_key.k.ipv4); - - nfv9_logging_bulk_add_record.outside_ip_port_start = - clib_host_to_net_u16(bulk_alloc_start_port); - nfv9_logging_bulk_add_record.outside_ip_port_end = - clib_host_to_net_u16(bulk_alloc_start_port + bulk_size -1); - - clib_memcpy(nfv9_logging_info->record[DS_LITE_BULK_ADD_RECORD], - &nfv9_logging_bulk_add_record, CNAT_NFV9_DS_LITE_BULK_ADD_RECORD_LENGTH); - - nfv9_logging_info->record_length[DS_LITE_BULK_ADD_RECORD] - += CNAT_NFV9_DS_LITE_BULK_ADD_RECORD_LENGTH; - - nfv9_logging_info->pkt_length += CNAT_NFV9_DS_LITE_BULK_ADD_RECORD_LENGTH; - nfv9_logging_info->total_record_count += 1; - nfv9_logging_info->record[DS_LITE_BULK_ADD_RECORD] - += CNAT_NFV9_DS_LITE_BULK_ADD_RECORD_LENGTH; - nfv9_logging_info->next_data_ptr = - nfv9_logging_info->record[DS_LITE_BULK_ADD_RECORD]; - nfv9_logging_info->dataflow_header->dataflow_length = - clib_host_to_net_u32( - nfv9_logging_info->record_length[DS_LITE_BULK_ADD_RECORD]); -} - - -static void cnat_nfv9_ds_lite_insert_bulk_del_record( - cnat_nfv9_logging_info_t *nfv9_logging_info, - cnat_main_db_entry_t *db, - dslite_table_entry_t *dslite_entry, - int bulk_alloc_start_port) -{ - - nfv9_ds_lite_bulk_del_record_t nfv9_logging_bulk_del_record = {0}; - cnat_user_db_entry_t *udb = NULL; - - if (PREDICT_FALSE(nfv9_logging_info->record[DS_LITE_BULK_DEL_RECORD] == NULL)) { - cnat_nfv9_record_create(nfv9_logging_info, DS_LITE_BULK_DEL_RECORD); - } - udb = cnat_user_db + db->user_index; - if (PREDICT_FALSE(!udb)) { - return; - } - /* - * We should definitely have add_record now, no need to sanitize - */ - - nfv9_logging_bulk_del_record.inside_vrf_id = - clib_host_to_net_u32(dslite_entry->i_vrf_id); - -#ifdef DSLITE_USER_IPV4 - nfv9_logging_bulk_del_record.inside_ip_addr = - clib_host_to_net_u32(db->in2out_key.k.ipv4); -#else - nfv9_logging_bulk_del_record.inside_ip_addr = - clib_host_to_net_u32(0); -#endif - - nfv9_logging_bulk_del_record.inside_v6_src_addr[0] = - clib_host_to_net_u32(udb->ipv6[0]); - nfv9_logging_bulk_del_record.inside_v6_src_addr[1] = - clib_host_to_net_u32(udb->ipv6[1]); - nfv9_logging_bulk_del_record.inside_v6_src_addr[2] = - clib_host_to_net_u32(udb->ipv6[2]); - nfv9_logging_bulk_del_record.inside_v6_src_addr[3] = - clib_host_to_net_u32(udb->ipv6[3]); - - nfv9_logging_bulk_del_record.outside_ip_port_start = - clib_host_to_net_u16(bulk_alloc_start_port); - - clib_memcpy(nfv9_logging_info->record[DS_LITE_BULK_DEL_RECORD], - &nfv9_logging_bulk_del_record, - CNAT_NFV9_DS_LITE_BULK_DEL_RECORD_LENGTH); - nfv9_logging_info->record_length[DS_LITE_BULK_DEL_RECORD] += - CNAT_NFV9_DS_LITE_BULK_DEL_RECORD_LENGTH; - nfv9_logging_info->pkt_length += - CNAT_NFV9_DS_LITE_BULK_DEL_RECORD_LENGTH; - nfv9_logging_info->total_record_count += 1; - nfv9_logging_info->record[DS_LITE_BULK_DEL_RECORD] += - CNAT_NFV9_DS_LITE_BULK_DEL_RECORD_LENGTH; - nfv9_logging_info->next_data_ptr = - nfv9_logging_info->record[DS_LITE_BULK_DEL_RECORD]; - nfv9_logging_info->dataflow_header->dataflow_length = - clib_host_to_net_u32( - nfv9_logging_info->record_length[DS_LITE_BULK_DEL_RECORD]); -} -#endif /* #ifndef NO_BULK_LOGGING */ - -static void cnat_nfv9_insert_del_record( - cnat_nfv9_logging_info_t *nfv9_logging_info, - cnat_main_db_entry_t *db, - cnat_vrfmap_t *vrfmap) -{ - u16 my_proto_mask; - u8 my_protocol; - nfv9_del_record_t nfv9_logging_del_record; - - if (PREDICT_FALSE(nfv9_logging_info->record[NAT44_DEL_RECORD] == NULL)) { - cnat_nfv9_record_create(nfv9_logging_info, NAT44_DEL_RECORD); - } - - /* - * We should definitely have add_record now, no need to sanitize - */ - - nfv9_logging_del_record.inside_vrf_id = - clib_host_to_net_u32(vrfmap->i_vrf_id); - - nfv9_logging_del_record.inside_ip_addr = - clib_host_to_net_u32(db->in2out_key.k.ipv4); - - nfv9_logging_del_record.inside_ip_port = - clib_host_to_net_u16(db->in2out_key.k.port); - - my_proto_mask = db->in2out_key.k.vrf & CNAT_PRO_MASK; - my_protocol = ((my_proto_mask == CNAT_UDP) ? UDP_PROT : - ((my_proto_mask == CNAT_TCP) ? TCP_PROT : - ((my_proto_mask == CNAT_ICMP) ? ICMP_PROT : GRE_PROT))); - - nfv9_logging_del_record.protocol = my_protocol; - - clib_memcpy(nfv9_logging_info->record[NAT44_DEL_RECORD], - &nfv9_logging_del_record, CNAT_NFV9_DEL_RECORD_LENGTH); - - nfv9_logging_info->record_length[NAT44_DEL_RECORD] - += CNAT_NFV9_DEL_RECORD_LENGTH; - - nfv9_logging_info->pkt_length += CNAT_NFV9_DEL_RECORD_LENGTH; - - nfv9_logging_info->record[NAT44_DEL_RECORD] - += CNAT_NFV9_DEL_RECORD_LENGTH; - nfv9_logging_info->next_data_ptr = - nfv9_logging_info->record[NAT44_DEL_RECORD]; - - nfv9_logging_info->dataflow_header->dataflow_length = - clib_host_to_net_u32( - nfv9_logging_info->record_length[NAT44_DEL_RECORD]); - -} - -#ifndef NO_BULK_LOGGING -static void cnat_nfv9_insert_bulk_del_record( - cnat_nfv9_logging_info_t *nfv9_logging_info, - cnat_main_db_entry_t *db, - cnat_vrfmap_t *vrfmap, - int bulk_alloc_start_port) -{ - nfv9_bulk_del_record_t nfv9_logging_bulk_del_record; - if (PREDICT_FALSE(nfv9_logging_info->record[NAT44_BULK_DEL_RECORD] == NULL)) { - cnat_nfv9_record_create(nfv9_logging_info, NAT44_BULK_DEL_RECORD); - } - - /* - * We should definitely have add_record now, no need to sanitize - */ - - nfv9_logging_bulk_del_record.inside_vrf_id = - clib_host_to_net_u32(vrfmap->i_vrf_id); - - nfv9_logging_bulk_del_record.inside_ip_addr = - clib_host_to_net_u32(db->in2out_key.k.ipv4); - - nfv9_logging_bulk_del_record.outside_ip_port_start = - clib_host_to_net_u16(bulk_alloc_start_port); - - clib_memcpy(nfv9_logging_info->record[NAT44_BULK_DEL_RECORD], - &nfv9_logging_bulk_del_record, CNAT_NFV9_BULK_DEL_RECORD_LENGTH); - - nfv9_logging_info->record_length[NAT44_BULK_DEL_RECORD] - += CNAT_NFV9_BULK_DEL_RECORD_LENGTH; - - nfv9_logging_info->pkt_length += CNAT_NFV9_BULK_DEL_RECORD_LENGTH; - - nfv9_logging_info->record[NAT44_BULK_DEL_RECORD] - += CNAT_NFV9_BULK_DEL_RECORD_LENGTH; - nfv9_logging_info->next_data_ptr = - nfv9_logging_info->record[NAT44_BULK_DEL_RECORD]; - - nfv9_logging_info->dataflow_header->dataflow_length = - clib_host_to_net_u32( - nfv9_logging_info->record_length[NAT44_BULK_DEL_RECORD]); - -} - -#endif /* #ifndef NO_BULK_LOGGING */ -/* - * edt: * * cnat_nfv9_log_mapping_create - * - * Tries to log a creation of mapping record - * - * Argument: cnat_main_db_entry_t *db - * Main DB entry being created - * - * Argument: cnat_vrfmap_t *vrfmap - * VRF Map for the Main DB entry being created - */ -void cnat_nfv9_log_mapping_create (cnat_main_db_entry_t *db, - cnat_vrfmap_t *vrfmap -#ifndef NO_BULK_LOGGING - , int bulk_alloc -#endif - ) -{ - cnat_nfv9_logging_info_t *nfv9_logging_info = 0; - vlib_main_t * vm = vlib_get_main(); - - if (PREDICT_FALSE(vrfmap->nfv9_logging_index == EMPTY)) { - - //vlib_cli_output(vm, "\n1. Log Mapping failed"); - /* - * No logging configured, silently return - */ - return; - } - - if (cnat_nfv9_logging_info_pool == NULL) { - vlib_cli_output(vm, "%s: info_pool pointer is NULL !!!!\n", __func__); - return; - } - nfv9_logging_info = - cnat_nfv9_logging_info_pool + vrfmap->nfv9_logging_index; - - if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { - cnat_nfv9_create_logging_context(nfv9_logging_info, - cnat_nfv9_template_add_default); - - /* - * If still empty, return after increasing the count - */ - if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { - //vlib_cli_output(vm, "\n2. Log Mapping failed"); - return; - } - - } - -#ifndef NO_BULK_LOGGING - if(bulk_alloc > 0) { /* new bulk alloc - use bulk add template */ - cnat_nfv9_insert_bulk_add_record(nfv9_logging_info, db, vrfmap, - bulk_alloc); - } else if(bulk_alloc == CACHE_ALLOC_NO_LOG_REQUIRED) - return; /* No logging required.. bulk port usage */ - else /* Individual logging .. fall back to old method */ -#endif - cnat_nfv9_insert_add_record(nfv9_logging_info, db, vrfmap); - - nfv9_logging_info->total_record_count += 1; - - /* - * If we have exceeded the packet length, let us send the - * packet now. There is buffer of additional bytes beyond - * max_pkt_length to ensure that the last add/delete record - * can be stored safely. - */ - if (PREDICT_FALSE(nfv9_logging_info->pkt_length > - nfv9_logging_info->max_length_minus_max_record_size)) { - cnat_nfv9_send_pkt(nfv9_logging_info); - } -} - -/* - * edt: * * cnat_nfv9_log_mapping_delete - * - * Tries to log a deletion of mapping record - * - * Argument: cnat_main_db_entry_t *db - * Main DB entry being deleted - * - * Argument: cnat_vrfmap_t *vrfmap - * VRF Map for the Main DB entry being deleted - */ -void cnat_nfv9_log_mapping_delete (cnat_main_db_entry_t * db, - cnat_vrfmap_t *vrfmap -#ifndef NO_BULK_LOGGING - , int bulk_alloc -#endif - ) -{ - cnat_nfv9_logging_info_t *nfv9_logging_info = 0; - - if (PREDICT_FALSE(vrfmap->nfv9_logging_index == EMPTY)) { - //vlib_cli_output(vm, "\n3. Log Mapping failed"); - /* - * No logging configured, silently return - */ - return; - } - - nfv9_logging_info = - cnat_nfv9_logging_info_pool + vrfmap->nfv9_logging_index; - - if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { - cnat_nfv9_create_logging_context(nfv9_logging_info, - cnat_nfv9_template_add_default); - - /* - * If still empty, return after increasing the count - */ - if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { - //vlib_cli_output(vm, "\n4. Log Mapping failed"); - return; - } - } -#ifndef NO_BULK_LOGGING - if(bulk_alloc > 0) { /* new bulk alloc - use bulk add template */ - cnat_nfv9_insert_bulk_del_record(nfv9_logging_info, db, vrfmap, - bulk_alloc); - } else if(bulk_alloc == CACHE_ALLOC_NO_LOG_REQUIRED) - return; /* No logging required.. bulk port usage */ - else /* Individual logging .. fall back to old method */ -#endif - cnat_nfv9_insert_del_record(nfv9_logging_info, db, vrfmap); - - nfv9_logging_info->total_record_count += 1; - - /* - * If we have exceeded the packet length, let us send the - * packet now. There is buffer of additional bytes beyond - * max_pkt_length to ensure that the last add/delete record - * can be stored safely. - */ - if (PREDICT_FALSE(nfv9_logging_info->pkt_length > - nfv9_logging_info->max_length_minus_max_record_size)) { - cnat_nfv9_send_pkt(nfv9_logging_info); - } -} - - -/* NAT64 Related routines */ - -/* - * edt: * * cnat_nfv9_bib_mapping_create - * - * Tries to log a creation of Bib mapping record - * - * Argument: nat64_bib_entry_t *db - * BIB DB entry being created - * - * Argument: nat64_table_entry_t *nat64_entry - * NAT64 Instance where this BIB belongs - */ -void cnat_nfv9_bib_mapping_create (nat64_bib_entry_t *db, - nat64_table_entry_t *nat64_entry) -{ - cnat_nfv9_logging_info_t *nfv9_logging_info = 0; - u16 my_proto_mask; - u8 my_protocol; - nfv9_nat64_add_bib_record_t nfv9_logging_add_record; - - if (PREDICT_FALSE(nat64_entry->logging_index == EMPTY)) { - /* - * No logging configured, silently return - */ - return; - } - - nfv9_logging_info = - cnat_nfv9_logging_info_pool + nat64_entry->logging_index; - - - if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { - cnat_nfv9_create_logging_context(nfv9_logging_info, - cnat_nfv9_template_add_default); - - /* - * If still empty, return after increasing the count - */ - if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { - return; - } - } - - if (PREDICT_FALSE(nfv9_logging_info->record[NAT64_ADD_BIB_RECORD] == NULL)){ - cnat_nfv9_record_create(nfv9_logging_info,NAT64_ADD_BIB_RECORD); - } - - - nfv9_logging_add_record.inside_v6_src_addr[0] = - clib_host_to_net_u32(db->v6_in_key.ipv6[0]); - nfv9_logging_add_record.inside_v6_src_addr[1] = - clib_host_to_net_u32(db->v6_in_key.ipv6[1]); - nfv9_logging_add_record.inside_v6_src_addr[2] = - clib_host_to_net_u32(db->v6_in_key.ipv6[2]); - nfv9_logging_add_record.inside_v6_src_addr[3] = - clib_host_to_net_u32(db->v6_in_key.ipv6[3]); - - - nfv9_logging_add_record.outside_v4_src_addr = - clib_host_to_net_u32(db->v4_out_key.k.ipv4); - - nfv9_logging_add_record.inside_src_port = - clib_host_to_net_u16(db->v6_in_key.port); - nfv9_logging_add_record.outside_src_port = - clib_host_to_net_u16(db->v4_out_key.k.port); - - my_proto_mask = db->v6_in_key.vrf & CNAT_PRO_MASK; - - my_protocol = ((my_proto_mask == CNAT_UDP) ? UDP_PROT : - ((my_proto_mask == CNAT_TCP) ? TCP_PROT : - ((my_proto_mask == CNAT_ICMP) ? IPV6_PROTO_ICMPV6 : 0))); - nfv9_logging_add_record.protocol = my_protocol; - - - clib_memcpy(nfv9_logging_info->record[NAT64_ADD_BIB_RECORD], - &nfv9_logging_add_record, CNAT_NFV9_NAT64_ADD_BIB_RECORD_LENGTH); - - nfv9_logging_info->record_length[NAT64_ADD_BIB_RECORD] += - CNAT_NFV9_NAT64_ADD_BIB_RECORD_LENGTH; - nfv9_logging_info->pkt_length += CNAT_NFV9_NAT64_ADD_BIB_RECORD_LENGTH; - nfv9_logging_info->total_record_count += 1; - - nfv9_logging_info->record[NAT64_ADD_BIB_RECORD] - += CNAT_NFV9_NAT64_ADD_BIB_RECORD_LENGTH; - - nfv9_logging_info->next_data_ptr = - nfv9_logging_info->record[NAT64_ADD_BIB_RECORD]; - - nfv9_logging_info->dataflow_header->dataflow_length = - clib_host_to_net_u32( - nfv9_logging_info->record_length[NAT64_ADD_BIB_RECORD]); - - /* - * If we have exceeded the packet length, let us send the - * packet now. There is buffer of additional bytes beyond - * max_pkt_length to ensure that the last add/delete record - * can be stored safely. - */ - if (PREDICT_FALSE(nfv9_logging_info->pkt_length > - nfv9_logging_info->max_length_minus_max_record_size)) { - cnat_nfv9_send_pkt(nfv9_logging_info); - } -} - - -/* - * edt: * * cnat_nfv9_session_mapping_create - * - * Tries to log a creation of Bib mapping record - * - * Argument: nat64_bib_entry_t *bdb - * BIB DB entry for the session that is created - * - * Argument: nat64_session_entry_t *sdb - * Session DB entry being created - * - * Argument: nat64_table_entry_t *nat64_entry - * NAT64 Instance where this BIB and Session belongs - */ -void cnat_nfv9_session_mapping_create (nat64_bib_entry_t *bdb, - nat64_session_entry_t *sdb, - nat64_table_entry_t *nat64_entry_ptr) -{ - cnat_nfv9_logging_info_t *nfv9_logging_info = 0; - u16 my_proto_mask; - u8 my_protocol; - u32 dest_v6[4]; - nfv9_nat64_add_session_record_t nfv9_logging_add_record; - u8 *ipv6_addr_ptr; - u8 *ipv4_addr_ptr; - - - if (PREDICT_FALSE(nat64_entry_ptr->logging_index == EMPTY)) { - /* - * No logging configured, silently return - */ - return; - } - - nfv9_logging_info = - cnat_nfv9_logging_info_pool + nat64_entry_ptr->logging_index; - - - if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { - cnat_nfv9_create_logging_context(nfv9_logging_info, - cnat_nfv9_template_add_default); - - /* - * If still empty, return after increasing the count - */ - if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)){ - return; - } - } - - if (PREDICT_FALSE(nfv9_logging_info->record[NAT64_ADD_SESSION_RECORD] - == NULL)){ - cnat_nfv9_record_create(nfv9_logging_info, NAT64_ADD_SESSION_RECORD); - } - - - nfv9_logging_add_record.inside_v6_src_addr[0] = - clib_host_to_net_u32(bdb->v6_in_key.ipv6[0]); - nfv9_logging_add_record.inside_v6_src_addr[1] = - clib_host_to_net_u32(bdb->v6_in_key.ipv6[1]); - nfv9_logging_add_record.inside_v6_src_addr[2] = - clib_host_to_net_u32(bdb->v6_in_key.ipv6[2]); - nfv9_logging_add_record.inside_v6_src_addr[3] = - clib_host_to_net_u32(bdb->v6_in_key.ipv6[3]); - - - nfv9_logging_add_record.outside_v4_src_addr = - clib_host_to_net_u32(bdb->v4_out_key.k.ipv4); - - - nfv9_logging_add_record.outside_v4_dest_addr = - clib_host_to_net_u32(sdb->v4_dest_key.k.ipv4); - - /* Need to create the V6 address using prefix */ - dest_v6[0] = nat64_entry_ptr->v6_prefix[0]; - dest_v6[1] = nat64_entry_ptr->v6_prefix[1]; - dest_v6[2] = nat64_entry_ptr->v6_prefix[2]; - dest_v6[3] = nat64_entry_ptr->v6_prefix[3]; - - ipv6_addr_ptr = (u8 *) (&(dest_v6[0])); - ipv4_addr_ptr = (u8 *) (&(sdb->v4_dest_key.k.ipv4)); - - *(ipv6_addr_ptr + nat64_entry_ptr->octet0_position) = *(ipv4_addr_ptr); - *(ipv6_addr_ptr + nat64_entry_ptr->octet1_position) = *(ipv4_addr_ptr + 1); - *(ipv6_addr_ptr + nat64_entry_ptr->octet2_position) = *(ipv4_addr_ptr + 2); - *(ipv6_addr_ptr + nat64_entry_ptr->octet3_position) = *(ipv4_addr_ptr + 3); - - nfv9_logging_add_record.inside_v6_dest_addr[0] = - clib_host_to_net_u32(dest_v6[0]); - nfv9_logging_add_record.inside_v6_dest_addr[1] = - clib_host_to_net_u32(dest_v6[1]); - nfv9_logging_add_record.inside_v6_dest_addr[2] = - clib_host_to_net_u32(dest_v6[2]); - nfv9_logging_add_record.inside_v6_dest_addr[3] = - clib_host_to_net_u32(dest_v6[3]); - - nfv9_logging_add_record.outside_v4_dest_addr = - clib_host_to_net_u32(sdb->v4_dest_key.k.ipv4); - - nfv9_logging_add_record.inside_src_port = - clib_host_to_net_u16(bdb->v6_in_key.port); - nfv9_logging_add_record.outside_src_port = - clib_host_to_net_u16(bdb->v4_out_key.k.port); - - nfv9_logging_add_record.dest_port = - clib_host_to_net_u16(sdb->v4_dest_key.k.port); - - - my_proto_mask = bdb->v6_in_key.vrf & CNAT_PRO_MASK; - - my_protocol = ((my_proto_mask == CNAT_UDP) ? UDP_PROT : - ((my_proto_mask == CNAT_TCP) ? TCP_PROT : - ((my_proto_mask == CNAT_ICMP) ? IPV6_PROTO_ICMPV6 : 0))); - nfv9_logging_add_record.protocol = my_protocol; - - - clib_memcpy(nfv9_logging_info->record[NAT64_ADD_SESSION_RECORD], - &nfv9_logging_add_record, CNAT_NFV9_NAT64_ADD_SESSION_RECORD_LENGTH); - - nfv9_logging_info->record_length[NAT64_ADD_SESSION_RECORD] += - CNAT_NFV9_NAT64_ADD_SESSION_RECORD_LENGTH; - nfv9_logging_info->pkt_length += CNAT_NFV9_NAT64_ADD_SESSION_RECORD_LENGTH; - nfv9_logging_info->total_record_count += 1; - - nfv9_logging_info->record[NAT64_ADD_SESSION_RECORD] - += CNAT_NFV9_NAT64_ADD_SESSION_RECORD_LENGTH; - - nfv9_logging_info->next_data_ptr = - nfv9_logging_info->record[NAT64_ADD_SESSION_RECORD]; - - nfv9_logging_info->dataflow_header->dataflow_length = - clib_host_to_net_u32( - nfv9_logging_info->record_length[NAT64_ADD_SESSION_RECORD]); - - /* - * If we have exceeded the packet length, let us send the - * packet now. There is buffer of additional bytes beyond - * max_pkt_length to ensure that the last add/delete record - * can be stored safely. - */ - if (PREDICT_FALSE(nfv9_logging_info->pkt_length > - nfv9_logging_info->max_length_minus_max_record_size)) { - cnat_nfv9_send_pkt(nfv9_logging_info); - } -} - - -/* - * edt: * * cnat_nfv9_bib_mapping_delete - * - * Tries to log a deletion of Bib mapping record - * - * Argument: nat64_bib_entry_t *db - * BIB DB entry being created - * - * Argument: nat64_table_entry_t *nat64_entry - * NAT64 Instance where this BIB belongs - */ -void cnat_nfv9_bib_mapping_delete (nat64_bib_entry_t *db, - nat64_table_entry_t *nat64_entry) -{ - cnat_nfv9_logging_info_t *nfv9_logging_info = 0; - u16 my_proto_mask; - u8 my_protocol; - nfv9_nat64_del_bib_record_t nfv9_logging_del_record; - if (PREDICT_FALSE(nat64_entry->logging_index == EMPTY)) { - /* - * No logging configured, silently return - */ - return; - } - - nfv9_logging_info = - cnat_nfv9_logging_info_pool + nat64_entry->logging_index; - - - if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { - cnat_nfv9_create_logging_context(nfv9_logging_info, - cnat_nfv9_template_add_default); - - /* - * If still empty, return after increasing the count - */ - if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)){ - return; - } - } - - if (PREDICT_FALSE(nfv9_logging_info->record[NAT64_DEL_BIB_RECORD] == NULL)){ - cnat_nfv9_record_create(nfv9_logging_info,NAT64_DEL_BIB_RECORD); - } - - - nfv9_logging_del_record.inside_v6_src_addr[0] = - clib_host_to_net_u32(db->v6_in_key.ipv6[0]); - nfv9_logging_del_record.inside_v6_src_addr[1] = - clib_host_to_net_u32(db->v6_in_key.ipv6[1]); - nfv9_logging_del_record.inside_v6_src_addr[2] = - clib_host_to_net_u32(db->v6_in_key.ipv6[2]); - nfv9_logging_del_record.inside_v6_src_addr[3] = - clib_host_to_net_u32(db->v6_in_key.ipv6[3]); - - - nfv9_logging_del_record.inside_src_port = - clib_host_to_net_u16(db->v6_in_key.port); - - my_proto_mask = db->v6_in_key.vrf & CNAT_PRO_MASK; - - my_protocol = ((my_proto_mask == CNAT_UDP) ? UDP_PROT : - ((my_proto_mask == CNAT_TCP) ? TCP_PROT : - ((my_proto_mask == CNAT_ICMP) ? IPV6_PROTO_ICMPV6 : 0))); - nfv9_logging_del_record.protocol = my_protocol; - - - clib_memcpy(nfv9_logging_info->record[NAT64_DEL_BIB_RECORD], - &nfv9_logging_del_record, CNAT_NFV9_NAT64_DEL_BIB_RECORD_LENGTH); - - nfv9_logging_info->record_length[NAT64_DEL_BIB_RECORD] += - CNAT_NFV9_NAT64_DEL_BIB_RECORD_LENGTH; - nfv9_logging_info->pkt_length += CNAT_NFV9_NAT64_DEL_BIB_RECORD_LENGTH; - nfv9_logging_info->total_record_count += 1; - - nfv9_logging_info->record[NAT64_DEL_BIB_RECORD] - += CNAT_NFV9_NAT64_DEL_BIB_RECORD_LENGTH; - - nfv9_logging_info->next_data_ptr = - nfv9_logging_info->record[NAT64_DEL_BIB_RECORD]; - - nfv9_logging_info->dataflow_header->dataflow_length = - clib_host_to_net_u32( - nfv9_logging_info->record_length[NAT64_DEL_BIB_RECORD]); - - /* - * If we have exceeded the packet length, let us send the - * packet now. There is buffer of additional bytes beyond - * max_pkt_length to ensure that the last add/delete record - * can be stored safely. - */ - if (PREDICT_FALSE(nfv9_logging_info->pkt_length > - nfv9_logging_info->max_length_minus_max_record_size)) { - cnat_nfv9_send_pkt(nfv9_logging_info); - } -} - - -/* - * edt: * * cnat_nfv9_session_mapping_delete - * - * Tries to log a deletion of Bib mapping record - * - * Argument: nat64_bib_entry_t *bdb - * BIB DB entry for the session that is created - * - * Argument: nat64_session_entry_t *sdb - * Session DB entry being created - * - * Argument: nat64_table_entry_t *nat64_entry - * NAT64 Instance where this BIB and Session belongs - */ -void cnat_nfv9_session_mapping_delete (nat64_bib_entry_t *bdb, - nat64_session_entry_t *sdb, - nat64_table_entry_t *nat64_entry_ptr) -{ - cnat_nfv9_logging_info_t *nfv9_logging_info = 0; - u16 my_proto_mask; - u8 my_protocol; - u32 dest_v6[4]; - nfv9_nat64_del_session_record_t nfv9_logging_del_record; - u8 *ipv6_addr_ptr; - u8 *ipv4_addr_ptr; - - if (PREDICT_FALSE(nat64_entry_ptr->logging_index == EMPTY)) { - /* - * No logging configured, silently return - */ - return; - } - - nfv9_logging_info = - cnat_nfv9_logging_info_pool + nat64_entry_ptr->logging_index; - - - if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { - cnat_nfv9_create_logging_context(nfv9_logging_info, - cnat_nfv9_template_add_default); - - /* - * If still empty, return after increasing the count - */ - if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)){ - return; - } - } - - if (PREDICT_FALSE(nfv9_logging_info->record[NAT64_DEL_SESSION_RECORD] - == NULL)){ - cnat_nfv9_record_create(nfv9_logging_info, NAT64_DEL_SESSION_RECORD); - } - - - nfv9_logging_del_record.inside_v6_src_addr[0] = - clib_host_to_net_u32(bdb->v6_in_key.ipv6[0]); - nfv9_logging_del_record.inside_v6_src_addr[1] = - clib_host_to_net_u32(bdb->v6_in_key.ipv6[1]); - nfv9_logging_del_record.inside_v6_src_addr[2] = - clib_host_to_net_u32(bdb->v6_in_key.ipv6[2]); - nfv9_logging_del_record.inside_v6_src_addr[3] = - clib_host_to_net_u32(bdb->v6_in_key.ipv6[3]); - - /* Need to create the V6 address using prefix */ - dest_v6[0] = nat64_entry_ptr->v6_prefix[0]; - dest_v6[1] = nat64_entry_ptr->v6_prefix[1]; - dest_v6[2] = nat64_entry_ptr->v6_prefix[2]; - dest_v6[3] = nat64_entry_ptr->v6_prefix[3]; - - ipv6_addr_ptr = (u8 *) (&(dest_v6[0])); - ipv4_addr_ptr = (u8 *) (&(sdb->v4_dest_key.k.ipv4)); - - *(ipv6_addr_ptr + nat64_entry_ptr->octet0_position) = *(ipv4_addr_ptr); - *(ipv6_addr_ptr + nat64_entry_ptr->octet1_position) = *(ipv4_addr_ptr + 1); - *(ipv6_addr_ptr + nat64_entry_ptr->octet2_position) = *(ipv4_addr_ptr + 2); - *(ipv6_addr_ptr + nat64_entry_ptr->octet3_position) = *(ipv4_addr_ptr + 3); - - nfv9_logging_del_record.inside_v6_dest_addr[0] = - clib_host_to_net_u32(dest_v6[0]); - nfv9_logging_del_record.inside_v6_dest_addr[1] = - clib_host_to_net_u32(dest_v6[1]); - nfv9_logging_del_record.inside_v6_dest_addr[2] = - clib_host_to_net_u32(dest_v6[2]); - nfv9_logging_del_record.inside_v6_dest_addr[3] = - clib_host_to_net_u32(dest_v6[3]); - - nfv9_logging_del_record.inside_src_port = - clib_host_to_net_u16(bdb->v6_in_key.port); - - nfv9_logging_del_record.dest_port = - clib_host_to_net_u16(sdb->v4_dest_key.k.port); - - - my_proto_mask = bdb->v6_in_key.vrf & CNAT_PRO_MASK; - - my_protocol = ((my_proto_mask == CNAT_UDP) ? UDP_PROT : - ((my_proto_mask == CNAT_TCP) ? TCP_PROT : - ((my_proto_mask == CNAT_ICMP) ? IPV6_PROTO_ICMPV6 : 0))); - nfv9_logging_del_record.protocol = my_protocol; - - clib_memcpy(nfv9_logging_info->record[NAT64_DEL_SESSION_RECORD], - &nfv9_logging_del_record, CNAT_NFV9_NAT64_DEL_SESSION_RECORD_LENGTH); - - nfv9_logging_info->record_length[NAT64_DEL_SESSION_RECORD] += - CNAT_NFV9_NAT64_DEL_SESSION_RECORD_LENGTH; - nfv9_logging_info->pkt_length += CNAT_NFV9_NAT64_DEL_SESSION_RECORD_LENGTH; - nfv9_logging_info->total_record_count += 1; - - nfv9_logging_info->record[NAT64_DEL_SESSION_RECORD] - += CNAT_NFV9_NAT64_DEL_SESSION_RECORD_LENGTH; - - nfv9_logging_info->next_data_ptr = - nfv9_logging_info->record[NAT64_DEL_SESSION_RECORD]; - - nfv9_logging_info->dataflow_header->dataflow_length = - clib_host_to_net_u32( - nfv9_logging_info->record_length[NAT64_DEL_SESSION_RECORD]); - - /* - * If we have exceeded the packet length, let us send the - * packet now. There is buffer of additional bytes beyond - * max_pkt_length to ensure that the last add/delete record - * can be stored safely. - */ - if (PREDICT_FALSE(nfv9_logging_info->pkt_length > - nfv9_logging_info->max_length_minus_max_record_size)) { - cnat_nfv9_send_pkt(nfv9_logging_info); - } -} - -/* - * edt: * * cnat_nfv9_nat44_log_session_create - * - * Tries to log a creation of mapping record (session based) - * - * Argument: cnat_main_db_entry_t *db - * Main DB entry being created - * Arugment: cnat_session_entry_t *sdb - * Session DB entry if the destination is not the first dest - * Argument: cnat_vrfmap_t *vrfmap - * VRF Map for the Main DB entry being created - */ - -void cnat_nfv9_nat44_log_session_create(cnat_main_db_entry_t *db, - cnat_session_entry_t *sdb, - cnat_vrfmap_t *vrfmap) -{ - cnat_nfv9_logging_info_t *nfv9_logging_info = 0; - u16 my_proto_mask; - u8 my_protocol; - nfv9_add_session_record_t nfv9_logging_add_session_record; - - if (PREDICT_FALSE(vrfmap->nfv9_logging_index == EMPTY)) { - //vlib_cli_output(vm,"\n1. Log Mapping failed"); - /* - * No logging configured, silently return - */ - return; - } - - nfv9_logging_info = - cnat_nfv9_logging_info_pool + vrfmap->nfv9_logging_index; - - if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { - cnat_nfv9_create_logging_context(nfv9_logging_info, - cnat_nfv9_template_add_default); - - /* - * If still empty, return after increasing the count - */ - if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { - //vlib_cli_output(vm,"\n2. Log Mapping failed"); - return; - } - } - - if(PREDICT_FALSE(nfv9_logging_info->record[ - NAT44_ADD_SESSION_RECORD] == NULL)) { - cnat_nfv9_record_create(nfv9_logging_info, NAT44_ADD_SESSION_RECORD); - } - - /* - * We should definitely have add_record now, no need to sanitize - */ - nfv9_logging_add_session_record.inside_vrf_id = - clib_host_to_net_u32(vrfmap->i_vrf_id); - nfv9_logging_add_session_record.outside_vrf_id = - clib_host_to_net_u32(vrfmap->o_vrf_id); - - nfv9_logging_add_session_record.inside_ip_addr = - clib_host_to_net_u32(db->in2out_key.k.ipv4); - nfv9_logging_add_session_record.outside_ip_addr = - clib_host_to_net_u32(db->out2in_key.k.ipv4); - - /* If sdb is null, it is assumed that logging is being done - * for the first destination which is held in the main db - - * itself - */ - if(PREDICT_TRUE(sdb == NULL)) { - nfv9_logging_add_session_record.dest_ip_addr = - clib_host_to_net_u32(db->dst_ipv4); - nfv9_logging_add_session_record.dest_port = - clib_host_to_net_u16(db->dst_port); - } else { - nfv9_logging_add_session_record.dest_ip_addr = - clib_host_to_net_u32(sdb->v4_dest_key.k.ipv4); - nfv9_logging_add_session_record.dest_port = - clib_host_to_net_u16(sdb->v4_dest_key.k.port); - } - - nfv9_logging_add_session_record.inside_ip_port = - clib_host_to_net_u16(db->in2out_key.k.port); - nfv9_logging_add_session_record.outside_ip_port = - clib_host_to_net_u16(db->out2in_key.k.port); - - - my_proto_mask = db->in2out_key.k.vrf & CNAT_PRO_MASK; - - my_protocol = ((my_proto_mask == CNAT_UDP) ? UDP_PROT : - ((my_proto_mask == CNAT_TCP) ? TCP_PROT : - ((my_proto_mask == CNAT_ICMP) ? ICMP_PROT : GRE_PROT))); - nfv9_logging_add_session_record.protocol = my_protocol; - - clib_memcpy(nfv9_logging_info->record[NAT44_ADD_SESSION_RECORD], - &nfv9_logging_add_session_record, - CNAT_NFV9_NAT44_ADD_SESSION_RECORD_LENGTH); - - nfv9_logging_info->record_length[NAT44_ADD_SESSION_RECORD] - += CNAT_NFV9_NAT44_ADD_SESSION_RECORD_LENGTH; - nfv9_logging_info->pkt_length += CNAT_NFV9_NAT44_ADD_SESSION_RECORD_LENGTH; - nfv9_logging_info->total_record_count += 1; - - - nfv9_logging_info->record[NAT44_ADD_SESSION_RECORD] - += CNAT_NFV9_NAT44_ADD_SESSION_RECORD_LENGTH; - - nfv9_logging_info->next_data_ptr = - nfv9_logging_info->record[NAT44_ADD_SESSION_RECORD]; - - nfv9_logging_info->dataflow_header->dataflow_length = - clib_host_to_net_u32( - nfv9_logging_info->record_length[NAT44_ADD_SESSION_RECORD]); - - /* - * If we have exceeded the packet length, let us send the - * packet now. There is buffer of additional bytes beyond - * max_pkt_length to ensure that the last add/delete record - * can be stored safely. - */ - if (PREDICT_FALSE(nfv9_logging_info->pkt_length > - nfv9_logging_info->max_length_minus_max_record_size)) { - cnat_nfv9_send_pkt(nfv9_logging_info); - } -} - -/* - * edt: * * cnat_nfv9_nat44_log_session_delete - * - * Tries to log a deletion of mapping record (session based) - * - * Argument: cnat_main_db_entry_t *db - * Main DB entry being created - * Arugment: cnat_session_entry_t *sdb - * Session DB entry if the destination is not the first dest - * Argument: cnat_vrfmap_t *vrfmap - * VRF Map for the Main DB entry being deleted - */ - -void cnat_nfv9_nat44_log_session_delete(cnat_main_db_entry_t *db, - cnat_session_entry_t *sdb, - cnat_vrfmap_t *vrfmap) -{ - cnat_nfv9_logging_info_t *nfv9_logging_info = 0; - u16 my_proto_mask; - u8 my_protocol; - nfv9_del_session_record_t nfv9_logging_del_session_record; - - if (PREDICT_FALSE(vrfmap->nfv9_logging_index == EMPTY)) { - //vlib_cli_output(vm, "\n1. Log Mapping failed"); - /* - * No logging configured, silently return - */ - return; - } - - nfv9_logging_info = - cnat_nfv9_logging_info_pool + vrfmap->nfv9_logging_index; - - if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { - cnat_nfv9_create_logging_context(nfv9_logging_info, - cnat_nfv9_template_add_default); - - /* - * If still empty, return after increasing the count - */ - if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { - //vlib_cli_output(vm, "\n2. Log Mapping failed"); - return; - } - } - - if(PREDICT_FALSE(nfv9_logging_info->record[ - NAT44_DEL_SESSION_RECORD] == NULL)) { - cnat_nfv9_record_create(nfv9_logging_info, NAT44_DEL_SESSION_RECORD); - } - - /* - * We should definitely have add_record now, no need to sanitize - */ - nfv9_logging_del_session_record.inside_vrf_id = - clib_host_to_net_u32(vrfmap->i_vrf_id); - - nfv9_logging_del_session_record.inside_ip_addr = - clib_host_to_net_u32(db->in2out_key.k.ipv4); - - /* If sdb is null, it is assumed that logging is being done - * for the first destination which is held in the main db - * itself - */ - if(PREDICT_TRUE(sdb == NULL)) { - nfv9_logging_del_session_record.dest_ip_addr = - clib_host_to_net_u32(db->dst_ipv4); - nfv9_logging_del_session_record.dest_port = - clib_host_to_net_u16(db->dst_port); - } else { - nfv9_logging_del_session_record.dest_ip_addr = - clib_host_to_net_u32(sdb->v4_dest_key.k.ipv4); - nfv9_logging_del_session_record.dest_port = - clib_host_to_net_u16(sdb->v4_dest_key.k.port); - } - - nfv9_logging_del_session_record.inside_ip_port = - clib_host_to_net_u16(db->in2out_key.k.port); - - my_proto_mask = db->in2out_key.k.vrf & CNAT_PRO_MASK; - my_protocol = ((my_proto_mask == CNAT_UDP) ? UDP_PROT : - ((my_proto_mask == CNAT_TCP) ? TCP_PROT : - ((my_proto_mask == CNAT_ICMP) ? ICMP_PROT : GRE_PROT))); - - nfv9_logging_del_session_record.protocol = my_protocol; - - clib_memcpy(nfv9_logging_info->record[NAT44_DEL_SESSION_RECORD], - &nfv9_logging_del_session_record, - CNAT_NFV9_NAT44_DEL_SESSION_RECORD_LENGTH); - - nfv9_logging_info->record_length[NAT44_DEL_SESSION_RECORD] - += CNAT_NFV9_NAT44_DEL_SESSION_RECORD_LENGTH; - nfv9_logging_info->pkt_length += CNAT_NFV9_NAT44_DEL_SESSION_RECORD_LENGTH; - nfv9_logging_info->total_record_count += 1; - - nfv9_logging_info->record[NAT44_DEL_SESSION_RECORD] - += CNAT_NFV9_NAT44_DEL_SESSION_RECORD_LENGTH; - - nfv9_logging_info->next_data_ptr = - nfv9_logging_info->record[NAT44_DEL_SESSION_RECORD]; - - nfv9_logging_info->dataflow_header->dataflow_length = - clib_host_to_net_u32( - nfv9_logging_info->record_length[NAT44_DEL_SESSION_RECORD]); - - /* - * If we have exceeded the packet length, let us send the - * packet now. There is buffer of additional bytes beyond - * max_pkt_length to ensure that the last add/delete record - * can be stored safely. - */ - if (PREDICT_FALSE(nfv9_logging_info->pkt_length > - nfv9_logging_info->max_length_minus_max_record_size)) { - cnat_nfv9_send_pkt(nfv9_logging_info); - } -} - -/* - * DS-Lite APIs for netflow logging - */ - -/* - * edt: * * cnat_nfv9_ds_lite_mapping_create - * - * Tries to log a creation of mapping record - * - * Argument: cnat_main_db_entry_t *db - * Main DB entry being created - * - * Argument: dslite_table_entry_t *dslite_entry - * ds-lite instance for the Main DB entry being created - */ -void cnat_nfv9_ds_lite_mapping_create(cnat_main_db_entry_t *db, - dslite_table_entry_t *dslite_entry -#ifndef NO_BULK_LOGGING - , int bulk_alloc -#endif - ) -{ - - cnat_nfv9_logging_info_t *nfv9_logging_info = NULL; - - if (PREDICT_FALSE(!(db && dslite_entry))) { - return; - } - if (PREDICT_FALSE(dslite_entry->nfv9_logging_index == EMPTY)) { - /* - * no logging configured, silently return - */ - return; - } - - nfv9_logging_info = - cnat_nfv9_logging_info_pool + dslite_entry->nfv9_logging_index; - if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { - cnat_nfv9_create_logging_context(nfv9_logging_info, - cnat_nfv9_template_add_default); - /* - * If still empty, return after increasing the count - */ - if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { - return; - } - } -#ifndef NO_BULK_LOGGING - if(bulk_alloc > 0) { /* new bulk alloc - use bulk add template */ - cnat_nfv9_ds_lite_insert_bulk_add_record(nfv9_logging_info, - db, dslite_entry, bulk_alloc); - } else if(bulk_alloc == CACHE_ALLOC_NO_LOG_REQUIRED) - return; /* No logging required.. bulk port usage */ - else /* Individual logging .. fall back to old method */ -#endif /*NO_BULK_LOGGING*/ - cnat_nfv9_ds_lite_insert_add_record(nfv9_logging_info, db, dslite_entry); - /* - * If we have exceeded the packet length, let us send the - * packet now. There is buffer of additional bytes beyond - * max_pkt_length to ensure that the last add/delete record - * can be stored safely. - */ - if (PREDICT_FALSE(nfv9_logging_info->pkt_length > - nfv9_logging_info->max_length_minus_max_record_size)) { - cnat_nfv9_send_pkt(nfv9_logging_info); - } -} - -/* - * edt: * * cnat_nfv9_ds_lite_mapping_delete - * - * Tries to log a deletion of mapping record - * - * Argument: cnat_main_db_entry_t *db - * Main DB entry being deleted - * - * Argument: dslite_table_entry_t *dslite_entry - * ds-lite instance for the Main DB entry being deleted - */ -void cnat_nfv9_ds_lite_mapping_delete(cnat_main_db_entry_t *db, - dslite_table_entry_t *dslite_entry -#ifndef NO_BULK_LOGGING - , int bulk_alloc -#endif - ) -{ - - cnat_nfv9_logging_info_t *nfv9_logging_info = NULL; - if (PREDICT_FALSE(!(db && dslite_entry))) { - return; - } - if (PREDICT_FALSE(dslite_entry->nfv9_logging_index == EMPTY)) { - /* - * No logging configured, silently return - */ - return; - } - nfv9_logging_info = - cnat_nfv9_logging_info_pool + dslite_entry->nfv9_logging_index; - - - if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { - cnat_nfv9_create_logging_context(nfv9_logging_info, - cnat_nfv9_template_add_default); - /* - * If still empty, return after increasing the count - */ - if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { - return; - } - } -#ifndef NO_BULK_LOGGING - if(bulk_alloc > 0) { /* new bulk alloc - use bulk add template */ - cnat_nfv9_ds_lite_insert_bulk_del_record(nfv9_logging_info, - db, dslite_entry, bulk_alloc); - } else if(bulk_alloc == CACHE_ALLOC_NO_LOG_REQUIRED) - return; /* No logging required.. bulk port usage */ - else /* Individual logging .. fall back to old method */ -#endif /*NO_BULK_LOGGING*/ - cnat_nfv9_ds_lite_insert_del_record(nfv9_logging_info, db, dslite_entry); - /* - * If we have exceeded the packet length, let us send the - * packet now. There is buffer of additional bytes beyond - * max_pkt_length to ensure that the last add/delete record - * can be stored safely. - */ - if (PREDICT_FALSE(nfv9_logging_info->pkt_length > - nfv9_logging_info->max_length_minus_max_record_size)) { - cnat_nfv9_send_pkt(nfv9_logging_info); - } -} - -/* - * edt: * * cnat_nfv9_dslite_log_session_create - * - * Tries to log a creation of mapping record (session based) - * Argument: cnat_main_db_entry_t *db - * Main DB entry being created - * Arugment: cnat_session_entry_t *sdb - * Session DB entry if the destination is not the first dest - * Argument: dslite_table_entry_t *dslite_entry, - * dslite table entry for dslite instance - */ - -void cnat_nfv9_ds_lite_log_session_create( - cnat_main_db_entry_t *db, - dslite_table_entry_t *dslite_entry, - cnat_session_entry_t *sdb) -{ - - nfv9_ds_lite_add_session_record_t nfv9_logging_add_record ; - cnat_user_db_entry_t *udb = NULL; - u16 my_proto_mask; - u8 my_protocol; - cnat_nfv9_logging_info_t *nfv9_logging_info = 0; - - if (PREDICT_FALSE(dslite_entry->nfv9_logging_index == EMPTY)) { - /* - * no logging configured, silently return - */ - return; - } - - nfv9_logging_info = - cnat_nfv9_logging_info_pool + dslite_entry->nfv9_logging_index; - udb = cnat_user_db + db->user_index; - - if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { - cnat_nfv9_create_logging_context(nfv9_logging_info, - cnat_nfv9_template_add_default); - - /* - * If still empty, return after increasing the count - */ - if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { - return; - } - } - - udb = cnat_user_db + db->user_index; - if (PREDICT_FALSE(!udb)) { - return; - } - if (PREDICT_FALSE(nfv9_logging_info->record[DS_LITE_ADD_SESSION_RECORD] == NULL)) { - cnat_nfv9_record_create(nfv9_logging_info, DS_LITE_ADD_SESSION_RECORD); - } - /* - * We should definitely have add_record now, no need to sanitize - */ - nfv9_logging_add_record.inside_vrf_id = - clib_host_to_net_u32(dslite_entry->i_vrf_id); - nfv9_logging_add_record.outside_vrf_id = - clib_host_to_net_u32(dslite_entry->o_vrf_id); - - nfv9_logging_add_record.inside_ip_addr = - clib_host_to_net_u32(db->in2out_key.k.ipv4); - - nfv9_logging_add_record.inside_v6_src_addr[0] = - clib_host_to_net_u32(udb->ipv6[0]); - nfv9_logging_add_record.inside_v6_src_addr[1] = - clib_host_to_net_u32(udb->ipv6[1]); - nfv9_logging_add_record.inside_v6_src_addr[2] = - clib_host_to_net_u32(udb->ipv6[2]); - nfv9_logging_add_record.inside_v6_src_addr[3] = - clib_host_to_net_u32(udb->ipv6[3]); - - nfv9_logging_add_record.outside_ip_addr = - clib_host_to_net_u32(db->out2in_key.k.ipv4); - - nfv9_logging_add_record.inside_ip_port = - clib_host_to_net_u16(db->in2out_key.k.port); - nfv9_logging_add_record.outside_ip_port = - clib_host_to_net_u16(db->out2in_key.k.port); - - /* If sdb is null, it is assumed that logging is being done - * for the first destination which is held in the main db - - * itself - */ - if(PREDICT_TRUE(sdb == NULL)) { - nfv9_logging_add_record.dest_ip_addr = - clib_host_to_net_u32(db->dst_ipv4); - nfv9_logging_add_record.dest_port = - clib_host_to_net_u16(db->dst_port); - } else { - nfv9_logging_add_record.dest_ip_addr = - clib_host_to_net_u32(sdb->v4_dest_key.k.ipv4); - nfv9_logging_add_record.dest_port = - clib_host_to_net_u16(sdb->v4_dest_key.k.port); - } - - - my_proto_mask = db->in2out_key.k.vrf & CNAT_PRO_MASK; - - my_protocol = ((my_proto_mask == CNAT_UDP) ? UDP_PROT : - ((my_proto_mask == CNAT_TCP) ? TCP_PROT : - ((my_proto_mask == CNAT_ICMP) ? ICMP_PROT : 0))); - nfv9_logging_add_record.protocol = my_protocol; - - clib_memcpy(nfv9_logging_info->record[DS_LITE_ADD_SESSION_RECORD], - &nfv9_logging_add_record, CNAT_NFV9_DS_LITE_ADD_SESSION_RECORD_LENGTH); - - nfv9_logging_info->record_length[DS_LITE_ADD_SESSION_RECORD] - += CNAT_NFV9_DS_LITE_ADD_SESSION_RECORD_LENGTH; - - nfv9_logging_info->pkt_length += CNAT_NFV9_DS_LITE_ADD_SESSION_RECORD_LENGTH; - nfv9_logging_info->total_record_count += 1; - - nfv9_logging_info->record[DS_LITE_ADD_SESSION_RECORD] - += CNAT_NFV9_DS_LITE_ADD_SESSION_RECORD_LENGTH; - nfv9_logging_info->next_data_ptr = - nfv9_logging_info->record[DS_LITE_ADD_SESSION_RECORD]; - - nfv9_logging_info->dataflow_header->dataflow_length = - clib_host_to_net_u32( - nfv9_logging_info->record_length[DS_LITE_ADD_SESSION_RECORD]); - - /* - * If we have exceeded the packet length, let us send the - * packet now. There is buffer of additional bytes beyond - * max_pkt_length to ensure that the last add/delete record - * can be stored safely. - */ - if (PREDICT_FALSE(nfv9_logging_info->pkt_length > - nfv9_logging_info->max_length_minus_max_record_size)) { - cnat_nfv9_send_pkt(nfv9_logging_info); - } - -} - -/* - * edt: * * cnat_nfv9_dslite_log_session_delete - * - * Tries to log a creation of mapping record (session based) - * Argument: cnat_main_db_entry_t *db - * Main DB entry being created - * Arugment: cnat_session_entry_t *sdb - * Session DB entry if the destination is not the first dest - * Argument: dslite_table_entry_t *dslite_entry, - * dslite table entry for dslite instance - */ - -void cnat_nfv9_ds_lite_log_session_delete( - cnat_main_db_entry_t *db, - dslite_table_entry_t *dslite_entry, - cnat_session_entry_t *sdb) -{ - - nfv9_ds_lite_del_session_record_t nfv9_logging_add_record = {0}; - cnat_user_db_entry_t *udb = NULL; - u16 my_proto_mask; - u8 my_protocol; - cnat_nfv9_logging_info_t *nfv9_logging_info = NULL; - - if (PREDICT_FALSE(dslite_entry->nfv9_logging_index == EMPTY)) { - /* - * no logging configured, silently return - */ - return; - } - - nfv9_logging_info = - cnat_nfv9_logging_info_pool + dslite_entry->nfv9_logging_index; - udb = cnat_user_db + db->user_index; - - if (PREDICT_FALSE(!udb)) { - return; - } - - if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { - cnat_nfv9_create_logging_context(nfv9_logging_info, - cnat_nfv9_template_add_default); - - /* - * If still empty, return after increasing the count - */ - if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { - return; - } - } - - if (PREDICT_FALSE(nfv9_logging_info->record[DS_LITE_DEL_SESSION_RECORD] == NULL)) { - cnat_nfv9_record_create(nfv9_logging_info, DS_LITE_DEL_SESSION_RECORD); - } - /* - * We should definitely have add_record now, no need to sanitize - */ - nfv9_logging_add_record.inside_vrf_id = - clib_host_to_net_u32(dslite_entry->i_vrf_id); - - nfv9_logging_add_record.inside_ip_addr = - clib_host_to_net_u32(db->in2out_key.k.ipv4); - - nfv9_logging_add_record.inside_v6_src_addr[0] = - clib_host_to_net_u32(udb->ipv6[0]); - nfv9_logging_add_record.inside_v6_src_addr[1] = - clib_host_to_net_u32(udb->ipv6[1]); - nfv9_logging_add_record.inside_v6_src_addr[2] = - clib_host_to_net_u32(udb->ipv6[2]); - nfv9_logging_add_record.inside_v6_src_addr[3] = - clib_host_to_net_u32(udb->ipv6[3]); - - nfv9_logging_add_record.inside_ip_port = - clib_host_to_net_u16(db->in2out_key.k.port); - - /* If sdb is null, it is assumed that logging is being done - * for the first destination which is held in the main db - * itself - */ - if(PREDICT_TRUE(sdb == NULL)) { - nfv9_logging_add_record.dest_ip_addr = - clib_host_to_net_u32(db->dst_ipv4); - nfv9_logging_add_record.dest_port = - clib_host_to_net_u16(db->dst_port); - } else { - nfv9_logging_add_record.dest_ip_addr = - clib_host_to_net_u32(sdb->v4_dest_key.k.ipv4); - nfv9_logging_add_record.dest_port = - clib_host_to_net_u16(sdb->v4_dest_key.k.port); - } - - - my_proto_mask = db->in2out_key.k.vrf & CNAT_PRO_MASK; - - my_protocol = ((my_proto_mask == CNAT_UDP) ? UDP_PROT : - ((my_proto_mask == CNAT_TCP) ? TCP_PROT : - ((my_proto_mask == CNAT_ICMP) ? ICMP_PROT : 0))); - nfv9_logging_add_record.protocol = my_protocol; - - clib_memcpy(nfv9_logging_info->record[DS_LITE_DEL_SESSION_RECORD], - &nfv9_logging_add_record, CNAT_NFV9_DS_LITE_DEL_SESSION_RECORD_LENGTH); - - nfv9_logging_info->record_length[DS_LITE_DEL_SESSION_RECORD] - += CNAT_NFV9_DS_LITE_DEL_SESSION_RECORD_LENGTH; - - nfv9_logging_info->pkt_length += CNAT_NFV9_DS_LITE_DEL_SESSION_RECORD_LENGTH; - nfv9_logging_info->total_record_count += 1; - - nfv9_logging_info->record[DS_LITE_DEL_SESSION_RECORD] - += CNAT_NFV9_DS_LITE_DEL_SESSION_RECORD_LENGTH; - nfv9_logging_info->next_data_ptr = - nfv9_logging_info->record[DS_LITE_DEL_SESSION_RECORD]; - - nfv9_logging_info->dataflow_header->dataflow_length = - clib_host_to_net_u32( - nfv9_logging_info->record_length[DS_LITE_DEL_SESSION_RECORD]); - - /* - * If we have exceeded the packet length, let us send the - * packet now. There is buffer of additional bytes beyond - * max_pkt_length to ensure that the last add/delete record - * can be stored safely. - */ - if (PREDICT_FALSE(nfv9_logging_info->pkt_length > - nfv9_logging_info->max_length_minus_max_record_size)) { - cnat_nfv9_send_pkt(nfv9_logging_info); - } - -} - - -/* - * netflow logging API for ingress vrf_id to name mapping - */ - -/* - * edt: * * handle_vrfid_name_mapping - * It will search for valid natflow entry in netflow pool, - * once found one, will send all vrfid name mapping info - * using that entry - */ - - -static inline __attribute__((unused)) -void handle_vrfid_name_mapping(void) -{ - cnat_nfv9_logging_info_t *nfv9_logging_info = NULL; - - pool_foreach (nfv9_logging_info, cnat_nfv9_logging_info_pool, ({ - if(PREDICT_FALSE(nfv9_logging_info == NULL)) { - continue; - } - nfv9_server_info_t *server = nfv9_server_info_pool + - nfv9_logging_info->server_index; - if(server->template_sent == TEMPLATE_SENT_TRUE) { - cnat_nfv9_ingress_vrfid_name_mapping_create(nfv9_logging_info); - server->template_sent = TEMPLATE_SENT_FALSE; - } - })); -} - -/* - * edt: * * cnat_nfv9_ingress_vrfid_name_mapping_create - * - * Tries to log vrfid-name mapping record - * Argument: netflow pointer - */ - - -void cnat_nfv9_ingress_vrfid_name_mapping_create( - cnat_nfv9_logging_info_t *nfv9_logging_info) -{ - u16 index = 0; - - for (index = 0; index < MAX_VRFID; index++) { - if(vrfid_name_map[index].ref_count == 0) { - continue; - } - if (PREDICT_FALSE( - nfv9_logging_info->current_logging_context == NULL)) { - cnat_nfv9_create_logging_context(nfv9_logging_info, - cnat_nfv9_template_add_default); - } - cnat_nfv9_insert_ingress_vrfid_name_record( - nfv9_logging_info,index); - if (PREDICT_FALSE(nfv9_logging_info->pkt_length > - nfv9_logging_info->max_length_minus_max_record_size) || - PREDICT_FALSE(index == MAX_VRFID - 1)) { - if (PREDICT_TRUE(nfv9_logging_info->current_logging_context - != NULL)) { - cnat_nfv9_send_pkt(nfv9_logging_info); - } - } - }/*for()*/ - return; -} - -static void cnat_nfv9_insert_ingress_vrfid_name_record( - cnat_nfv9_logging_info_t *nfv9_logging_info, u16 index) -{ - nfv9_ingress_vrfid_name_record_t nfv9_ingress_vrfid_name_record = {0}; - - if (PREDICT_FALSE( - nfv9_logging_info->record[INGRESS_VRF_ID_NAME_RECORD] == NULL)) { - cnat_nfv9_record_create(nfv9_logging_info, INGRESS_VRF_ID_NAME_RECORD); - } - nfv9_ingress_vrfid_name_record.ingress_vrf_id = - clib_host_to_net_u32(vrfid_name_map[index].vrf_id); - - clib_memcpy(nfv9_ingress_vrfid_name_record.ingress_vrf_name, - vrfid_name_map[index].vrf_name, NFV9_VRF_NAME_LEN); - - clib_memcpy(nfv9_logging_info->record[INGRESS_VRF_ID_NAME_RECORD], - &nfv9_ingress_vrfid_name_record, - CNAT_NFV9_INGRESS_VRFID_NAME_RECORD_LENGTH); - - nfv9_logging_info->record_length[INGRESS_VRF_ID_NAME_RECORD] - += CNAT_NFV9_INGRESS_VRFID_NAME_RECORD_LENGTH; - - nfv9_logging_info->pkt_length += - CNAT_NFV9_INGRESS_VRFID_NAME_RECORD_LENGTH; - - nfv9_logging_info->total_record_count += 1; - - nfv9_logging_info->record[INGRESS_VRF_ID_NAME_RECORD] - += CNAT_NFV9_INGRESS_VRFID_NAME_RECORD_LENGTH; - - nfv9_logging_info->next_data_ptr = - nfv9_logging_info->record[INGRESS_VRF_ID_NAME_RECORD]; - - nfv9_logging_info->dataflow_header->dataflow_length = - clib_host_to_net_u32( - nfv9_logging_info->record_length[INGRESS_VRF_ID_NAME_RECORD]); - return; -} -/* - * edt: * * cnat_log_timer_handler - * - * Timer handler for sending any pending NFV9 record - * - * Argument: spp_timer_t * timer_p - * Timer handler structure - */ -void handle_pending_nfv9_pkts() -{ - vlib_node_t *output_node; - vlib_main_t * vm = vlib_get_main(); - cnat_nfv9_logging_info_t *my_nfv9_logging_info = 0; - u32 current_timestamp = cnat_nfv9_get_sys_up_time_in_ms(); - u32 current_unix_time_in_seconds = cnat_nfv9_get_unix_time_in_seconds(); - - output_node = vlib_get_node_by_name (vm, (u8 *) "ip4-lookup"); - - pool_foreach (my_nfv9_logging_info, cnat_nfv9_logging_info_pool, ({ - nfv9_server_info_t *server = nfv9_server_info_pool + - my_nfv9_logging_info->server_index; - if (my_nfv9_logging_info->queued_logging_context || - (my_nfv9_logging_info->current_logging_context && - (current_timestamp - - my_nfv9_logging_info->current_logging_context_timestamp) - > 1000)) { - /* - * If there is a current logging context and timestamp - * indicates it is pending for long, send it out - * Also if there is a queued context send it out as well - */ - vlib_cli_output(vm, "\nNFV9_TIMER: queued %p, curr %p", - my_nfv9_logging_info->queued_logging_context, - my_nfv9_logging_info->current_logging_context); - - - cnat_nfv9_send_pkt_always_success(my_nfv9_logging_info, - output_node); - } else { - /* - * If the last_template_sent_time is too far back in time - * send the template even if there is no NFv9 records to send - */ - if ((my_nfv9_logging_info->queued_logging_context == NULL) && - (my_nfv9_logging_info->current_logging_context == NULL) && - ((current_unix_time_in_seconds - - server->last_template_sent_time) > - server->timeout_rate)) { - cnat_nfv9_create_logging_context(my_nfv9_logging_info, - cnat_nfv9_template_add_always); - if (PREDICT_TRUE(my_nfv9_logging_info->current_logging_context - != NULL)) { - cnat_nfv9_send_pkt(my_nfv9_logging_info); - } - } - } - })); -} - -/* - * Code to initialize NFV9 Template. This is done when a NFV9 is enabled - * It is done only once and later used when sending NFV9 template records. - */ -static void -cnat_nfv9_template_init (void) -{ - cnat_nfv9_template_info.flowset_id = - clib_host_to_net_u16(CNAT_NFV9_TEMPLATE_FLOWSET_ID); - cnat_nfv9_template_info.length = - clib_host_to_net_u16(CNAT_NFV9_TEMPLATE_LENGTH - - CNAT_NFV9_OPTION_TEMPLATE_LENGTH); - /* - * Create the add Template - */ - cnat_nfv9_template_info.add_template_id = - clib_host_to_net_u16(CNAT_NFV9_ADD_TEMPLATE_ID); - cnat_nfv9_template_info.add_field_count = - clib_host_to_net_u16(CNAT_NFV9_ADD_FIELD_COUNT); - - cnat_nfv9_template_info.add_inside_vrf_id_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_TYPE); - cnat_nfv9_template_info.add_inside_vrf_id_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_SIZE); - - cnat_nfv9_template_info.add_outside_vrf_id_field_type = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_VRFID_FIELD_TYPE); - cnat_nfv9_template_info.add_outside_vrf_id_field_size = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_VRFID_FIELD_SIZE); - - cnat_nfv9_template_info.add_inside_ip_addr_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_TYPE); - cnat_nfv9_template_info.add_inside_ip_addr_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_SIZE); - - cnat_nfv9_template_info.add_outside_ip_addr_field_type = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_ADDR_FIELD_TYPE); - cnat_nfv9_template_info.add_outside_ip_addr_field_size = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_ADDR_FIELD_SIZE); - - cnat_nfv9_template_info.add_inside_ip_port_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_TYPE); - cnat_nfv9_template_info.add_inside_ip_port_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_SIZE); - - cnat_nfv9_template_info.add_outside_ip_port_field_type = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_FIELD_TYPE); - cnat_nfv9_template_info.add_outside_ip_port_field_size = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_FIELD_SIZE); - - cnat_nfv9_template_info.add_protocol_field_type = - clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_TYPE); - cnat_nfv9_template_info.add_protocol_field_size = - clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_SIZE); - - /* - * Create the delete Template - */ - cnat_nfv9_template_info.del_template_id = - clib_host_to_net_u16(CNAT_NFV9_DEL_TEMPLATE_ID); - cnat_nfv9_template_info.del_field_count = - clib_host_to_net_u16(CNAT_NFV9_DEL_FIELD_COUNT); - - cnat_nfv9_template_info.del_inside_vrf_id_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_TYPE); - cnat_nfv9_template_info.del_inside_vrf_id_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_SIZE); - - cnat_nfv9_template_info.del_inside_ip_addr_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_TYPE); - cnat_nfv9_template_info.del_inside_ip_addr_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_SIZE); - - cnat_nfv9_template_info.del_inside_ip_port_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_TYPE); - cnat_nfv9_template_info.del_inside_ip_port_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_SIZE); - - cnat_nfv9_template_info.del_protocol_field_type = - clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_TYPE); - cnat_nfv9_template_info.del_protocol_field_size = - clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_SIZE); - - - /* Create NAT64 BIB Add template */ -#if 0 - cnat_nfv9_template_info.nat64_add_bib_template_id = - clib_host_to_net_u16(CNAT_NFV9_NAT64_ADD_BIB_TEMPLATE_ID); - cnat_nfv9_template_info.nat64_add_bib_field_count = - clib_host_to_net_u16(CNAT_NFV9_NAT64_ADD_BIB_FIELD_COUNT); - - - cnat_nfv9_template_info.nat64_add_bib_inside_ipv6_addr_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_TYPE); - cnat_nfv9_template_info.nat64_add_bib_inside_ipv6_addr_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_SIZE); - - cnat_nfv9_template_info.nat64_add_bib_outside_ip_addr_field_type = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_ADDR_FIELD_TYPE); - cnat_nfv9_template_info.nat64_add_bib_outside_ip_addr_field_size = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_ADDR_FIELD_SIZE); - - cnat_nfv9_template_info.nat64_add_bib_inside_ip_port_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_TYPE); - cnat_nfv9_template_info.nat64_add_bib_inside_ip_port_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_SIZE); - - cnat_nfv9_template_info.nat64_add_bib_outside_ip_port_field_type = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_FIELD_TYPE); - cnat_nfv9_template_info.nat64_add_bib_outside_ip_port_field_size = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_FIELD_SIZE); - - cnat_nfv9_template_info.nat64_add_bib_protocol_field_type = - clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_TYPE); - cnat_nfv9_template_info.nat64_add_bib_protocol_field_size = - clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_SIZE); - - - /* NAT64 BIB Delete */ - cnat_nfv9_template_info.nat64_del_bib_template_id = - clib_host_to_net_u16(CNAT_NFV9_NAT64_DEL_BIB_TEMPLATE_ID); - cnat_nfv9_template_info.nat64_del_bib_field_count = - clib_host_to_net_u16(CNAT_NFV9_NAT64_DEL_BIB_FIELD_COUNT); - - cnat_nfv9_template_info.nat64_del_bib_inside_ip_addr_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_TYPE); - cnat_nfv9_template_info.nat64_del_bib_inside_ip_addr_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_SIZE); - - cnat_nfv9_template_info.nat64_del_bib_inside_ip_port_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_TYPE); - cnat_nfv9_template_info.nat64_del_bib_inside_ip_port_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_SIZE); - - cnat_nfv9_template_info.nat64_del_bib_protocol_field_type = - clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_TYPE); - cnat_nfv9_template_info.nat64_del_bib_protocol_field_size = - clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_SIZE); - - - /* NAt64 SESSION ADD */ - - cnat_nfv9_template_info.nat64_add_session_template_id = - clib_host_to_net_u16(CNAT_NFV9_NAT64_ADD_SESSION_TEMPLATE_ID); - cnat_nfv9_template_info.nat64_add_session_field_count = - clib_host_to_net_u16(CNAT_NFV9_NAT64_ADD_SESSION_FIELD_COUNT); - - - cnat_nfv9_template_info.nat64_add_session_inside_ipv6_src_addr_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_TYPE); - cnat_nfv9_template_info.nat64_add_session_inside_ipv6_src_addr_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_SIZE); - - cnat_nfv9_template_info.nat64_add_session_outside_ip_src_addr_field_type = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_ADDR_FIELD_TYPE); - cnat_nfv9_template_info.nat64_add_session_outside_ip_src_addr_field_size = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_ADDR_FIELD_SIZE); - - - cnat_nfv9_template_info.nat64_add_session_inside_ipv6_dst_addr_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_DST_ADDR_FIELD_TYPE); - cnat_nfv9_template_info.nat64_add_session_inside_ipv6_dst_addr_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_DST_ADDR_FIELD_SIZE); - - - cnat_nfv9_template_info.nat64_add_session_outside_ip_dst_addr_field_type = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_DST_ADDR_FIELD_TYPE); - cnat_nfv9_template_info.nat64_add_session_outside_ip_dst_addr_field_size = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_DST_ADDR_FIELD_SIZE); - - cnat_nfv9_template_info.nat64_add_session_inside_ip_src_port_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_TYPE); - cnat_nfv9_template_info.nat64_add_session_inside_ip_src_port_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_SIZE); - - - cnat_nfv9_template_info.nat64_add_session_outside_ip_src_port_field_type = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_FIELD_TYPE); - cnat_nfv9_template_info.nat64_add_session_outside_ip_src_port_field_size = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_FIELD_SIZE); - - - cnat_nfv9_template_info.nat64_add_session_ip_dest_port_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_DST_PORT_FIELD_TYPE); - cnat_nfv9_template_info.nat64_add_session_ip_dest_port_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_DST_PORT_FIELD_SIZE); - - cnat_nfv9_template_info.nat64_add_session_protocol_field_type = - clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_TYPE); - cnat_nfv9_template_info.nat64_add_session_protocol_field_size = - clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_SIZE); - - - - /* Session Delete */ - cnat_nfv9_template_info.nat64_del_session_template_id = - clib_host_to_net_u16(CNAT_NFV9_NAT64_DEL_SESSION_TEMPLATE_ID); - cnat_nfv9_template_info.nat64_del_session_field_count = - clib_host_to_net_u16(CNAT_NFV9_NAT64_DEL_SESSION_FIELD_COUNT); - - cnat_nfv9_template_info.nat64_del_session_inside_ip_src_addr_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_TYPE); - cnat_nfv9_template_info.nat64_del_session_inside_ip_src_addr_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_SIZE); - - cnat_nfv9_template_info.nat64_del_session_inside_ip_dst_addr_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_DST_ADDR_FIELD_TYPE); - cnat_nfv9_template_info.nat64_del_session_inside_ip_dst_addr_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_DST_ADDR_FIELD_SIZE); - - cnat_nfv9_template_info.nat64_del_session_inside_ip_src_port_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_TYPE); - cnat_nfv9_template_info.nat64_del_session_inside_ip_src_port_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_SIZE); - - cnat_nfv9_template_info.nat64_del_session_inside_ip_dst_port_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_DST_PORT_FIELD_TYPE); - cnat_nfv9_template_info.nat64_del_session_inside_ip_dst_port_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_DST_PORT_FIELD_SIZE); - - cnat_nfv9_template_info.nat64_del_session_protocol_field_type = - clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_TYPE); - cnat_nfv9_template_info.nat64_del_session_protocol_field_size = - clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_SIZE); -#endif - /* - * Create the nat44 session add Template - */ - cnat_nfv9_template_info.nat44_session_add_template_id = - clib_host_to_net_u16(CNAT_NFV9_NAT44_ADD_SESSION_TEMPLATE_ID); - cnat_nfv9_template_info.nat44_session_add_field_count = - clib_host_to_net_u16(CNAT_NFV9_NAT44_ADD_SESSION_FIELD_COUNT); - - cnat_nfv9_template_info.nat44_session_add_inside_vrf_id_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_TYPE); - cnat_nfv9_template_info.nat44_session_add_inside_vrf_id_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_SIZE); - - cnat_nfv9_template_info.nat44_session_add_outside_vrf_id_field_type = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_VRFID_FIELD_TYPE); - cnat_nfv9_template_info.nat44_session_add_outside_vrf_id_field_size = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_VRFID_FIELD_SIZE); - - cnat_nfv9_template_info.nat44_session_add_inside_ip_addr_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_TYPE); - cnat_nfv9_template_info.nat44_session_add_inside_ip_addr_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_SIZE); - - cnat_nfv9_template_info.nat44_session_add_outside_ip_addr_field_type = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_ADDR_FIELD_TYPE); - cnat_nfv9_template_info.nat44_session_add_outside_ip_addr_field_size = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_ADDR_FIELD_SIZE); - - cnat_nfv9_template_info.nat44_session_add_inside_ip_port_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_TYPE); - cnat_nfv9_template_info.nat44_session_add_inside_ip_port_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_SIZE); - - cnat_nfv9_template_info.nat44_session_add_outside_ip_port_field_type = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_FIELD_TYPE); - cnat_nfv9_template_info.nat44_session_add_outside_ip_port_field_size = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_FIELD_SIZE); - - cnat_nfv9_template_info.nat44_session_add_dest_ip_addr_field_type = - clib_host_to_net_u16(CNAT_NFV9_DESTINATION_IP_ADDR_FIELD_TYPE); - cnat_nfv9_template_info.nat44_session_add_dest_ip_addr_field_size = - clib_host_to_net_u16(CNAT_NFV9_DESTINATION_IP_ADDR_FIELD_SIZE); - - cnat_nfv9_template_info.nat44_session_add_dest_port_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_DST_PORT_FIELD_TYPE); - cnat_nfv9_template_info.nat44_session_add_dest_port_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_DST_PORT_FIELD_SIZE); - - cnat_nfv9_template_info.nat44_session_add_protocol_field_type = - clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_TYPE); - cnat_nfv9_template_info.nat44_session_add_protocol_field_size = - clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_SIZE); - - /* - * Create the nat44 session del Template - */ - cnat_nfv9_template_info.nat44_session_del_template_id = - clib_host_to_net_u16(CNAT_NFV9_NAT44_DEL_SESSION_TEMPLATE_ID); - cnat_nfv9_template_info.nat44_session_del_field_count = - clib_host_to_net_u16(CNAT_NFV9_NAT44_DEL_SESSION_FIELD_COUNT); - - cnat_nfv9_template_info.nat44_session_del_inside_vrf_id_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_TYPE); - cnat_nfv9_template_info.nat44_session_del_inside_vrf_id_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_SIZE); - - cnat_nfv9_template_info.nat44_session_del_inside_ip_addr_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_TYPE); - cnat_nfv9_template_info.nat44_session_del_inside_ip_addr_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_SIZE); - - cnat_nfv9_template_info.nat44_session_del_dest_ip_addr_field_type = - clib_host_to_net_u16(CNAT_NFV9_DESTINATION_IP_ADDR_FIELD_TYPE); - cnat_nfv9_template_info.nat44_session_del_dest_ip_addr_field_size = - clib_host_to_net_u16(CNAT_NFV9_DESTINATION_IP_ADDR_FIELD_SIZE); - - cnat_nfv9_template_info.nat44_session_del_inside_ip_port_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_TYPE); - cnat_nfv9_template_info.nat44_session_del_inside_ip_port_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_SIZE); - - cnat_nfv9_template_info.nat44_session_del_dest_port_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_DST_PORT_FIELD_TYPE); - cnat_nfv9_template_info.nat44_session_del_dest_port_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_DST_PORT_FIELD_SIZE); - - cnat_nfv9_template_info.nat44_session_del_protocol_field_type = - clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_TYPE); - cnat_nfv9_template_info.nat44_session_del_protocol_field_size = - clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_SIZE); - /* - * Ds-lite add template - */ -#if 0 - cnat_nfv9_template_info.add_dslite_template_id = - clib_host_to_net_u16(CNAT_NFV9_DS_LITE_ADD_TEMPLATE_ID); - cnat_nfv9_template_info.add_dslite_field_count = - clib_host_to_net_u16(CNAT_NFV9_DS_LITE_ADD_FIELD_COUNT); - - cnat_nfv9_template_info.add_dslite_inside_vrf_id_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_TYPE); - cnat_nfv9_template_info.add_dslite_inside_vrf_id_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_SIZE); - - cnat_nfv9_template_info.add_dslite_outside_vrf_id_field_type = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_VRFID_FIELD_TYPE); - cnat_nfv9_template_info.add_dslite_outside_vrf_id_field_size = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_VRFID_FIELD_SIZE); - - cnat_nfv9_template_info.add_dslite_inside_ip_addr_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_TYPE); - cnat_nfv9_template_info.add_dslite_inside_ip_addr_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_SIZE); - - cnat_nfv9_template_info.add_dslite_inside_ipv6_addr_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_TYPE); - cnat_nfv9_template_info.add_dslite_inside_ipv6_addr_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_SIZE); - - cnat_nfv9_template_info.add_dslite_outside_ip_addr_field_type = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_ADDR_FIELD_TYPE); - cnat_nfv9_template_info.add_dslite_outside_ip_addr_field_size = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_ADDR_FIELD_SIZE); - - cnat_nfv9_template_info.add_dslite_inside_ip_port_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_TYPE); - cnat_nfv9_template_info.add_dslite_inside_ip_port_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_SIZE); - - cnat_nfv9_template_info.add_dslite_outside_ip_port_field_type = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_FIELD_TYPE); - cnat_nfv9_template_info.add_dslite_outside_ip_port_field_size = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_FIELD_SIZE); - - cnat_nfv9_template_info.add_dslite_protocol_field_type = - clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_TYPE); - cnat_nfv9_template_info.add_dslite_protocol_field_size = - clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_SIZE); - - /* - * Ds-lite delete template - */ - cnat_nfv9_template_info.del_dslite_template_id = - clib_host_to_net_u16(CNAT_NFV9_DS_LITE_DEL_TEMPLATE_ID); - cnat_nfv9_template_info.del_dslite_field_count = - clib_host_to_net_u16(CNAT_NFV9_DS_LITE_DEL_FIELD_COUNT); - - cnat_nfv9_template_info.del_dslite_inside_vrf_id_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_TYPE); - cnat_nfv9_template_info.del_dslite_inside_vrf_id_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_SIZE); - - cnat_nfv9_template_info.del_dslite_inside_ip_addr_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_TYPE); - cnat_nfv9_template_info.del_dslite_inside_ip_addr_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_SIZE); - - cnat_nfv9_template_info.del_dslite_inside_ipv6_addr_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_TYPE); - cnat_nfv9_template_info.del_dslite_inside_ipv6_addr_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_SIZE); - - cnat_nfv9_template_info.del_dslite_inside_ip_port_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_TYPE); - cnat_nfv9_template_info.del_dslite_inside_ip_port_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_SIZE); - - cnat_nfv9_template_info.del_dslite_protocol_field_type = - clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_TYPE); - cnat_nfv9_template_info.del_dslite_protocol_field_size = - clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_SIZE); - - /* - * Ds-lite session add template - */ - - cnat_nfv9_template_info.add_dslite_session_template_id = - clib_host_to_net_u16(CNAT_NFV9_DS_LITE_ADD_SESSION_TEMPLATE_ID); - cnat_nfv9_template_info.add_dslite_session_field_count = - clib_host_to_net_u16(CNAT_NFV9_DS_LITE_ADD_SESSION_FIELD_COUNT); - - cnat_nfv9_template_info.add_dslite_session_inside_vrf_id_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_TYPE); - cnat_nfv9_template_info.add_dslite_session_inside_vrf_id_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_SIZE); - - cnat_nfv9_template_info.add_dslite_session_outside_vrf_id_field_type = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_VRFID_FIELD_TYPE); - cnat_nfv9_template_info.add_dslite_session_outside_vrf_id_field_size = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_VRFID_FIELD_SIZE); - - cnat_nfv9_template_info.add_dslite_session_inside_ip_addr_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_TYPE); - cnat_nfv9_template_info.add_dslite_session_inside_ip_addr_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_SIZE); - - cnat_nfv9_template_info.add_dslite_session_inside_ipv6_addr_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_TYPE); - cnat_nfv9_template_info.add_dslite_session_inside_ipv6_addr_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_SIZE); - - cnat_nfv9_template_info.add_dslite_session_outside_ip_addr_field_type = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_ADDR_FIELD_TYPE); - cnat_nfv9_template_info.add_dslite_session_outside_ip_addr_field_size = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_ADDR_FIELD_SIZE); - - cnat_nfv9_template_info.add_dslite_session_inside_ip_port_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_TYPE); - cnat_nfv9_template_info.add_dslite_session_inside_ip_port_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_SIZE); - - cnat_nfv9_template_info.add_dslite_session_outside_ip_port_field_type = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_FIELD_TYPE); - cnat_nfv9_template_info.add_dslite_session_outside_ip_port_field_size = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_FIELD_SIZE); - - cnat_nfv9_template_info.add_dslite_session_dest_ip_addr_field_type = - clib_host_to_net_u16(CNAT_NFV9_DESTINATION_IP_ADDR_FIELD_TYPE); - cnat_nfv9_template_info.add_dslite_session_dest_ip_addr_field_size = - clib_host_to_net_u16(CNAT_NFV9_DESTINATION_IP_ADDR_FIELD_SIZE); - - cnat_nfv9_template_info.add_dslite_session_dest_port_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_DST_PORT_FIELD_TYPE); - cnat_nfv9_template_info.add_dslite_session_dest_port_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_DST_PORT_FIELD_SIZE); - - cnat_nfv9_template_info.add_dslite_session_protocol_field_type = - clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_TYPE); - cnat_nfv9_template_info.add_dslite_session_protocol_field_size = - clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_SIZE); - - /* - * Ds-lite session delete template - */ - cnat_nfv9_template_info.del_dslite_session_template_id = - clib_host_to_net_u16(CNAT_NFV9_DS_LITE_DEL_SESSION_TEMPLATE_ID); - cnat_nfv9_template_info.del_dslite_session_field_count = - clib_host_to_net_u16(CNAT_NFV9_DS_LITE_DEL_SESSION_FIELD_COUNT); - - cnat_nfv9_template_info.del_dslite_session_inside_vrf_id_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_TYPE); - cnat_nfv9_template_info.del_dslite_session_inside_vrf_id_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_SIZE); - - cnat_nfv9_template_info.del_dslite_session_inside_ip_addr_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_TYPE); - cnat_nfv9_template_info.del_dslite_session_inside_ip_addr_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_SIZE); - - cnat_nfv9_template_info.del_dslite_session_inside_ipv6_addr_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_TYPE); - cnat_nfv9_template_info.del_dslite_session_inside_ipv6_addr_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_SIZE); - - cnat_nfv9_template_info.del_dslite_session_inside_ip_port_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_TYPE); - cnat_nfv9_template_info.del_dslite_session_inside_ip_port_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_SIZE); - - cnat_nfv9_template_info.del_dslite_session_dest_ip_addr_field_type = - clib_host_to_net_u16(CNAT_NFV9_DESTINATION_IP_ADDR_FIELD_TYPE); - cnat_nfv9_template_info.del_dslite_session_dest_ip_addr_field_size = - clib_host_to_net_u16(CNAT_NFV9_DESTINATION_IP_ADDR_FIELD_SIZE); - - cnat_nfv9_template_info.del_dslite_session_dest_port_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_DST_PORT_FIELD_TYPE); - cnat_nfv9_template_info.del_dslite_session_dest_port_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_DST_PORT_FIELD_SIZE); - - cnat_nfv9_template_info.del_dslite_session_protocol_field_type = - clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_TYPE); - cnat_nfv9_template_info.del_dslite_session_protocol_field_size = - clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_SIZE); - - /* Create add bulk template */ - cnat_nfv9_template_info.bulk_add_template_id = - clib_host_to_net_u16(CNAT_NFV9_NAT44_BULK_ADD_TEMPLATE_ID); - cnat_nfv9_template_info.bulk_add_field_count = - clib_host_to_net_u16(CNAT_NFV9_NAT44_BULK_ADD_FIELD_COUNT); - - cnat_nfv9_template_info.bulk_add_inside_vrf_id_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_TYPE); - cnat_nfv9_template_info.bulk_add_inside_vrf_id_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_SIZE); - - cnat_nfv9_template_info.bulk_add_outside_vrf_id_field_type = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_VRFID_FIELD_TYPE); - cnat_nfv9_template_info.bulk_add_outside_vrf_id_field_size = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_VRFID_FIELD_SIZE); - - cnat_nfv9_template_info.bulk_add_inside_ip_addr_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_TYPE); - cnat_nfv9_template_info.bulk_add_inside_ip_addr_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_SIZE); - - cnat_nfv9_template_info.bulk_add_outside_ip_addr_field_type = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_ADDR_FIELD_TYPE); - cnat_nfv9_template_info.bulk_add_outside_ip_addr_field_size = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_ADDR_FIELD_SIZE); - - cnat_nfv9_template_info.bulk_add_outside_start_port_field_type = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_START_FIELD_TYPE); - cnat_nfv9_template_info.bulk_add_outside_start_port_field_size = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_START_FIELD_SIZE); - - cnat_nfv9_template_info.bulk_add_outside_end_port_field_type = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_END_FIELD_TYPE); - cnat_nfv9_template_info.bulk_add_outside_end_port_field_size = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_END_FIELD_SIZE); - - /* - * Create the bulk delete Template - */ - cnat_nfv9_template_info.bulk_del_template_id = - clib_host_to_net_u16(CNAT_NFV9_NAT44_BULK_DEL_TEMPLATE_ID); - cnat_nfv9_template_info.bulk_del_field_count = - clib_host_to_net_u16(CNAT_NFV9_NAT44_BULK_DEL_FIELD_COUNT); - - cnat_nfv9_template_info.bulk_del_inside_vrf_id_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_TYPE); - cnat_nfv9_template_info.bulk_del_inside_vrf_id_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_SIZE); - - cnat_nfv9_template_info.bulk_del_inside_ip_addr_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_TYPE); - cnat_nfv9_template_info.bulk_del_inside_ip_addr_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_SIZE); - - cnat_nfv9_template_info.bulk_del_outside_start_port_field_type = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_START_FIELD_TYPE); - cnat_nfv9_template_info.bulk_del_outside_start_port_field_size = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_START_FIELD_SIZE); - - /* - * Ds-lite bulk add template - */ - cnat_nfv9_template_info.bulk_dslite_add_template_id = - clib_host_to_net_u16(CNAT_NFV9_DS_LITE_BULK_ADD_TEMPLATE_ID); - cnat_nfv9_template_info.bulk_dslite_add_field_count = - clib_host_to_net_u16(CNAT_NFV9_DS_LITE_BULK_ADD_FIELD_COUNT); - - cnat_nfv9_template_info.bulk_dslite_add_inside_vrf_id_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_TYPE); - cnat_nfv9_template_info.bulk_dslite_add_inside_vrf_id_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_SIZE); - - cnat_nfv9_template_info.bulk_dslite_add_outside_vrf_id_field_type = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_VRFID_FIELD_TYPE); - cnat_nfv9_template_info.bulk_dslite_add_outside_vrf_id_field_size = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_VRFID_FIELD_SIZE); - - cnat_nfv9_template_info.bulk_dslite_add_inside_ip_addr_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_TYPE); - cnat_nfv9_template_info.bulk_dslite_add_inside_ip_addr_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_SIZE); - - cnat_nfv9_template_info.bulk_dslite_add_inside_ipv6_addr_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_TYPE); - cnat_nfv9_template_info.bulk_dslite_add_inside_ipv6_addr_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_SIZE); - - cnat_nfv9_template_info.bulk_dslite_add_outside_ip_addr_field_type = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_ADDR_FIELD_TYPE); - cnat_nfv9_template_info.bulk_dslite_add_outside_ip_addr_field_size = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_ADDR_FIELD_SIZE); - - cnat_nfv9_template_info.bulk_dslite_add_outside_start_port_field_type = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_START_FIELD_TYPE); - cnat_nfv9_template_info.bulk_dslite_add_outside_start_port_field_size = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_START_FIELD_SIZE); - - cnat_nfv9_template_info.bulk_dslite_add_outside_end_port_field_type = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_END_FIELD_TYPE); - cnat_nfv9_template_info.bulk_dslite_add_outside_end_port_field_size = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_END_FIELD_SIZE); - - /* - * Ds-lite bulk delete template - */ - - cnat_nfv9_template_info.bulk_dslite_del_template_id = - clib_host_to_net_u16(CNAT_NFV9_DS_LITE_BULK_DEL_TEMPLATE_ID); - cnat_nfv9_template_info.bulk_dslite_del_field_count = - clib_host_to_net_u16(CNAT_NFV9_DS_LITE_BULK_DEL_FIELD_COUNT); - - cnat_nfv9_template_info.bulk_dslite_del_inside_vrf_id_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_TYPE); - cnat_nfv9_template_info.bulk_dslite_del_inside_vrf_id_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_SIZE); - - cnat_nfv9_template_info.bulk_dslite_del_inside_ip_addr_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_TYPE); - cnat_nfv9_template_info.bulk_dslite_del_inside_ip_addr_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_SIZE); - - cnat_nfv9_template_info.bulk_dslite_del_inside_ipv6_addr_field_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_TYPE); - cnat_nfv9_template_info.bulk_dslite_del_inside_ipv6_addr_field_size = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_SIZE); - - cnat_nfv9_template_info.bulk_dslite_del_outside_start_port_field_type = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_START_FIELD_TYPE); - cnat_nfv9_template_info.bulk_dslite_del_outside_start_port_field_size = - clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_START_FIELD_SIZE); - -#endif /* NO_BULK_LOGGING */ - - /* - * Ingress vrfid - name mapping - */ - CNAT_NFV9_OPTION_TEMPLATE.flowset_id = - clib_host_to_net_u16(CNAT_NFV9_OPTION_TEMPLATE_FLOWSET_ID); - CNAT_NFV9_OPTION_TEMPLATE.length = - clib_host_to_net_u16(CNAT_NFV9_OPTION_TEMPLATE_LENGTH); - - CNAT_NFV9_OPTION_TEMPLATE.ingress_vrfid_name_map_template_id = - clib_host_to_net_u16(CNAT_NFV9_INGRESS_VRF_ID_NAME_TEMPLATE_ID); - /* currently no scope field supported */ - CNAT_NFV9_OPTION_TEMPLATE.ingress_vrfid_name_map_scope_len = 0; - CNAT_NFV9_OPTION_TEMPLATE.ingress_vrfid_name_map_option_len = - clib_host_to_net_u16(CNAT_NFV9_INGRESS_VRF_ID_NAME_OPTION_LEN); - CNAT_NFV9_OPTION_TEMPLATE.ingress_vrfid_name_map_vrfid_option_type = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_TYPE); - CNAT_NFV9_OPTION_TEMPLATE.ingress_vrfid_name_map_vrfid_option_len = - clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_SIZE); - CNAT_NFV9_OPTION_TEMPLATE.ingress_vrfid_name_map_vrfname_option_type = - clib_host_to_net_u16(CNAT_NFV9_INGRESS_VRF_NAME_FIELD_TYPE); - CNAT_NFV9_OPTION_TEMPLATE.ingress_vrfid_name_map_vrfname_option_len = - clib_host_to_net_u16(CNAT_NFV9_INGRESS_VRF_NAME_FIELD_SIZE); - - /* - * Set the padding (which was added to make the size of template - * multiple of 4) to zero - */ - CNAT_NFV9_OPTION_TEMPLATE.padding1 = 0; -} - -/* - * one time function - * has to be called at the init time - */ -void cnat_nfv9_logging_init() -{ - if (!cnat_nfv9_global_info.cnat_nfv9_init_done) { - cnat_nfv9_template_init(); - - /* Pre allocate for NFV9_SERVER_POOL_SIZE. Will be good - * enough for most deployments - */ - pool_alloc(nfv9_server_info_pool, NFV9_SERVER_POOL_SIZE); - int i; - nfv9_server_info_t *server __attribute__((unused)); - for(i = 0; i < NFV9_SERVER_POOL_SIZE; i++) { - pool_get(nfv9_server_info_pool, server); - } - - for(i = 0; i < NFV9_SERVER_POOL_SIZE; i++) { - pool_put(nfv9_server_info_pool, nfv9_server_info_pool + i); - } - - memset(&cnat_nfv9_global_info, 0 , sizeof(cnat_nfv9_global_info_t)); - ASSERT(cnat_nfv9_global_info.cnat_nfv9_disp_node_index != (u16)~0); - - cnat_nfv9_global_info.cnat_nfv9_global_collector_index = EMPTY; - cnat_nfv9_global_info.cnat_nfv9_init_done = 1; - - /* - * src id is set to infra IPv4 address + octeon core number - */ - nfv9_src_id = my_instance_number; - } -} diff --git a/plugins/plugins/vcgn/cnat_logging.h b/plugins/plugins/vcgn/cnat_logging.h deleted file mode 100644 index 7bd43ecf..00000000 --- a/plugins/plugins/vcgn/cnat_logging.h +++ /dev/null @@ -1,1091 +0,0 @@ -/* - *------------------------------------------------------------------ - * cnat_logging.h - * - * Copyright (c) 2009, 2012 Cisco and/or its affiliates. - * 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 __CNAT_LOGGING_H__ -#define __CNAT_LOGGING_H__ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "nat64_db.h" -#include "cnat_log_common.h" -#include "dslite_defs.h" - -#define NFV9_DEF_PATH_MTU 1500 -#define NFV9_VRF_NAME_LEN 12 - -/* one time call at the beginning */ -void cnat_nfv9_logging_init(); - -/* - * unconditional call - * will check logging config inside - */ -void cnat_nfv9_log_mapping_create(cnat_main_db_entry_t * db, - cnat_vrfmap_t *vrfmap -#ifndef NO_BULK_LOGGING - , int bulk_alloc -#endif - ); - -void cnat_nfv9_nat44_log_session_create(cnat_main_db_entry_t * db, - cnat_session_entry_t * sdb, - cnat_vrfmap_t *vrfmap); - -void cnat_nfv9_nat44_log_session_delete(cnat_main_db_entry_t * db, - cnat_session_entry_t * sdb, - cnat_vrfmap_t *vrfmap); - - -/* - * unconditional call - * will check logging config inside - */ -void cnat_nfv9_log_mapping_delete(cnat_main_db_entry_t * db, - cnat_vrfmap_t *vrfmap -#ifndef NO_BULK_LOGGING - , int bulk_alloc -#endif - ); - -/* nat44 syslog APIs */ -void cnat_syslog_nat44_mapping_create(cnat_main_db_entry_t *db, - cnat_vrfmap_t *vrfmap, cnat_session_entry_t * sdb -#ifndef NO_BULK_LOGGING - , int bulk_alloc -#endif - ); - -void cnat_syslog_nat44_mapping_delete(cnat_main_db_entry_t *db, - cnat_vrfmap_t *vrfmap, cnat_session_entry_t *sdb -#ifndef NO_BULK_LOGGING - , int bulk_alloc -#endif - ); - -/* - * dslite - */ -void cnat_nfv9_ds_lite_mapping_create(cnat_main_db_entry_t *db, - dslite_table_entry_t *dslite_entry -#ifndef NO_BULK_LOGGING - , int bulk_alloc -#endif - ); - -void cnat_nfv9_ds_lite_mapping_delete(cnat_main_db_entry_t *db, - dslite_table_entry_t *dslite_entry -#ifndef NO_BULK_LOGGING - , int bulk_alloc -#endif - ); -void cnat_nfv9_ds_lite_log_session_create(cnat_main_db_entry_t * db, - dslite_table_entry_t *dslite_entry, - cnat_session_entry_t * sdb); - -void cnat_nfv9_ds_lite_log_session_delete(cnat_main_db_entry_t * db, - dslite_table_entry_t *dslite_entry, - cnat_session_entry_t * sdb); - -/* - * nat64 - */ - -void cnat_nfv9_bib_mapping_create (nat64_bib_entry_t *db, - nat64_table_entry_t *nat64_entry); - -void cnat_nfv9_session_mapping_create (nat64_bib_entry_t *bdb, - nat64_session_entry_t *sdb, - nat64_table_entry_t *nat64_entry_ptr); - -void cnat_nfv9_bib_mapping_delete (nat64_bib_entry_t *db, - nat64_table_entry_t *nat64_entry); - -void cnat_nfv9_session_mapping_delete (nat64_bib_entry_t *bdb, - nat64_session_entry_t *sdb, - nat64_table_entry_t *nat64_entry_ptr); - -typedef enum { - RECORD_INVALID = 0, - NAT44_ADD_RECORD, - NAT44_DEL_RECORD, - NAT64_ADD_BIB_RECORD, - NAT64_DEL_BIB_RECORD, - NAT64_ADD_SESSION_RECORD, - NAT64_DEL_SESSION_RECORD, - DS_LITE_ADD_RECORD, - DS_LITE_DEL_RECORD, - NAT44_BULK_ADD_RECORD, - NAT44_BULK_DEL_RECORD, - DS_LITE_BULK_ADD_RECORD, - DS_LITE_BULK_DEL_RECORD, - INGRESS_VRF_ID_NAME_RECORD, - NAT44_ADD_SESSION_RECORD, - NAT44_DEL_SESSION_RECORD, - DS_LITE_ADD_SESSION_RECORD, - DS_LITE_DEL_SESSION_RECORD, - MAX_RECORDS -} netflow_record; - -typedef enum { - TEMPLATE_SENT_FALSE = 0, - TEMPLATE_SENT_TRUE = 1 -} netflow_template_sent; - -#define cnat_nfv9_get_sys_up_time_in_ms cnat_get_sys_up_time_in_ms - -#define cnat_nfv9_get_unix_time_in_seconds cnat_get_unix_time_in_seconds - -#define cnat_nfv9_dump_time_change_logs cnat_dump_time_change_logs - - -/* - * Netflow V9 Specific Defines and structures - */ - -#define CNAT_NFV9_VERSION_NUMBER 9 - -#define CNAT_NFV9_TEMPLATE_FLOWSET_ID 0 -#define CNAT_NFV9_OPTION_TEMPLATE_FLOWSET_ID 1 - -#define CNAT_NFV9_ADD_FIELD_COUNT 7 -#define CNAT_NFV9_DEL_FIELD_COUNT 4 -#define CNAT_NFV9_DS_LITE_ADD_FIELD_COUNT 8 -#define CNAT_NFV9_DS_LITE_DEL_FIELD_COUNT 5 -#define CNAT_NFV9_NAT64_ADD_BIB_FIELD_COUNT 5 -#define CNAT_NFV9_NAT64_DEL_BIB_FIELD_COUNT 3 -#define CNAT_NFV9_NAT64_ADD_SESSION_FIELD_COUNT 8 -#define CNAT_NFV9_NAT64_DEL_SESSION_FIELD_COUNT 5 -#define CNAT_NFV9_NAT44_ADD_SESSION_FIELD_COUNT 9 -#define CNAT_NFV9_NAT44_DEL_SESSION_FIELD_COUNT 6 -#define CNAT_NFV9_DS_LITE_ADD_SESSION_FIELD_COUNT 10 -#define CNAT_NFV9_DS_LITE_DEL_SESSION_FIELD_COUNT 7 - -#define CNAT_NFV9_ADD_TEMPLATE_ID 256 -#define CNAT_NFV9_DEL_TEMPLATE_ID 257 -#define CNAT_NFV9_NAT64_ADD_BIB_TEMPLATE_ID 258 -#define CNAT_NFV9_NAT64_DEL_BIB_TEMPLATE_ID 259 -#define CNAT_NFV9_NAT64_ADD_SESSION_TEMPLATE_ID 260 -#define CNAT_NFV9_NAT64_DEL_SESSION_TEMPLATE_ID 261 -#define CNAT_NFV9_INGRESS_VRF_ID_NAME_TEMPLATE_ID 262 -#define CNAT_NFV9_DS_LITE_ADD_TEMPLATE_ID 267 -#define CNAT_NFV9_DS_LITE_DEL_TEMPLATE_ID 268 -#define CNAT_NFV9_NAT44_ADD_SESSION_TEMPLATE_ID 271 -#define CNAT_NFV9_NAT44_DEL_SESSION_TEMPLATE_ID 272 -#define CNAT_NFV9_DS_LITE_ADD_SESSION_TEMPLATE_ID 273 -#define CNAT_NFV9_DS_LITE_DEL_SESSION_TEMPLATE_ID 274 - -#ifndef NO_BULK_LOGGING -#define CNAT_NFV9_NAT44_BULK_ADD_TEMPLATE_ID 265 -#define CNAT_NFV9_NAT44_BULK_DEL_TEMPLATE_ID 266 -#define CNAT_NFV9_DS_LITE_BULK_ADD_TEMPLATE_ID 269 -#define CNAT_NFV9_DS_LITE_BULK_DEL_TEMPLATE_ID 270 - -#define CNAT_NFV9_NAT44_BULK_ADD_FIELD_COUNT 6 -#define CNAT_NFV9_NAT44_BULK_DEL_FIELD_COUNT 3 -#define CNAT_NFV9_DS_LITE_BULK_ADD_FIELD_COUNT 7 -#define CNAT_NFV9_DS_LITE_BULK_DEL_FIELD_COUNT 4 - -#define CNAT_NFV9_OUTSIDE_IP_PORT_START_FIELD_TYPE 361 -#define CNAT_NFV9_OUTSIDE_IP_PORT_START_FIELD_SIZE 2 - -#define CNAT_NFV9_OUTSIDE_IP_PORT_END_FIELD_TYPE 362 -#define CNAT_NFV9_OUTSIDE_IP_PORT_END_FIELD_SIZE 2 - -#endif /* #ifndef NO_BULK_LOGGING */ - -#define CNAT_NFV9_INGRESS_VRF_NAME_FIELD_TYPE 236 -#define CNAT_NFV9_INGRESS_VRF_NAME_FIELD_SIZE 12 -/* 4 byte for vrf_id + 4 byte for vrf_name (option fields) */ -#define CNAT_NFV9_INGRESS_VRF_ID_NAME_OPTION_LEN 8 -extern u16 cnat_template_id[MAX_RECORDS]; - -#define CNAT_NFV9_INSIDE_VRFID_FIELD_TYPE 234 -#define CNAT_NFV9_INSIDE_VRFID_FIELD_SIZE 4 - -#define CNAT_NFV9_OUTSIDE_VRFID_FIELD_TYPE 235 -#define CNAT_NFV9_OUTSIDE_VRFID_FIELD_SIZE 4 - -#define CNAT_NFV9_INSIDE_IP_ADDR_FIELD_TYPE 8 -#define CNAT_NFV9_INSIDE_IP_ADDR_FIELD_SIZE 4 - -#define CNAT_NFV9_OUTSIDE_IP_ADDR_FIELD_TYPE 225 -#define CNAT_NFV9_OUTSIDE_IP_ADDR_FIELD_SIZE 4 - -#define CNAT_NFV9_INSIDE_IP_PORT_FIELD_TYPE 7 -#define CNAT_NFV9_INSIDE_IP_PORT_FIELD_SIZE 2 - -#define CNAT_NFV9_OUTSIDE_IP_PORT_FIELD_TYPE 227 -#define CNAT_NFV9_OUTSIDE_IP_PORT_FIELD_SIZE 2 - -#define CNAT_NFV9_PROTOCOL_FIELD_TYPE 4 -#define CNAT_NFV9_PROTOCOL_FIELD_SIZE 1 - -/* IPv6 related info */ - -#define CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_TYPE 27 -#define CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_SIZE 16 - -#define CNAT_NFV9_INSIDE_IPV6_DST_ADDR_FIELD_TYPE 28 -#define CNAT_NFV9_INSIDE_IPV6_DST_ADDR_FIELD_SIZE 16 - -#define CNAT_NFV9_OUTSIDE_IP_DST_ADDR_FIELD_TYPE 226 -#define CNAT_NFV9_OUTSIDE_IP_DST_ADDR_FIELD_SIZE 4 - -#define CNAT_NFV9_INSIDE_DST_PORT_FIELD_TYPE 11 -#define CNAT_NFV9_INSIDE_DST_PORT_FIELD_SIZE 2 - -#define CNAT_NFV9_DESTINATION_IP_ADDR_FIELD_TYPE 12 -#define CNAT_NFV9_DESTINATION_IP_ADDR_FIELD_SIZE 4 - - -typedef struct { - u16 version; - u16 count; - u32 sys_up_time; /* time in ms since system was booted */ - u32 timestamp; /* UNIX time in seconds since 1970 */ - u32 sequence_num; - u32 source_id; -} nfv9_header_t; - -/* - * Hardcoded - need to be fixed - */ -#define CNAT_NFV9_SOURCE_ID_VALUE 0x1234 - -typedef struct { - u16 flowset_id; - u16 length; - - u16 ingress_vrfid_name_map_template_id; - u16 ingress_vrfid_name_map_scope_len; - u16 ingress_vrfid_name_map_option_len; - u16 ingress_vrfid_name_map_vrfid_option_type; - u16 ingress_vrfid_name_map_vrfid_option_len; - u16 ingress_vrfid_name_map_vrfname_option_type; - u16 ingress_vrfid_name_map_vrfname_option_len; - /* - * Adding the padding so as to make the tempalate - * structure end on a 4 byte boundary - */ - u16 padding1; - -} cnat_nfv9_option_template_t; - -/* - * The following structure defines the Netflow Template that - * will be exported to the Netflow Collector - */ - -typedef struct { - u16 flowset_id; - u16 length; - - u16 add_template_id; - u16 add_field_count; - u16 add_inside_vrf_id_field_type; - u16 add_inside_vrf_id_field_size; - u16 add_outside_vrf_id_field_type; - u16 add_outside_vrf_id_field_size; - u16 add_inside_ip_addr_field_type; - u16 add_inside_ip_addr_field_size; - u16 add_outside_ip_addr_field_type; - u16 add_outside_ip_addr_field_size; - u16 add_inside_ip_port_field_type; - u16 add_inside_ip_port_field_size; - u16 add_outside_ip_port_field_type; - u16 add_outside_ip_port_field_size; - u16 add_protocol_field_type; - u16 add_protocol_field_size; - - u16 del_template_id; - u16 del_field_count; - u16 del_inside_vrf_id_field_type; - u16 del_inside_vrf_id_field_size; - u16 del_inside_ip_addr_field_type; - u16 del_inside_ip_addr_field_size; - u16 del_inside_ip_port_field_type; - u16 del_inside_ip_port_field_size; - u16 del_protocol_field_type; - u16 del_protocol_field_size; -#if 0 - /* NAT64 related info */ - u16 nat64_add_bib_template_id; - u16 nat64_add_bib_field_count; - u16 nat64_add_bib_inside_ipv6_addr_field_type; - u16 nat64_add_bib_inside_ipv6_addr_field_size; - u16 nat64_add_bib_outside_ip_addr_field_type; - u16 nat64_add_bib_outside_ip_addr_field_size; - u16 nat64_add_bib_inside_ip_port_field_type; - u16 nat64_add_bib_inside_ip_port_field_size; - u16 nat64_add_bib_outside_ip_port_field_type; - u16 nat64_add_bib_outside_ip_port_field_size; - u16 nat64_add_bib_protocol_field_type; - u16 nat64_add_bib_protocol_field_size; - - u16 nat64_del_bib_template_id; - u16 nat64_del_bib_field_count; - u16 nat64_del_bib_inside_ip_addr_field_type; - u16 nat64_del_bib_inside_ip_addr_field_size; - u16 nat64_del_bib_inside_ip_port_field_type; - u16 nat64_del_bib_inside_ip_port_field_size; - u16 nat64_del_bib_protocol_field_type; - u16 nat64_del_bib_protocol_field_size; - - - u16 nat64_add_session_template_id; - u16 nat64_add_session_field_count; - u16 nat64_add_session_inside_ipv6_src_addr_field_type; - u16 nat64_add_session_inside_ipv6_src_addr_field_size; - u16 nat64_add_session_outside_ip_src_addr_field_type; - u16 nat64_add_session_outside_ip_src_addr_field_size; - u16 nat64_add_session_inside_ipv6_dst_addr_field_type; - u16 nat64_add_session_inside_ipv6_dst_addr_field_size; - u16 nat64_add_session_outside_ip_dst_addr_field_type; - u16 nat64_add_session_outside_ip_dst_addr_field_size; - u16 nat64_add_session_inside_ip_src_port_field_type; - u16 nat64_add_session_inside_ip_src_port_field_size; - u16 nat64_add_session_outside_ip_src_port_field_type; - u16 nat64_add_session_outside_ip_src_port_field_size; - u16 nat64_add_session_ip_dest_port_field_type; - u16 nat64_add_session_ip_dest_port_field_size; - u16 nat64_add_session_protocol_field_type; - u16 nat64_add_session_protocol_field_size; - - u16 nat64_del_session_template_id; - u16 nat64_del_session_field_count; - u16 nat64_del_session_inside_ip_src_addr_field_type; - u16 nat64_del_session_inside_ip_src_addr_field_size; - u16 nat64_del_session_inside_ip_dst_addr_field_type; - u16 nat64_del_session_inside_ip_dst_addr_field_size; - u16 nat64_del_session_inside_ip_src_port_field_type; - u16 nat64_del_session_inside_ip_src_port_field_size; - u16 nat64_del_session_inside_ip_dst_port_field_type; - u16 nat64_del_session_inside_ip_dst_port_field_size; - u16 nat64_del_session_protocol_field_type; - u16 nat64_del_session_protocol_field_size; - - /* - * Ds-Lite specific info - */ - u16 add_dslite_template_id; - u16 add_dslite_field_count; - u16 add_dslite_inside_vrf_id_field_type; - u16 add_dslite_inside_vrf_id_field_size; - u16 add_dslite_outside_vrf_id_field_type; - u16 add_dslite_outside_vrf_id_field_size; - u16 add_dslite_inside_ip_addr_field_type; - u16 add_dslite_inside_ip_addr_field_size; - u16 add_dslite_inside_ipv6_addr_field_type; - u16 add_dslite_inside_ipv6_addr_field_size; - u16 add_dslite_outside_ip_addr_field_type; - u16 add_dslite_outside_ip_addr_field_size; - u16 add_dslite_inside_ip_port_field_type; - u16 add_dslite_inside_ip_port_field_size; - u16 add_dslite_outside_ip_port_field_type; - u16 add_dslite_outside_ip_port_field_size; - u16 add_dslite_protocol_field_type; - u16 add_dslite_protocol_field_size; - - u16 del_dslite_template_id; - u16 del_dslite_field_count; - u16 del_dslite_inside_vrf_id_field_type; - u16 del_dslite_inside_vrf_id_field_size; - u16 del_dslite_inside_ip_addr_field_type; - u16 del_dslite_inside_ip_addr_field_size; - u16 del_dslite_inside_ipv6_addr_field_type; - u16 del_dslite_inside_ipv6_addr_field_size; - u16 del_dslite_inside_ip_port_field_type; - u16 del_dslite_inside_ip_port_field_size; - u16 del_dslite_protocol_field_type; - u16 del_dslite_protocol_field_size; -#endif - -//#ifndef NO_BULK_LOGGING /* commenting for time being */ -#if 0 - u16 bulk_add_template_id; - u16 bulk_add_field_count; - u16 bulk_add_inside_vrf_id_field_type; - u16 bulk_add_inside_vrf_id_field_size; - u16 bulk_add_outside_vrf_id_field_type; - u16 bulk_add_outside_vrf_id_field_size; - u16 bulk_add_inside_ip_addr_field_type; - u16 bulk_add_inside_ip_addr_field_size; - u16 bulk_add_outside_ip_addr_field_type; - u16 bulk_add_outside_ip_addr_field_size; - u16 bulk_add_outside_start_port_field_type; - u16 bulk_add_outside_start_port_field_size; - u16 bulk_add_outside_end_port_field_type; - u16 bulk_add_outside_end_port_field_size; - - u16 bulk_del_template_id; - u16 bulk_del_field_count; - u16 bulk_del_inside_vrf_id_field_type; - u16 bulk_del_inside_vrf_id_field_size; - u16 bulk_del_inside_ip_addr_field_type; - u16 bulk_del_inside_ip_addr_field_size; - u16 bulk_del_outside_start_port_field_type; - u16 bulk_del_outside_start_port_field_size; - - /* ds-lite bulk logging create delete event */ - - u16 bulk_dslite_add_template_id; - u16 bulk_dslite_add_field_count; - u16 bulk_dslite_add_inside_vrf_id_field_type; - u16 bulk_dslite_add_inside_vrf_id_field_size; - u16 bulk_dslite_add_outside_vrf_id_field_type; - u16 bulk_dslite_add_outside_vrf_id_field_size; - u16 bulk_dslite_add_inside_ip_addr_field_type; - u16 bulk_dslite_add_inside_ip_addr_field_size; - u16 bulk_dslite_add_inside_ipv6_addr_field_type; - u16 bulk_dslite_add_inside_ipv6_addr_field_size; - u16 bulk_dslite_add_outside_ip_addr_field_type; - u16 bulk_dslite_add_outside_ip_addr_field_size; - u16 bulk_dslite_add_outside_start_port_field_type; - u16 bulk_dslite_add_outside_start_port_field_size; - u16 bulk_dslite_add_outside_end_port_field_type; - u16 bulk_dslite_add_outside_end_port_field_size; - - u16 bulk_dslite_del_template_id; - u16 bulk_dslite_del_field_count; - u16 bulk_dslite_del_inside_vrf_id_field_type; - u16 bulk_dslite_del_inside_vrf_id_field_size; - u16 bulk_dslite_del_inside_ip_addr_field_type; - u16 bulk_dslite_del_inside_ip_addr_field_size; - u16 bulk_dslite_del_inside_ipv6_addr_field_type; - u16 bulk_dslite_del_inside_ipv6_addr_field_size; - u16 bulk_dslite_del_outside_start_port_field_type; - u16 bulk_dslite_del_outside_start_port_field_size; - -#endif /* NO_BULK_LOGGING */ - - u16 nat44_session_add_template_id; - u16 nat44_session_add_field_count; - u16 nat44_session_add_inside_vrf_id_field_type; - u16 nat44_session_add_inside_vrf_id_field_size; - u16 nat44_session_add_outside_vrf_id_field_type; - u16 nat44_session_add_outside_vrf_id_field_size; - u16 nat44_session_add_inside_ip_addr_field_type; - u16 nat44_session_add_inside_ip_addr_field_size; - u16 nat44_session_add_outside_ip_addr_field_type; - u16 nat44_session_add_outside_ip_addr_field_size; - u16 nat44_session_add_inside_ip_port_field_type; - u16 nat44_session_add_inside_ip_port_field_size; - u16 nat44_session_add_outside_ip_port_field_type; - u16 nat44_session_add_outside_ip_port_field_size; - u16 nat44_session_add_dest_ip_addr_field_type; - u16 nat44_session_add_dest_ip_addr_field_size; - u16 nat44_session_add_dest_port_field_type; - u16 nat44_session_add_dest_port_field_size; - u16 nat44_session_add_protocol_field_type; - u16 nat44_session_add_protocol_field_size; - - u16 nat44_session_del_template_id; - u16 nat44_session_del_field_count; - u16 nat44_session_del_inside_vrf_id_field_type; - u16 nat44_session_del_inside_vrf_id_field_size; - u16 nat44_session_del_inside_ip_addr_field_type; - u16 nat44_session_del_inside_ip_addr_field_size; - u16 nat44_session_del_dest_ip_addr_field_type; - u16 nat44_session_del_dest_ip_addr_field_size; - u16 nat44_session_del_inside_ip_port_field_type; - u16 nat44_session_del_inside_ip_port_field_size; - u16 nat44_session_del_dest_port_field_type; - u16 nat44_session_del_dest_port_field_size; - u16 nat44_session_del_protocol_field_type; - u16 nat44_session_del_protocol_field_size; - -#if 0 - u16 add_dslite_session_template_id; - u16 add_dslite_session_field_count; - u16 add_dslite_session_inside_vrf_id_field_type; - u16 add_dslite_session_inside_vrf_id_field_size; - u16 add_dslite_session_outside_vrf_id_field_type; - u16 add_dslite_session_outside_vrf_id_field_size; - u16 add_dslite_session_inside_ip_addr_field_type; - u16 add_dslite_session_inside_ip_addr_field_size; - u16 add_dslite_session_inside_ipv6_addr_field_type; - u16 add_dslite_session_inside_ipv6_addr_field_size; - u16 add_dslite_session_outside_ip_addr_field_type; - u16 add_dslite_session_outside_ip_addr_field_size; - u16 add_dslite_session_inside_ip_port_field_type; - u16 add_dslite_session_inside_ip_port_field_size; - u16 add_dslite_session_outside_ip_port_field_type; - u16 add_dslite_session_outside_ip_port_field_size; - u16 add_dslite_session_dest_ip_addr_field_type; - u16 add_dslite_session_dest_ip_addr_field_size; - u16 add_dslite_session_dest_port_field_type; - u16 add_dslite_session_dest_port_field_size; - u16 add_dslite_session_protocol_field_type; - u16 add_dslite_session_protocol_field_size; - - u16 del_dslite_session_template_id; - u16 del_dslite_session_field_count; - u16 del_dslite_session_inside_vrf_id_field_type; - u16 del_dslite_session_inside_vrf_id_field_size; - u16 del_dslite_session_inside_ip_addr_field_type; - u16 del_dslite_session_inside_ip_addr_field_size; - u16 del_dslite_session_inside_ipv6_addr_field_type; - u16 del_dslite_session_inside_ipv6_addr_field_size; - u16 del_dslite_session_dest_ip_addr_field_type; - u16 del_dslite_session_dest_ip_addr_field_size; - u16 del_dslite_session_inside_ip_port_field_type; - u16 del_dslite_session_inside_ip_port_field_size; - u16 del_dslite_session_dest_port_field_type; - u16 del_dslite_session_dest_port_field_size; - u16 del_dslite_session_protocol_field_type; - u16 del_dslite_session_protocol_field_size; -#endif - - /* - * Netflow option template - * Ingress VRF ID - Name mapping - * This template will be sent under flowset id 1 - */ - cnat_nfv9_option_template_t cnat_nfv9_option_template; -} cnat_nfv9_template_t; - -/* - * The Dataflow header for each add/delete record group - */ -typedef struct { - u16 dataflow_template_id; - u16 dataflow_length; -} nfv9_dataflow_record_header_t; - -/* - * NFv9 Add record definition - */ - -/* - * pad bytes needed to make the structure a multiple of 4 bytes - */ -#define CNAT_NFV9_ADD_RECORD_PAD_BYTES (3) -#define CNAT_NFV9_DEL_RECORD_PAD_BYTES (1) - -#define CNAT_NFV9_NAT64_ADD_BIB_RECORD_PAD_BYTES (3) -#define CNAT_NFV9_NAT64_DEL_BIB_RECORD_PAD_BYTES (1) -#define CNAT_NFV9_NAT64_ADD_SESSION_RECORD_PAD_BYTES (1) -#define CNAT_NFV9_NAT64_DEL_SESSION_RECORD_PAD_BYTES (3) -#define CNAT_NFV9_NAT44_ADD_SESSION_RECORD_PAD_BYTES (1) -#define CNAT_NFV9_NAT44_DEL_SESSION_RECORD_PAD_BYTES (3) - -#define CNAT_NFV9_DS_LITE_ADD_RECORD_PAD_BYTES (3) -#define CNAT_NFV9_DS_LITE_DEL_RECORD_PAD_BYTES (1) -#define CNAT_NFV9_DS_LITE_ADD_SESSION_RECORD_PAD_BYTES (1) -#define CNAT_NFV9_DS_LITE_DEL_SESSION_RECORD_PAD_BYTES (3) - -#define CNAT_NFV9_INGRESS_VRFID_NAME_RECORD_PAD_BYTES (0) - -typedef struct { - u32 inside_vrf_id; - u32 outside_vrf_id; - u32 inside_ip_addr; - u32 outside_ip_addr; - u16 inside_ip_port; - u16 outside_ip_port; - u8 protocol; - u8 pad[CNAT_NFV9_ADD_RECORD_PAD_BYTES]; -} nfv9_add_record_t; - -/* - * NFv9 Delete record definition - */ -typedef struct { - u32 inside_vrf_id; - u32 inside_ip_addr; - u16 inside_ip_port; - u8 protocol; - u8 pad[CNAT_NFV9_DEL_RECORD_PAD_BYTES]; -} nfv9_del_record_t; - -#ifndef NO_BULK_LOGGING - -#define CNAT_NFV9_BULK_ADD_RECORD_PAD_BYTES (0) -#define CNAT_NFV9_BULK_DEL_RECORD_PAD_BYTES (2) - -typedef struct { - u32 inside_vrf_id; - u32 outside_vrf_id; - u32 inside_ip_addr; - u32 outside_ip_addr; - u16 outside_ip_port_start; - u16 outside_ip_port_end; - u8 pad[CNAT_NFV9_BULK_ADD_RECORD_PAD_BYTES]; -} nfv9_bulk_add_record_t; - -/* - * NFv9 Delete record definition - */ -typedef struct { - u32 inside_vrf_id; - u32 inside_ip_addr; - u16 outside_ip_port_start; - u8 pad[CNAT_NFV9_BULK_DEL_RECORD_PAD_BYTES]; -} nfv9_bulk_del_record_t; - -/* - * DS-lite bulk port (user based) add record definition - */ - -#define CNAT_NFV9_DS_LITE_BULK_ADD_RECORD_PAD_BYTES (0) -#define CNAT_NFV9_DS_LITE_BULK_DEL_RECORD_PAD_BYTES (2) - -typedef struct { - u32 inside_vrf_id; - u32 outside_vrf_id; - u32 inside_ip_addr; - u32 inside_v6_src_addr[4]; - u32 outside_ip_addr; - u16 outside_ip_port_start; - u16 outside_ip_port_end; - u8 pad[CNAT_NFV9_DS_LITE_BULK_ADD_RECORD_PAD_BYTES]; -} nfv9_ds_lite_bulk_add_record_t; - - -/* - * DS-lite bulk port (user based) delete record definition - */ - -typedef struct { - u32 inside_vrf_id; - u32 inside_ip_addr; - u32 inside_v6_src_addr[4]; - u16 outside_ip_port_start; - u8 pad[CNAT_NFV9_DS_LITE_BULK_DEL_RECORD_PAD_BYTES]; -} nfv9_ds_lite_bulk_del_record_t; - -#endif /* NO_BULK_LOGGING */ - -/* NAT64 related structures */ - -typedef struct { - u32 inside_v6_src_addr[4]; - u32 outside_v4_src_addr; - u16 inside_src_port; - u16 outside_src_port; - u8 protocol; - u8 pad[CNAT_NFV9_NAT64_ADD_BIB_RECORD_PAD_BYTES]; -} nfv9_nat64_add_bib_record_t; - - -typedef struct { - u32 inside_v6_src_addr[4]; - u32 outside_v4_src_addr; - u32 inside_v6_dest_addr[4]; - u32 outside_v4_dest_addr; - u16 inside_src_port; - u16 outside_src_port; - u16 dest_port; - u8 protocol; - u8 pad[CNAT_NFV9_NAT64_ADD_SESSION_RECORD_PAD_BYTES]; -} nfv9_nat64_add_session_record_t; - - -typedef struct { - u32 inside_v6_src_addr[4]; - u16 inside_src_port; - u8 protocol; - u8 pad[CNAT_NFV9_NAT64_DEL_BIB_RECORD_PAD_BYTES]; -} nfv9_nat64_del_bib_record_t; - - -typedef struct { - u32 inside_v6_src_addr[4]; - u32 inside_v6_dest_addr[4]; - u16 inside_src_port; - u16 dest_port; - u8 protocol; - u8 pad[CNAT_NFV9_NAT64_DEL_SESSION_RECORD_PAD_BYTES]; -} nfv9_nat64_del_session_record_t; - -/* - * NFv9 Session based Add record definition - */ -typedef struct { - u32 inside_vrf_id; - u32 outside_vrf_id; - u32 inside_ip_addr; - u32 outside_ip_addr; - u16 inside_ip_port; - u16 outside_ip_port; - u32 dest_ip_addr; - u16 dest_port; - u8 protocol; - u8 pad[CNAT_NFV9_NAT44_ADD_SESSION_RECORD_PAD_BYTES]; -} nfv9_add_session_record_t; - -/* - * NFv9 Session based del record definition - */ -typedef struct { - u32 inside_vrf_id; - u32 inside_ip_addr; - u32 dest_ip_addr; - u16 inside_ip_port; - u16 dest_port; - u8 protocol; - u8 pad[CNAT_NFV9_NAT44_DEL_SESSION_RECORD_PAD_BYTES]; -} nfv9_del_session_record_t; - -/* - * DS-lite NFv9 create record structure - */ -typedef struct { - u32 inside_vrf_id; - u32 outside_vrf_id; - u32 inside_ip_addr; - u32 inside_v6_src_addr[4]; - u32 outside_ip_addr; - u16 inside_ip_port; - u16 outside_ip_port; - u8 protocol; - u8 pad[CNAT_NFV9_DS_LITE_ADD_RECORD_PAD_BYTES]; -} nfv9_ds_lite_add_record_t; - -typedef struct { - u32 inside_vrf_id; - u32 inside_ip_addr; - u32 inside_v6_src_addr[4]; - u16 inside_ip_port; - u8 protocol; - u8 pad[CNAT_NFV9_DS_LITE_DEL_RECORD_PAD_BYTES]; -} nfv9_ds_lite_del_record_t; - -/* - * NFv9 Session based Add record definition - */ -typedef struct { - u32 inside_vrf_id; - u32 outside_vrf_id; - u32 inside_ip_addr; - u32 inside_v6_src_addr[4]; - u32 outside_ip_addr; - u16 inside_ip_port; - u16 outside_ip_port; - u32 dest_ip_addr; - u16 dest_port; - u8 protocol; - u8 pad[CNAT_NFV9_DS_LITE_ADD_SESSION_RECORD_PAD_BYTES]; -} nfv9_ds_lite_add_session_record_t; - -/* - * NFv9 Session based del record definition - */ -typedef struct { - u32 inside_vrf_id; - u32 inside_ip_addr; - u32 inside_v6_src_addr[4]; - u32 dest_ip_addr; - u16 inside_ip_port; - u16 dest_port; - u8 protocol; - u8 pad[CNAT_NFV9_DS_LITE_DEL_SESSION_RECORD_PAD_BYTES]; -} nfv9_ds_lite_del_session_record_t; - - -typedef struct { - u32 ingress_vrf_id; - u8 ingress_vrf_name[NFV9_VRF_NAME_LEN]; - u8 pad[CNAT_NFV9_INGRESS_VRFID_NAME_RECORD_PAD_BYTES]; -} nfv9_ingress_vrfid_name_record_t; - -#define CNAT_NFV9_TEMPLATE_OFFSET \ - (CNAT_NFV9_HDR_OFFSET + sizeof(nfv9_header_t)) - -#define CNAT_NFV9_TEMPLATE_LENGTH (sizeof(cnat_nfv9_template_t)) -#define CNAT_NFV9_OPTION_TEMPLATE_LENGTH (sizeof(cnat_nfv9_option_template_t)) - -#define CNAT_NFV9_DATAFLOW_RECORD_HEADER_LENGTH \ - (sizeof(nfv9_dataflow_record_header_t)) - -/* - * No padding is needed for the add/delete records - reduce padding bytes - */ - -#define CNAT_NFV9_ADD_RECORD_LENGTH (sizeof(nfv9_add_record_t) - \ - CNAT_NFV9_ADD_RECORD_PAD_BYTES) - -#define CNAT_NFV9_DEL_RECORD_LENGTH (sizeof(nfv9_del_record_t) - \ - CNAT_NFV9_DEL_RECORD_PAD_BYTES) - -#define CNAT_NFV9_DS_LITE_ADD_RECORD_LENGTH (sizeof(nfv9_ds_lite_add_record_t) - \ - CNAT_NFV9_DS_LITE_ADD_RECORD_PAD_BYTES) -#define CNAT_NFV9_DS_LITE_DEL_RECORD_LENGTH (sizeof(nfv9_ds_lite_del_record_t) - \ - CNAT_NFV9_DS_LITE_DEL_RECORD_PAD_BYTES) -#ifndef NO_BULK_LOGGING -#define CNAT_NFV9_BULK_ADD_RECORD_LENGTH (sizeof(nfv9_bulk_add_record_t) - \ - CNAT_NFV9_BULK_ADD_RECORD_PAD_BYTES) -#define CNAT_NFV9_BULK_DEL_RECORD_LENGTH (sizeof(nfv9_bulk_del_record_t) - \ - CNAT_NFV9_BULK_DEL_RECORD_PAD_BYTES) - -#define CNAT_NFV9_DS_LITE_BULK_ADD_RECORD_LENGTH (sizeof(nfv9_ds_lite_bulk_add_record_t) - \ - CNAT_NFV9_DS_LITE_BULK_ADD_RECORD_PAD_BYTES) -#define CNAT_NFV9_DS_LITE_BULK_DEL_RECORD_LENGTH (sizeof(nfv9_ds_lite_bulk_del_record_t) - \ - CNAT_NFV9_DS_LITE_BULK_DEL_RECORD_PAD_BYTES) - - -#endif /* NO_BULK_LOGGING */ - -#define CNAT_NFV9_INGRESS_VRFID_NAME_RECORD_LENGTH (sizeof(nfv9_ingress_vrfid_name_record_t) - \ - CNAT_NFV9_INGRESS_VRFID_NAME_RECORD_PAD_BYTES) - -#define CNAT_NFV9_NAT64_ADD_BIB_RECORD_LENGTH \ - (sizeof(nfv9_nat64_add_bib_record_t) - \ - CNAT_NFV9_NAT64_ADD_BIB_RECORD_PAD_BYTES) - -#define CNAT_NFV9_NAT64_DEL_BIB_RECORD_LENGTH \ - (sizeof(nfv9_nat64_del_bib_record_t) - \ - CNAT_NFV9_NAT64_DEL_BIB_RECORD_PAD_BYTES) - -#define CNAT_NFV9_NAT64_ADD_SESSION_RECORD_LENGTH \ - (sizeof(nfv9_nat64_add_session_record_t) - \ - CNAT_NFV9_NAT64_ADD_SESSION_RECORD_PAD_BYTES) - -#define CNAT_NFV9_NAT64_DEL_SESSION_RECORD_LENGTH \ - (sizeof(nfv9_nat64_del_session_record_t) - \ - CNAT_NFV9_NAT64_DEL_SESSION_RECORD_PAD_BYTES) - -#define CNAT_NFV9_MAX_SINGLE_RECORD_LENGTH \ - (sizeof(nfv9_ds_lite_add_session_record_t) - \ - CNAT_NFV9_DS_LITE_ADD_SESSION_RECORD_PAD_BYTES) - -#define CNAT_NFV9_NAT44_ADD_SESSION_RECORD_LENGTH \ - (sizeof(nfv9_add_session_record_t) -\ - CNAT_NFV9_NAT44_ADD_SESSION_RECORD_PAD_BYTES) - -#define CNAT_NFV9_NAT44_DEL_SESSION_RECORD_LENGTH \ - (sizeof(nfv9_del_session_record_t) -\ - CNAT_NFV9_NAT44_DEL_SESSION_RECORD_PAD_BYTES) - -#define CNAT_NFV9_DS_LITE_ADD_SESSION_RECORD_LENGTH \ - (sizeof(nfv9_ds_lite_add_session_record_t) -\ - CNAT_NFV9_DS_LITE_ADD_SESSION_RECORD_PAD_BYTES) - -#define CNAT_NFV9_DS_LITE_DEL_SESSION_RECORD_LENGTH \ - (sizeof(nfv9_ds_lite_del_session_record_t) -\ - CNAT_NFV9_DS_LITE_DEL_SESSION_RECORD_PAD_BYTES) - -/* - * Minimum value of the path MTU value - */ -#define CNAT_NFV9_MIN_RECORD_SIZE (60 + \ - CNAT_NFV9_DATAFLOW_RECORD_HEADER_LENGTH + \ - CNAT_NFV9_TEMPLATE_LENGTH + \ - CNAT_NFV9_MAX_SINGLE_RECORD_LENGTH) - -/* - * Let us put the maximum length of the netflow data to be 1400 - */ -#define CNAT_NFV9_MAX_PKT_LENGTH 1400 - -/* - * Data structures and defines to store NFV9 specific info - */ -#define CNAT_NFV9_INVALID_LOGGING_INDEX 0xffffffff - -/* - * Padding value between ADD and DELETE records. This can be atmost 3 bytes - */ -#define NFV9_PAD_VALUE (3) - -typedef struct { - /* NFV9 server specific info - * For now, it will maintain only package sequence count. - * Later it will maintain server address, port, etc. - * Though it currently has server address and port, it is only for - * cross refernce - */ - u32 ipv4_address; /* Destination IP address of the collector */ - u16 port; /* Destination port number of the collector */ - u16 refresh_rate; /* Refresh rate in packets after which template is sent */ - u16 timeout_rate; /* Timeout rate in seconds after which template is sent */ - u16 ref_count; /* Num of instances using this data */ - u32 sequence_num; /* Sequence number of the logging packet */ - /* - * Keep track of the time and packets since last template send - */ - u32 last_template_sent_time; - u32 pkts_since_last_template; - u8 template_sent; /* used while sending vrfid-name mapping */ - -} nfv9_server_info_t; - -/* - * This structure store the Netflow Logging information on per NFv9 - * collector basis. This structure is allocated from a pool and index - * to this structure is stored VRF MAP structures - */ -typedef struct { - /* - * nat64_id will be 0 for nat44 config and i_vrf_id, i_vrf will be 0 - * for nat64 config. Nat64_id will be used while nat64 collector is - * search and i_vrf* for nat44 collector - */ - /* Similarly for ds_lite, ds_lite_id will be used and nat64_id, - * ivrf_id shall be set to 0 - */ - u32 i_vrf_id; /* Inside VRF ID corresponding to this collector */ - u16 i_vrf; /* Inside VRF (uidb_index) corresponding to this collector */ - u16 nat64_id; /* NAT64 instance for to this collector */ - u16 ds_lite_id; /* DS Lite instance for this collector */ - - /* - * This field determines the maximum size of the Netflow V9 information - * that can be stored in a logging packet - */ - u16 max_length_minus_max_record_size; - - /* - * Indicates if the entry is already deleted - */ - u16 deleted; - - u16 pkt_length; /* Length of the currently NFv9 information */ - u16 record_length[MAX_RECORDS]; /* Length of delete record */ - u16 total_record_count; /* Total number of records including templates */ - - u8 logging_policy; - - /* - * Keep track of the time and packets since last template send - */ - u32 last_template_sent_time; - u32 pkts_since_last_template; - - /* Server info */ - u32 server_index; - - /* - * current logging context - */ - vlib_buffer_t *current_logging_context; - - /* - * Timestamp in UNIX seconds corresponding to when the current - * logging packet was created - */ - u32 current_logging_context_timestamp; - - /* - * Queued logging context waiting to be sent to the l3 infra node - */ - vlib_buffer_t *queued_logging_context; - - /* - * Headers corresponding to various records in this - * current nfv9 logging context - */ - nfv9_header_t *nfv9_header; - cnat_nfv9_template_t *nfv9_template_header; - nfv9_dataflow_record_header_t *dataflow_header; - u8 *record[MAX_RECORDS]; - u8 *next_data_ptr; - u8 last_record; - u32 nfv9_logging_next_index; - u32 ip4_input_node_index; - vlib_frame_t *f; - u32 *to_next; -} cnat_nfv9_logging_info_t; - - -/* - * Global structure for CGN APP configuration - */ -typedef struct { - /* - * Global NFv9 Logging Collector Index - */ - u32 cnat_nfv9_global_collector_index; - - /* - * Node index corresponding to the infra L3 output node - * to which the nfv9 logging node will send the packet - */ - u16 cnat_nfv9_disp_node_index; - - /* - * Whether we have initialized the NFv9 information - */ - u8 cnat_nfv9_init_done; -} cnat_nfv9_global_info_t; - -typedef enum { - cnat_nfv9_template_add_default, - cnat_nfv9_template_add_always -} cnat_nfv9_template_add_flag_t; - -extern cnat_nfv9_template_t cnat_nfv9_template_info; - -extern cnat_nfv9_logging_info_t cnat_default_nfv9_logging_info; -extern cnat_nfv9_logging_info_t *cnat_nfv9_logging_info_pool; - -extern cnat_nfv9_global_info_t cnat_nfv9_global_info; -extern nfv9_server_info_t *nfv9_server_info_pool; - -/* #define DEBUG_NF_SERVER_CONFIG 1 */ -static inline void nfv9_delete_server_info(cnat_nfv9_logging_info_t *nfv9_info) -{ - nfv9_server_info_t *server = nfv9_server_info_pool + - nfv9_info->server_index; - if(nfv9_info->server_index == EMPTY) { -#ifdef DEBUG_NF_SERVER_CONFIG - if(my_instance_number == 1) { - PLATFORM_DEBUG_PRINT("Deleting empty server info\n"); - } -#endif /* #ifdef DEBUG_NF_SERVER_CONFIG */ - return; - } - - /* Check if this server is not used by anyone.. if not delete */ - /* Caller of this function does not need it..so decrement ref count */ - server->ref_count--; - if(!(server->ref_count)) { -#ifdef DEBUG_NF_SERVER_CONFIG - if(my_instance_number == 1) { - PLATFORM_DEBUG_PRINT("Deleting nfv9 server %x, %d at %d\n", - server->ipv4_address, - server->port, - nfv9_info->server_index); - } -#endif /* #ifdef DEBUG_NF_SERVER_CONFIG */ - pool_put(nfv9_server_info_pool, server); - nfv9_info->server_index = EMPTY; - } -#ifdef DEBUG_NF_SERVER_CONFIG - else { - if(my_instance_number == 1) { - PLATFORM_DEBUG_PRINT("Not Deleting nfv9 server %x, %d rc %d\n", - server->ipv4_address, - server->port, - server->ref_count); - } - } -#endif /* #ifdef DEBUG_NF_SERVER_CONFIG */ - return; -} - -void handle_pending_nfv9_pkts(); -#endif /* __CNAT_LOGGING_H__ */ diff --git a/plugins/plugins/vcgn/cnat_pcp_server.h b/plugins/plugins/vcgn/cnat_pcp_server.h deleted file mode 100644 index c77c6a87..00000000 --- a/plugins/plugins/vcgn/cnat_pcp_server.h +++ /dev/null @@ -1,398 +0,0 @@ -/* - *------------------------------------------------------------------ - * cnat_pcp_server.h - * - * Copyright (c) 2009-2012 Cisco and/or its affiliates. - * 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 __CNAT_PCP_SERVER_H__ -#define __CNAT_PCP_SERVER_H__ - -#include "dslite_defs.h" - -/* Debug utils of PCP */ -#define PCP_DBG(debug, ...) \ - if(PREDICT_FALSE(cnat_pcp_debug_flag >= debug)) { \ - printf("%s:%s:%d - ", \ - __FILE__, __FUNCTION__, __LINE__);\ - printf(__VA_ARGS__);\ - printf("\n"); \ - } - -#define PCP_DUMP_PDATA \ - if(PREDICT_FALSE(cnat_pcp_debug_flag >= 100)) { \ - printf("%s:%s:%d - \n", \ - __FILE__, __FUNCTION__, __LINE__);\ - printf("src - ip = %X, proto = %d, port = %d i_vrf = %d, o_vrf = %d\n", \ - pcp_data.src_ip[3], pcp_data.proto, pcp_data.src_port, pcp_data.i_vrf, pcp_data.o_vrf); \ - printf(" third party ip = %X\n", pcp_data.third_party_ip[3]); \ - printf("map - ip = %X, port = %d \n", \ - pcp_data.ext_ip[3], pcp_data.ext_port);\ - printf("remote - ip = %X, port = %d \n", \ - pcp_data.peer_ip[3], pcp_data.peer_port); \ - printf("req life time = %d \n", pcp_data.req_lifetime); \ - printf("drop = %d \n", pcp_data.drop);\ - printf("udp_len = %d \n", pcp_data.udp_len); \ - printf("pm = %p \n", pcp_data.pm); \ - printf("cnat_proto = %X \n", pcp_data.cnat_proto); \ - printf("inst_id = %X \n", pcp_data.inst_id); \ - printf("======================================================\n"); \ - } - -#define PCP_DUMP_PACKET(ip, len) pcp_hex_dump(ip, len) - -#ifdef TOBE_PORTED -#define PCP_INCR(counter) pcp_counters.pcp_##counter++ ; -#else -#define PCP_INCR(counter) -#endif - -typedef struct pcp_debug_counters { - u64 pcp_input; - u64 pcp_output; - u64 pcp_service_nat44; - u64 pcp_service_dslite; - /* below all are drops */ - u64 pcp_drops; - u64 pcp_i2o_key_inuse; - u64 pcp_throttle_drops; - u64 pcp_udp_len; - u64 pcp_nrequest; - u64 pcp_min_udp_len; - u64 pcp_max_udp_len; - u64 pcp_mod4_len; - u64 pcp_invalid_3rd_len; - u64 pcp_invalid_option; - u64 pcp_version; - u64 pcp_invalid_opcode; - u64 pcp_invalid_client_ip; - u64 pcp_invalid_proto; - u64 pcp_invalid_port; - u64 pcp_invalid_vrfmap; - u64 pcp_invalid_ext_addr; - u64 pcp_out_addr_inuse; - u64 pcp_exact_match; - u64 pcp_exact_entry_created; - u64 pcp_exact_db_alloc_failed; - u64 pcp_udb_mismatch; - u64 pcp_noexact_db_allocated; - u64 pcp_static_entry_present; - u64 pcp_entry_deleted; - u64 pcp_3rd_party_option; - - /* map counters */ - u64 pcp_map_input; - u64 pcp_map_min_len; - u64 pcp_map_max_len; - u64 pcp_map_invalid_option; - u64 pcp_map_invalid_option_len; - u64 pcp_map_pref_fail_option; - u64 pcp_map_invalid_delete_req; - u64 pcp_map_delete_req; - u64 pcp_map_create_req; - u64 pcp_map_refresh; - - /* peer counters */ - u64 pcp_peer_input; - u64 pcp_peer_invalid_len; - u64 pcp_peer_delete_req; - u64 pcp_peer_create_req; - u64 pcp_peer_addr_mistmatch; - u64 pcp_peer_refresh; - -} pcp_debug_counters_t; - -typedef struct { - u16 msg_id; - u8 rc; - u8 pad[5]; - - /* better to have a group structures rather than individual - variables, any change in counters is will automatically - reflect here */ - pcp_debug_counters_t counters; -} pcp_show_counters_resp_t ; - - - -/* PCP opcodes */ -typedef enum pcp_opcode { - PCP_OPCODE_MAP = 1, - PCP_OPCODE_PEER = 2 -}pcp_opcode_t; - - -/* PCP opcodes */ -typedef enum pcp_options { - PCP_OPTION_3RD_PARTY = 1, - PCP_OPTION_PREF_FAIL = 2, - PCP_OPTION_FILTER = 3 -} pcp_options_t; - -/* PCP Result codes */ -typedef enum pcp_result_codes { - PCP_SUCCESS = 0, - PCP_ERR_UNSUPP_VERSION = 1, - PCP_ERR_NOT_AUTHORIZED = 2, - PCP_ERR_MALFORMED_REQUEST = 3, - PCP_ERR_UNSUPP_OPCODE = 4, - PCP_ERR_UNSUPP_OPTION = 5, - PCP_ERR_MALFORMED_OPTION = 6, - PCP_ERR_NETWORK_FAILURE = 7, - PCP_ERR_NO_RESOURCES = 8, - PCP_ERR_UNSUPP_PROTOCOL = 9, - PCP_ERR_USER_EX_QUOTA = 10, - PCP_ERR_CANNOT_PROVIDE_EXTERNAL = 11, - PCP_ERR_ADDRESS_MISMATCH = 12, - PCP_ERR_EXCESSIVE_REMOTE_PEERS = 13 -} pcp_result_codes_t; - -#define PCP_DISABLED 0 -#define PCP_ENABLED 1 - -#define PCP_DROP 1 - -#define PCP_STATIC_LIFETIME 0xFFFFFFFF -#define PCP_MAX_LIFETIME 0x00015180 /* 24 hours = 86400 seconds*/ - -#define PCP_VERSION_SUPPORTED 1 - -#define PCP_NO_PREF_FAIL_OPTION 0 -#define PCP_PREF_FAIL_OPTION 1 - -#define CNAT_DEF_PCP_PORT 5351 - -#define PCP_REQ_RESP_BIT 0x80 -#define PCP_RESPONSE(r_opcode) (r_opcode & PCP_REQ_RESP_BIT) -#define PCP_REQUEST(r_opcode) !(PCP_RESPONSE(r_opcode)) - -#define PCP_REQ_OPCODE(r_opcode) (r_opcode & 0x7F) - -/* 24 bytes */ -#define PCP_COMMON_HDR_LEN sizeof(pcp_request_t) - -/* 8 bytes */ -#define UDP_HDR_LEN sizeof(udp_hdr_type_t) - -#define PCP_PREF_FAIL_OPTION_SIZE \ - sizeof(pcp_prefer_fail_option_t) - -#define PCP_3RD_PARTY_OPTION_SIZE \ - sizeof(pcp_3rd_party_option_t) - -#define PCP_MIN_LEN PCP_COMMON_HDR_LEN - -/* 24+8=32 bytes */ -#define PCP_MIN_UDP_LEN (PCP_MIN_LEN + UDP_HDR_LEN) - -#define PCP_MAX_LEN 1024 - -/* 1024+8 = 1032 bytes */ -#define PCP_MAX_UDP_LEN (PCP_MAX_LEN + UDP_HDR_LEN) - -/* 24+ 24 = 48 bytes */ -#define PCP_MAP_OPCODE_MIN_LEN (PCP_COMMON_HDR_LEN + \ - sizeof( pcp_map_option_specific_data_t)) - -/* 24 + 44 = 68 bytes */ -#define PCP_PEER_OPCODE_MIN_LEN (PCP_COMMON_HDR_LEN + \ - sizeof( pcp_peer_option_specific_data_t)) - -/* 48 + 8 = 56 bytes */ -#define PCP_MAP_OPCODE_MIN_UDP_LEN (PCP_MAP_OPCODE_MIN_LEN + \ - UDP_HDR_LEN ) - -#define PCP_GET_MAP_OPTION_OFFSET(req) \ - ((u8*)req + PCP_MAP_OPCODE_MIN_LEN) - -#define PCP_GET_PEER_OPTION_OFFSET(req) \ - ((u8*)req + PCP_PEER_OPCODE_MIN_LEN) - - -#define PCP_REQ_TOTAL_LEN(udp) (udp->udp_length - \ - UDP_HDR_LEN) -/* 56 + 4 = 60 bytes */ -#define PCP_MAP_OPCODE_PREF_FAIL_OPTION_LEN \ - (PCP_MAP_OPCODE_MIN_UDP_LEN + \ - sizeof(pcp_prefer_fail_option_t)) - - -/* 68 + 8 = 76 bytes */ -#define PCP_PEER_OPCODE_MIN_UDP_LEN (PCP_PEER_OPCODE_MIN_LEN + \ - UDP_HDR_LEN) - -#define PCP_MUST_OPTION(option_code) (option_code & 0x80) - - - -/* 56 + 20 = 76*/ -#define PCP_DSLITE_MAP_OPCODE_MIN_UDP_LEN \ - ( PCP_MAP_OPCODE_MIN_UDP_LEN + \ - PCP_3RD_PARTY_OPTION_SIZE) - -/* 60 + 20 = 80 */ -#define PCP_DSLITE_MAP_OPCODE_MAX_UDP_LEN \ - ( PCP_MAP_OPCODE_PREF_FAIL_OPTION_LEN + \ - PCP_3RD_PARTY_OPTION_SIZE) - -/* 76 + 20 = 96 */ -#define PCP_DSLITE_PEER_OPCODE_MIN_UDP_LEN \ - ( PCP_PEER_OPCODE_MIN_UDP_LEN + \ - PCP_3RD_PARTY_OPTION_SIZE) - - -#define PCP_SET_CNAT_PROTO(proto) \ - pcp_data.cnat_proto = (proto == TCP_PROT) ? CNAT_TCP: \ - (proto == UDP_PROT)? CNAT_UDP : CNAT_ICMP; - -#define PCP_SET_REQ_LIFETIME() \ - if(pcp_data.db->flags & CNAT_DB_FLAG_STATIC_PORT) { \ - pcp_data.db->proto_data.seq_pcp.pcp_lifetime = \ - PCP_STATIC_LIFETIME; \ - pcp_data.req_lifetime = PCP_STATIC_LIFETIME; \ - } else { \ - pcp_data.db->proto_data.seq_pcp.pcp_lifetime = \ - pcp_data.req_lifetime + cnat_current_time ; \ - } - - -/* per second not more than PCP_THROTTLE_LIMIT - * delete requests will be handled. - * this excludes , specific entries, in which - * only one entry needs to be deleted - */ -#define PCP_THROTTLE_LIMIT 2 - -typedef struct pcp_request { - u8 ver; - u8 r_opcode; - u16 reserved; - u32 req_lifetime; - u32 ip[4]; /* ipv4 will be represented - by the ipv4 mapped ipv6 */ -} pcp_request_t; - -typedef struct pcp_response { - u8 ver; - u8 r_opcode; - u8 reserved; - u8 result_code; - u32 lifetime; - u32 epochtime; - u32 reserved1[3]; -} pcp_response_t; - - -typedef struct pcp_options_hdr { - u8 code; - u8 reserved; - u16 len; - u8 data[0]; -} pcp_options_hdr_t; - - -/* same for both request and response */ -typedef struct pcp_map_option_specific_data { - u8 protocol; - u8 reserved[3]; - u16 int_port; - u16 ext_port; - u32 ext_ip[4]; /* ipv4 will be represnted - by the ipv4 mapped ipv6 */ -} pcp_map_option_specific_data_t; - -/* same for both request and response */ -typedef struct pcp_peer_option_specific_data { - u8 protocol; - u8 reserved[3]; - u16 int_port; - u16 ext_port; - u32 ext_ip[4]; /* ipv4 will be represented - by the ipv4 mapped ipv6 */ - u16 peer_port; - u16 reserved1; - u32 peer_ip[4]; -} pcp_peer_option_specific_data_t; - -typedef struct pcp_prefer_fail_option { - u8 option; - u8 reserved; - u16 len; -} pcp_prefer_fail_option_t; - - -typedef struct pcp_3rd_party_option{ - u8 option; - u8 reserved; - u16 len; - u32 ip[4]; -} pcp_3rd_party_option_t; - -/* structure used as pipeline data */ - -typedef struct pcp_pipeline_data { - - union { - - u8 *p; - ipv4_header *ip ; - ipv6_header_t *ipv6 ; - - } l3addr; - - udp_hdr_type_t *udp; - pcp_request_t *req; - pcp_response_t *resp; - pcp_opcode_t opcode; - u32 src_ip[4]; - u16 src_port; - u8 proto; - u16 i_vrf; - u16 o_vrf; - u32 ext_ip[4]; - u16 ext_port; - u32 third_party_ip[4]; - - /* valid for peer opcode */ - u32 peer_ip[4]; - u32 peer_port; - u32 req_lifetime; - u32 udp_len; - pcp_options_t pref_fail; - pcp_options_t third_party; - u8 *option_spec; - pcp_result_codes_t ret_code; - cnat_portmap_v2_t *pm; - cnat_main_db_entry_t *db; - cnat_vrfmap_t *vrfmap; - dslite_table_entry_t *inst_ptr; - u16 inst_id; - u32 flags; - u16 cnat_proto; - - /* is packet needs to be dropped ? */ - u8 drop; - /* nat44, dslite, nat64 */ -#define PCP_SERVICE_NAT44 1 -#define PCP_SERVICE_DSLITE 2 -#define PCP_SERVICE_NAT64 3 - u8 service_type; - -#define PCP_REQ_ENTRY_PRESENT 1 -#define PCP_REQ_EXT_MAP_PRESENT 1 - u8 state; -} pcp_pipeline_data_t; - -#endif /* __CNAT_PCP_sERVER_H__ */ diff --git a/plugins/plugins/vcgn/cnat_ports.c b/plugins/plugins/vcgn/cnat_ports.c deleted file mode 100644 index 943fb3ed..00000000 --- a/plugins/plugins/vcgn/cnat_ports.c +++ /dev/null @@ -1,1113 +0,0 @@ -/* - *------------------------------------------------------------------ - * cnat_ports.c - port allocator - * - * Copyright (c) 2008-2014 Cisco and/or its affiliates. - * 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 -#include -#include -#include -#include -#include -#include - -#include "cnat_db.h" -#include "cnat_config.h" -#include "cnat_global.h" -#include "cnat_logging.h" -#include "spp_timers.h" -#include "platform_common.h" -#include "cgn_bitmap.h" -#include "spp_platform_trace_log.h" -#include "cnat_ports.h" - -#if 1 /* TOBE_PORTED */ -/* Following is defined elsewhere. */ -#define msg_spp_err(s) \ -do { \ - fprintf(stderr,(i8 *)s); \ - fputs("\n", stderr); \ -} while(0); -#endif - - -#define PM_90_PERCENT_USE 58980 -/* - * instance number provisioned from HW - */ -u8 my_instance_number = 0; - -typedef struct { - u32 cached_next_index; - /* $$$$ add data here */ - - /* convenience variables */ - vlib_main_t * vlib_main; - vnet_main_t * vnet_main; -} cnat_ports_main_t; - -cnat_ports_main_t cnat_ports_main; - -static u32 rseed_port; /* random number generator seed */ - -void -cnat_db_dump_portmap_for_vrf (u32 vrfmap_index) -{ - u32 i, pm_len; - cnat_vrfmap_t *my_vrfmap = cnat_map_by_vrf + vrfmap_index; - cnat_portmap_v2_t *pm, *my_pm __attribute__((unused)); - - pm = my_vrfmap->portmap_list; - pm_len = vec_len(pm); - - for (i = 0; i < pm_len; i++) { - my_pm = pm + i; - - PLATFORM_DEBUG_PRINT("pm %d: IPv4 Addr 0x%x - in use %d private_ip_users_count %d\n", - i, my_pm->ipv4_address, my_pm->inuse, - my_pm->private_ip_users_count); - - PLATFORM_DEBUG_PRINT("pm %d: IPv4 Addr 0x%x - in use %d " - "private_ip_users_count %d\n", - i, my_pm->ipv4_address, my_pm->inuse, - my_pm->private_ip_users_count); - } -} - -void -cnat_db_dump_portmaps () -{ - u32 i, vrfmap_index; - - for (i = 0; i < CNAT_MAX_VRFMAP_ENTRIES; i++) { - vrfmap_index = vrf_map_array[i]; - - if (vrfmap_index == VRF_MAP_ENTRY_EMPTY) { - continue; - } - - PLATFORM_DEBUG_PRINT("\n\nDumping the port map for uidb_index %d\n", i); - cnat_db_dump_portmap_for_vrf(vrfmap_index); - } -} - -#ifndef NO_BULK_LOGGING -static int check_if_stat_alloc_ok_for_bulk(cnat_portmap_v2_t *pm, - u16 i_port, bulk_alloc_size_t bulk_size, - u16 static_port_range) -{ - uword bit_test_result; - if(BULK_ALLOC_SIZE_NONE == bulk_size) return 1; /* No issues */ - - if(i_port < static_port_range) return 1; /* we don't want bulk */ - - i_port = (i_port/bulk_size) * bulk_size; - bit_test_result = cgn_clib_bitmap_check_if_all(pm->bm, i_port, bulk_size); - return(bit_test_result); -} -#else /* dummy */ -inline static int check_if_stat_alloc_ok_for_bulk(cnat_portmap_v2_t *pm, - u16 i_port, bulk_alloc_size_t bulk_size, - u16 static_port_range) -{ - return 1; -} -#endif /* NO_BULK_LOGGING */ -/* - * cnat_port_alloc_static_v2 - * public ipv4 address/port allocator for Static Port commands - * tries to allocate same outside port as inside port - */ -cnat_errno_t -cnat_static_port_alloc_v2 ( - cnat_portmap_v2_t *pm, - port_alloc_t atype, - port_pair_t pair_type, - u32 i_ipv4_address, - u16 i_port, - u32 *index, - u32 *o_ipv4_address, - u16 *o_port, - u16 static_port_range -#ifndef NO_BULK_LOGGING - , bulk_alloc_size_t bulk_size, - int *nfv9_log_req -#endif - , u16 ip_n_to_1 - ) -{ - u32 i, hash_value, my_index, found, max_attempts; - u16 start_bit, new_port; - cnat_portmap_v2_t *my_pm = 0; - u32 pm_len = vec_len(pm); - uword bit_test_result; - -#ifndef NO_BULK_LOGGING - *nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED; -#endif - - if (PREDICT_FALSE(pm_len == 0)) { - return (CNAT_NO_POOL_ANY); - } - - switch (atype) { - - case PORT_ALLOC_ANY: - - found = 0; - - /* - * Try to hash the IPv4 address to get an index value to select the pm - */ - hash_value = (i_ipv4_address & 0xffff) ^ - ((i_ipv4_address > 16) & 0xffff); - - /* - * If pm_len <= 256, compact the hash to 8 bits - */ - if (PREDICT_TRUE(pm_len <= 256)) { - hash_value = (hash_value & 0xff) ^ ((hash_value > 8) & 0xff); - } - - /* - * Ensure that the hash value is in the range 0 .. (pm_len-1) - */ - my_index = hash_value % pm_len; - - for (i = 0; i < PORT_PROBE_LIMIT; i++) { - my_pm = pm + my_index; - if(PREDICT_TRUE(ip_n_to_1)) { - if(PREDICT_TRUE(my_pm->private_ip_users_count < ip_n_to_1)) { - /* - * Try to find a PM with atlest 33% free and my_port free - */ - if (PREDICT_TRUE((my_pm->inuse < ((BITS_PER_INST*2)/3)) && - clib_bitmap_get_no_check(my_pm->bm, - i_port) == 1) -#ifndef NO_BULK_LOGGING - && check_if_stat_alloc_ok_for_bulk(my_pm, i_port, - bulk_size, - static_port_range) -#endif - ) { - found = 1; - break; - } - } - - } else { - /* - * Try to find a PM with atlest 33% free and my_port free - */ - if (PREDICT_TRUE((my_pm->inuse < ((BITS_PER_INST*2)/3)) && - clib_bitmap_get_no_check(my_pm->bm, - i_port) == 1) -#ifndef NO_BULK_LOGGING - && check_if_stat_alloc_ok_for_bulk(my_pm, i_port, - bulk_size, - static_port_range) -#endif - ) { - found = 1; - break; - } - } - my_index = (my_index + 1) % pm_len; - } - - /* - * If not found do it the hard way . - * "hard" way, best-fit. - */ - if (!found) { - u32 min_inuse_any, min_inuse_myport; - u32 min_index_any, min_index_myport; - - min_inuse_any = min_inuse_myport = PORTS_PER_ADDR + 1; - min_index_any = min_index_myport = ~0; - for (i = 0; i < pm_len; i++) { - my_pm = pm + i; - if(PREDICT_TRUE(ip_n_to_1)) { - if(PREDICT_TRUE(my_pm->private_ip_users_count < ip_n_to_1)) { - if (PREDICT_FALSE(my_pm->inuse < min_inuse_any)) { - min_inuse_any = my_pm->inuse; - min_index_any = my_pm - pm; - } - if (PREDICT_FALSE(my_pm->inuse < min_inuse_myport)) { - if (PREDICT_TRUE(clib_bitmap_get_no_check( - my_pm->bm,i_port) == 1) -#ifndef NO_BULK_LOGGING - && check_if_stat_alloc_ok_for_bulk(my_pm, - i_port,bulk_size,static_port_range) -#endif - ) { - min_inuse_myport = my_pm->inuse; - min_index_myport = my_pm - pm; - } - } - - } - - } else { - if (PREDICT_FALSE(my_pm->inuse < min_inuse_any)) { - min_inuse_any = my_pm->inuse; - min_index_any = my_pm - pm; - } - if (PREDICT_FALSE(my_pm->inuse < min_inuse_myport)) { - if (PREDICT_TRUE(clib_bitmap_get_no_check( - my_pm->bm, i_port) == 1) -#ifndef NO_BULK_LOGGING - && check_if_stat_alloc_ok_for_bulk(my_pm, i_port, - bulk_size, static_port_range) -#endif - ) { - min_inuse_myport = my_pm->inuse; - min_index_myport = my_pm - pm; - } - } - } - } - - /* - * Check if we have an exactly matching PM that has - * myport free. If so use it. If no such PM is - * available, use any PM - */ - if (PREDICT_TRUE(min_inuse_myport < PORTS_PER_ADDR)) { - my_pm = pm + min_index_myport; - my_index = min_index_myport; - found = 1; - } else if (PREDICT_TRUE(min_inuse_any < PORTS_PER_ADDR)) { - my_pm = pm + min_index_any; - my_index = min_index_any; - found = 1; - } - } - - if (!found) { - return (CNAT_NO_PORT_ANY); - } - break; - - case PORT_ALLOC_DIRECTED: - my_index = *index; - if (PREDICT_FALSE(my_index > pm_len)) { - return (CNAT_INV_PORT_DIRECT); - } - my_pm = pm + my_index; - break; - - default: - return (CNAT_ERR_PARSER); - } - - /* Allocate a matching port if possible */ - start_bit = i_port; - found = 0; - max_attempts = BITS_PER_INST; -#ifndef NO_BULK_LOGGING - if((BULK_ALLOC_SIZE_NONE != bulk_size) && - (i_port >= static_port_range)) { - start_bit = (start_bit/bulk_size) * bulk_size; - max_attempts = BITS_PER_INST/bulk_size; - } -#endif /* NO_BULK_LOGGING */ - - for (i = 0; i < max_attempts; i++) { -#ifndef NO_BULK_LOGGING - if((BULK_ALLOC_SIZE_NONE != bulk_size) && - (i_port >= static_port_range)) { - bit_test_result = cgn_clib_bitmap_check_if_all(my_pm->bm, - start_bit, bulk_size); - } - else -#endif /* #ifndef NO_BULK_LOGGING */ - bit_test_result = clib_bitmap_get_no_check(my_pm->bm, start_bit); - - if (PREDICT_TRUE(bit_test_result)) { -#ifndef NO_BULK_LOGGING - if((BULK_ALLOC_SIZE_NONE != bulk_size) && - (i_port >= static_port_range)) { - *nfv9_log_req = start_bit; - if(i==0) new_port = i_port; /* First go */ - else { - new_port = bit2port(start_bit); - if (pair_type == PORT_S_ODD && (new_port & 0x1) == 0) - new_port++; - } - found = 1; - break; - } - else { -#endif /* NO_BULK_LOGGING */ - new_port = bit2port(start_bit); - if (pair_type == PORT_S_ODD) { - if ((new_port & 0x1) == 1) { - found = 1; - break; - } - } else if (pair_type == PORT_S_EVEN) { - if ((new_port & 0x1) == 0) { - found = 1; - break; - } - } else { - found = 1; - break; - } -#ifndef NO_BULK_LOGGING - } -#endif - } -#ifndef NO_BULK_LOGGING - if((BULK_ALLOC_SIZE_NONE != bulk_size) && - (i_port >= static_port_range)) - start_bit = (start_bit + bulk_size) % BITS_PER_INST; - else { -#endif /* NO_BULK_LOGGING */ - start_bit = (start_bit + 1) % BITS_PER_INST; - if(PREDICT_FALSE(start_bit == 0)) { - start_bit = 1; /* Port 0 is invalid, so start from 1 */ - } -#ifndef NO_BULK_LOGGING - } -#endif - } /* End of for loop */ - - if (!found) { - /* Port allocation failure */ - if (atype == PORT_ALLOC_DIRECTED) { - return (CNAT_NOT_FOUND_DIRECT); - } else { - return (CNAT_NOT_FOUND_ANY); - } - } - - /* Accounting */ - cgn_clib_bitmap_clear_no_check(my_pm->bm, new_port); - (my_pm->inuse)++; - - *index = my_pm - pm; - *o_ipv4_address = my_pm->ipv4_address; - - *o_port = new_port; - - return (CNAT_SUCCESS); -} - -/* - * Try to allocate a portmap structure based on atype field - */ -cnat_portmap_v2_t * -cnat_dynamic_addr_alloc_from_pm ( - cnat_portmap_v2_t *pm, - port_alloc_t atype, - u32 *index, - cnat_errno_t *err, - u16 ip_n_to_1, - u32 *rseed_ip) -{ - u32 i, pm_len; - int my_index; - int min_inuse, min_index; - - cnat_portmap_v2_t *my_pm = 0; - *err = CNAT_NO_POOL_ANY; - - pm_len = vec_len(pm); - - switch(atype) { - case PORT_ALLOC_ANY: - if (PREDICT_FALSE(pm_len == 0)) { - my_pm = 0; - *err = CNAT_NO_POOL_ANY; - goto done; - } - - /* "Easy" way, first address with at least 200 free ports */ - for (i = 0; i < PORT_PROBE_LIMIT; i++) { - *rseed_ip = randq1(*rseed_ip); - my_index = (*rseed_ip) % pm_len; - my_pm = pm + my_index; - if (PREDICT_FALSE(ip_n_to_1)) { - if(PREDICT_TRUE(ip_n_to_1 == 1)) { - if (PREDICT_FALSE(0 == my_pm->inuse)) { - goto done; - } - } else { - if(PREDICT_TRUE(my_pm->private_ip_users_count < ip_n_to_1)) { - if (PREDICT_FALSE(my_pm->inuse < ((BITS_PER_INST*2)/3))) { - goto done; - } - } - } - } else { - if (PREDICT_FALSE(my_pm->inuse < ((BITS_PER_INST*2)/3))) { - goto done; - } - } - } - - /* "hard" way, best-fit. $$$$ Throttle complaint */ - min_inuse = PORTS_PER_ADDR + 1; - min_index = ~0; - for (i = 0; i < pm_len; i++) { - my_pm = pm + i; - if (PREDICT_FALSE(ip_n_to_1)) { - if(PREDICT_TRUE(ip_n_to_1 == 1)) { - if (PREDICT_FALSE(!my_pm->inuse)) { - min_inuse = my_pm->inuse; - min_index = my_pm - pm; - } - } else { - if(PREDICT_TRUE(my_pm->private_ip_users_count < ip_n_to_1)) { - if (PREDICT_TRUE(my_pm->inuse < min_inuse)) { - min_inuse = my_pm->inuse; - min_index = my_pm - pm; - } - - } - } - - } else { - if (PREDICT_TRUE(my_pm->inuse < min_inuse)) { - min_inuse = my_pm->inuse; - min_index = my_pm - pm; - } - } - } - - if (PREDICT_TRUE(min_inuse < PORTS_PER_ADDR)) { - my_pm = pm + min_index; - my_index = min_index; - goto done; - } - - /* Completely out of ports */ -#ifdef DEBUG_PRINTF_ENABLED - PLATFORM_DEBUG_PRINT("%s out of ports\n", __FUNCTION__); -#endif - - my_pm = 0; - *err = CNAT_NO_PORT_ANY; - break; - - - case PORT_ALLOC_DIRECTED: - //ASSERT(*index < pm_len); - if (PREDICT_FALSE(*index > pm_len)) { - my_pm = 0; - *err = CNAT_INV_PORT_DIRECT; - goto done; - } - my_pm = pm + *index; - my_index = *index; - break; - - default: - msg_spp_err("bad allocation type in cnat_port_alloc"); - my_pm = 0; - *err = CNAT_ERR_PARSER; - break; - } - - done: - if (PREDICT_FALSE(my_pm == NULL)) { - return (my_pm); - } - - if (PREDICT_FALSE(my_pm->inuse >= BITS_PER_INST)) { - my_pm = 0; - if (atype == PORT_ALLOC_DIRECTED) { - *err = CNAT_BAD_INUSE_DIRECT; - } else { - *err = CNAT_BAD_INUSE_ANY; - } - } - - return (my_pm); -} - - -/* - * cnat_port_alloc_v2 - * public ipv4 address/port allocator for dynamic ports - * - * 200K users / 20M translations means vec_len(cnat_portmap) will be - * around 300. - * - */ -cnat_errno_t -cnat_dynamic_port_alloc_v2 ( - cnat_portmap_v2_t *pm, - port_alloc_t atype, - port_pair_t pair_type, - u32 *index, - u32 *o_ipv4_address, - u16 *o_port, - u16 static_port_range -#ifndef NO_BULK_LOGGING - , bulk_alloc_size_t bulk_size, - int *nfv9_log_req -#endif - , u16 ip_n_to_1, - u32 *rseed_ip - ) -{ - int i; - cnat_errno_t my_err = CNAT_NO_POOL_ANY; - cnat_portmap_v2_t *my_pm = 0; - u16 start_bit; - u16 new_port; - uword bit_test_result; - uword max_trys_to_find_port; - - ASSERT(index); - ASSERT(o_ipv4_address); - ASSERT(o_port); - - my_pm = cnat_dynamic_addr_alloc_from_pm(pm, atype, index, &my_err, ip_n_to_1, - rseed_ip); - - if (PREDICT_FALSE(my_pm == NULL)) { - return (my_err); - } - if(PREDICT_FALSE(my_pm->dyn_full == 1)) { - if (atype == PORT_ALLOC_DIRECTED) { - return (CNAT_NOT_FOUND_DIRECT); - } else { - return (CNAT_NOT_FOUND_ANY); - } - } - -#if DEBUG > 1 - PLATFORM_DEBUG_PRINT("ALLOC_PORT_V2: My_Instance_Number %d: IP addr 0x%x, Inuse %d\n", - my_instance_number, my_pm->ipv4_address, my_pm->inuse); -#endif - - rseed_port = randq1(rseed_port); - - /* - * Exclude the static port range for allocating dynamic ports - */ - start_bit = (rseed_port) % (BITS_PER_INST - static_port_range); - start_bit = start_bit + static_port_range; - -#ifndef NO_BULK_LOGGING - *nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED; - if(BULK_ALLOC_SIZE_NONE != bulk_size) - { - /* We need the start port of the range to be alined on integer multiple - * of bulk_size */ - max_trys_to_find_port = BITS_PER_INST/bulk_size; - start_bit= ((start_bit + bulk_size -1)/bulk_size) * bulk_size; - } - else -#endif /* #ifndef NO_BULK_LOGGING */ - max_trys_to_find_port = BITS_PER_INST; - - /* Allocate a random port / port-pair */ - for (i = 0; i < max_trys_to_find_port; i++) { - - /* start_bit is only a u16.. so it can rollover and become zero */ - if (PREDICT_FALSE( /* (start_bit >= BITS_PER_INST) || FIXME u16 cannot be >= 65536 */ - (start_bit < static_port_range))) { - start_bit = static_port_range; -#ifndef NO_BULK_LOGGING - if(BULK_ALLOC_SIZE_NONE != bulk_size) { - start_bit= ((start_bit + bulk_size -1)/bulk_size) * bulk_size; - } -#endif /* #ifndef NO_BULK_LOGGING */ - } - /* Scan forward from random position */ -#ifndef NO_BULK_LOGGING - if(BULK_ALLOC_SIZE_NONE != bulk_size) { - bit_test_result = cgn_clib_bitmap_check_if_all(my_pm->bm, - start_bit, bulk_size); - } - else -#endif /* #ifndef NO_BULK_LOGGING */ - bit_test_result = clib_bitmap_get_no_check(my_pm->bm, start_bit); - - if (PREDICT_TRUE(bit_test_result)) { - new_port = bit2port(start_bit); -#ifndef NO_BULK_LOGGING - if(BULK_ALLOC_SIZE_NONE != bulk_size) - *nfv9_log_req = new_port; -#endif - if ((pair_type == PORT_S_ODD) && - (!(new_port & 0x1))) { -#ifndef NO_BULK_LOGGING - if(BULK_ALLOC_SIZE_NONE != bulk_size) { - start_bit++; /* Just use the next one in the bulk range */ - new_port++; - goto found2; - } -#endif /* #ifndef NO_BULK_LOGGING */ - goto notfound; - } else if ((pair_type == PORT_S_EVEN) && - (new_port & 0x1)) { - goto notfound; - } - - /* OK we got one or two suitable ports */ - goto found2; - } - - notfound: -#ifndef NO_BULK_LOGGING - if(BULK_ALLOC_SIZE_NONE != bulk_size) - start_bit += bulk_size; - else -#endif /* #ifndef NO_BULK_LOGGING */ - start_bit++; - - } /* end of for loop */ - - /* Completely out of ports */ - - /* Port allocation failure */ - /* set dyn_full flag. This would be used to verify - * for further dyn session before searching for port - */ - if (atype == PORT_ALLOC_DIRECTED) { - my_pm->dyn_full = 1; - return (CNAT_NOT_FOUND_DIRECT); - } else { - my_pm->dyn_full = 1; - return (CNAT_NOT_FOUND_ANY); - } - - - found2: - - /* Accounting */ - cgn_clib_bitmap_clear_no_check (my_pm->bm, start_bit); - (my_pm->inuse)++; - - *index = my_pm - pm; - *o_ipv4_address = my_pm->ipv4_address; - - *o_port = new_port; - return (CNAT_SUCCESS); -} - -#ifdef TOBE_PORTED -/* - * cnat_alloc_port_from_pm - * Given a portmap structure find port/port_pair that are free - * - * The assumption in this function is that bit in bm corresponds - * to a port number. This is TRUE and hence there is no call - * to the function bit2port here, though it is done in other - * places in this file. - * - */ -static u32 -cnat_alloc_port_from_pm ( - u32 start_port, - u32 end_port, - cnat_portmap_v2_t *my_pm, - port_pair_t pair_type -#ifndef NO_BULK_LOGGING - , bulk_alloc_size_t bulk_size, - int *nfv9_log_req -#endif /* #ifnded NO_BULK_ALLOCATION */ - ) -{ - u32 i; - u32 start_bit; - u32 total_ports = end_port - start_port + 1; - uword bit_test_result; - uword max_trys_to_find_port; - - rseed_port = randq1(rseed_port); - - start_bit = rseed_port % total_ports; - start_bit = start_bit + start_port; -#ifndef NO_BULK_LOGGING - *nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED; - if(BULK_ALLOC_SIZE_NONE != bulk_size) - { - /* We need the start port of the range to be alined on integer multiple - * of bulk_size */ - max_trys_to_find_port = total_ports/bulk_size; - start_bit= ((start_bit + bulk_size -1)/bulk_size) * bulk_size; - } - else -#endif /* #ifndef NO_BULK_LOGGING */ - max_trys_to_find_port = total_ports; - - /* Allocate a random port / port-pair */ - for (i = 0; i < max_trys_to_find_port; i++) { - /* start_bit is only a u16.. so it can rollover and become zero */ - if (PREDICT_FALSE((start_bit >= end_port) || - (start_bit < start_port))) { - start_bit = start_port; -#ifndef NO_BULK_LOGGING - if(BULK_ALLOC_SIZE_NONE != bulk_size) { - start_bit= ((start_bit + bulk_size -1)/bulk_size) * bulk_size; - } -#endif /* #ifndef NO_BULK_LOGGING */ - } - - /* Scan forward from random position */ -#ifndef NO_BULK_LOGGING - if(BULK_ALLOC_SIZE_NONE != bulk_size) { - bit_test_result = cgn_clib_bitmap_check_if_all(my_pm->bm, - start_bit, bulk_size); - } - else -#endif /* #ifndef NO_BULK_LOGGING */ - bit_test_result = clib_bitmap_get_no_check(my_pm->bm, start_bit); - - if (PREDICT_TRUE(bit_test_result)) { -#ifndef NO_BULK_LOGGING - if(BULK_ALLOC_SIZE_NONE != bulk_size) { - /* Got the entire bulk range */ - *nfv9_log_req = bit2port(start_bit); - return start_bit; - } else { -#endif /* #ifndef NO_BULK_LOGGING */ - /* - * For PORT_PAIR, first port has to be Even - * subsequent port <= end_port - * subsequent port should be unallocated - */ - if ((start_bit & 0x1) || - ((start_bit + 1) > end_port) || - (clib_bitmap_get_no_check(my_pm->bm, - (start_bit + 1)) == 0)) { - goto notfound; - } - return (start_bit); -#ifndef NO_BULK_LOGGING - } -#endif /* #ifndef NO_BULK_LOGGING */ - } /* if( free port found ) */ - -notfound: -#ifndef NO_BULK_LOGGING - if(BULK_ALLOC_SIZE_NONE != bulk_size) { - start_bit += bulk_size; - } else -#endif /* #ifndef NO_BULK_LOGGING */ - start_bit++; - - } - return (BITS_PER_INST); -} - -/* - * cnat_dynamic_port_alloc_rtsp - * public ipv4 address/port allocator for dynamic ports - * - * 200K users / 20M translations means vec_len(cnat_portmap) will be - * around 300. - * - */ - -cnat_errno_t -cnat_dynamic_port_alloc_rtsp ( - cnat_portmap_v2_t *pm, - port_alloc_t atype, - port_pair_t pair_type, - u16 start_range, - u16 end_range, - u32 *index, - u32 *o_ipv4_address, - u16 *o_port -#ifndef NO_BULK_LOGGING - , bulk_alloc_size_t bulk_size, - int *nfv9_log_req -#endif - , u32 *rseed_ip - ) -{ - - u32 current_timestamp; - cnat_errno_t my_err = CNAT_NO_POOL_ANY; - cnat_portmap_v2_t *my_pm = 0; - u32 alloc_bit; - - ASSERT(index); - ASSERT(o_ipv4_address); - ASSERT(o_port); - - my_pm = cnat_dynamic_addr_alloc_from_pm(pm, atype, index, &my_err, 0,rseed_ip); - - if (PREDICT_FALSE(my_pm == NULL)) { - return (my_err); - } - -#if DEBUG > 1 - PLATFORM_DEBUG_PRINT("ALLOC_PORT_V2: My_Instance_Number %d: IP addr 0x%x, Inuse %d\n", - my_instance_number, my_pm->ipv4_address, my_pm->inuse); -#endif - - alloc_bit = - cnat_alloc_port_from_pm(start_range, end_range, my_pm, pair_type -#ifndef NO_BULK_LOGGING - , bulk_size, nfv9_log_req -#endif /* #ifndef NO_BULK_LOGGING */ - ); - - if (alloc_bit < BITS_PER_INST) { - if (pair_type == PORT_PAIR) { - /* Accounting */ - cgn_clib_bitmap_clear_no_check (my_pm->bm, alloc_bit); - cgn_clib_bitmap_clear_no_check (my_pm->bm, alloc_bit+1); - (my_pm->inuse) += 2; - } else { - /* Accounting */ - cgn_clib_bitmap_clear_no_check (my_pm->bm, alloc_bit); - (my_pm->inuse)++; - } - - *index = my_pm - pm; - *o_ipv4_address = my_pm->ipv4_address; - - *o_port = bit2port(alloc_bit);; - - return (CNAT_SUCCESS); - } - - /* Completely out of ports */ - current_timestamp = spp_trace_log_get_unix_time_in_seconds(); - if (PREDICT_FALSE((current_timestamp - my_pm->last_sent_timestamp) > - 1000)) { - spp_printf(CNAT_NO_EXT_PORT_AVAILABLE, 0, NULL); - my_pm->last_sent_timestamp = current_timestamp; - } - - - /* Port allocation failure */ - if (atype == PORT_ALLOC_DIRECTED) { - return (CNAT_NOT_FOUND_DIRECT); - } else { - return (CNAT_NOT_FOUND_ANY); - } -} -#else -cnat_errno_t -cnat_dynamic_port_alloc_rtsp ( - cnat_portmap_v2_t *pm, - port_alloc_t atype, - port_pair_t pair_type, - u16 start_range, - u16 end_range, - u32 *index, - u32 *o_ipv4_address, - u16 *o_port -#ifndef NO_BULK_LOGGING - , bulk_alloc_size_t bulk_size, - int *nfv9_log_req -#endif - , u32 *rseed_ip - ) -{ - return (CNAT_NOT_FOUND_ANY); -} -#endif - - -/* - * cnat_mapped_static_port_alloc_v2 - * / - */ -cnat_errno_t -cnat_mapped_static_port_alloc_v2 ( - cnat_portmap_v2_t *pm, - port_alloc_t atype, - u32 *index, - u32 ipv4_address, - u16 port -#ifndef NO_BULK_LOGGING - , int *nfv9_log_req, - bulk_alloc_size_t bulk_size -#endif - , u16 ip_n_to_1 - ) -{ - int i; - u32 pm_len; - u16 bm_bit; - cnat_portmap_v2_t *my_pm = 0; - u32 my_index; - - ASSERT(index); - - /* - * Map the port to the bit in the pm bitmap structure. - * Note that we use ports from 1024..65535, so - * port number x corresponds to (x-1024) position in bitmap - */ - bm_bit = port2bit(port); - - pm_len = vec_len(pm); - - switch(atype) { - case PORT_ALLOC_ANY: - if (PREDICT_FALSE(pm_len == 0)) { - return (CNAT_NO_POOL_ANY); - } - - /* - * Find the pm that is allocated for this translated IP address - */ - my_index = pm_len; - - for (i = 0; i < pm_len; i++) { - my_pm = pm + i; - if (PREDICT_FALSE(my_pm->ipv4_address == ipv4_address)) { - my_index = i; - break; - } - } - - if ((PREDICT_FALSE(my_index >= pm_len)) || - ((PREDICT_FALSE(ip_n_to_1)) && (PREDICT_TRUE(my_pm->private_ip_users_count >= ip_n_to_1)))) { - return (CNAT_NO_POOL_ANY); - } - - break; - - case PORT_ALLOC_DIRECTED: - if (PREDICT_FALSE(*index > pm_len)) { - return (CNAT_INV_PORT_DIRECT); - } - - my_index = *index; - my_pm = pm + my_index; - if (PREDICT_FALSE(my_pm->ipv4_address != ipv4_address)) { - if (PREDICT_FALSE(global_debug_flag && CNAT_DEBUG_GLOBAL_ALL)) { - PLATFORM_DEBUG_PRINT("Delete all main db entry for that particular in ipv4 address\n"); - } - return (CNAT_INV_PORT_DIRECT); - } - - break; - - default: - msg_spp_err("bad allocation type in cnat_port_alloc"); - return (CNAT_ERR_PARSER); - } - - - if (PREDICT_FALSE(my_pm == NULL)) { - return (CNAT_NO_POOL_ANY); - } - - /* - * Check if the port is already allocated to some other mapping - */ - if (PREDICT_FALSE(clib_bitmap_get_no_check (my_pm->bm, bm_bit) == 0)) { - return (CNAT_NO_POOL_ANY); - } - -#if DEBUG > 1 - PLATFORM_DEBUG_PRINT("ALLOC_PORT_V2: My_Instance_Number %d: IP addr 0x%x, Inuse %d\n", - my_instance_number, my_pm->ipv4_address, my_pm->inuse); -#endif - - /* - * Indicate that the port is already allocated - */ - cgn_clib_bitmap_clear_no_check (my_pm->bm, bm_bit); - (my_pm->inuse)++; - - *index = my_index; - - return (CNAT_SUCCESS); -} - -void cnat_port_free_v2 ( - cnat_portmap_v2_t *pm, - int index, - port_pair_t pair_type, - u16 base_port, - u16 static_port_range) -{ - cnat_portmap_v2_t *my_pm; - uword bit; - - /* check for valid portmap */ - if (PREDICT_FALSE(index > vec_len(pm))) { - spp_printf(CNAT_INVALID_INDEX_TO_FREE_PORT, 0, 0); - return; - } - - my_pm = pm + index; - bit = port2bit(base_port); - -#if DEBUG > 0 - if(clib_bitmap_get_no_check(my_pm->bm, bit)) - ASSERT(clib_bitmap_get_no_check(my_pm->bm, bit) == 0); -#endif - - cgn_clib_bitmap_set_no_check(my_pm->bm, bit); - - my_pm->inuse -= 1; - if(base_port >= static_port_range) { - /* Clear the full flag. we can have a new dynamic session now */ - my_pm->dyn_full = 0; - } - - return; -} - -void cnat_portmap_dump_v2 (cnat_portmap_v2_t *pm, u16 print_limit) -{ - int i; - u32 inuse =0; - - ASSERT(pm); - - for (i = 0; i < BITS_PER_INST; i++) { - if (PREDICT_FALSE(clib_bitmap_get_no_check (pm->bm, i) == 0)) { - if (PREDICT_TRUE(inuse++ < print_limit)) - PLATFORM_DEBUG_PRINT(" %d", bit2port(i)); - } - } - if (PREDICT_FALSE(inuse >= print_limit)) { - PLATFORM_DEBUG_PRINT("%d printed, print limit is %d\n", - inuse, print_limit); - } - PLATFORM_DEBUG_PRINT("\n"); -} - - -/* - * cnat_ports_init - */ -clib_error_t *cnat_ports_init(vlib_main_t *vm) -{ - cnat_ports_main_t *mp = &cnat_ports_main; - - mp->vlib_main = vm; - mp->vnet_main = vnet_get_main(); - - /* suppress crypto-random port numbering */ -#ifdef SOON - if (spp_get_int_prop("no_crypto_random_ports") == 0) - crypto_random32(&seed); -#endif - - return 0; -} - -VLIB_INIT_FUNCTION(cnat_ports_init); - diff --git a/plugins/plugins/vcgn/cnat_ports.h b/plugins/plugins/vcgn/cnat_ports.h deleted file mode 100644 index bc1fb0d2..00000000 --- a/plugins/plugins/vcgn/cnat_ports.h +++ /dev/null @@ -1,208 +0,0 @@ -/* - *------------------------------------------------------------------ - * cnat_ports.h - port database definitions - * - * Copyright (c) 2007-2013 Cisco and/or its affiliates. - * 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 __CNAT_PORTS_H__ -#define __CNAT_PORTS_H__ - -#include "platform_common.h" -#include "cnat_bulk_port_defs.h" - -#define PORTS_PER_ADDR 65536 - -#define CNAT_INSTS PLATFORM_CNAT_INSTS - -#define BITS_PER_INST (PORTS_PER_ADDR) - -/* - * Ensure that atleast few 4 bit ports are available for RTSP - * in case we want to map 4 digit inside ports to 4 digit outside ports - */ -#define MIN_STATIC_PORT_RANGE_FOR_RTSP (9900) - -extern u8 my_instance_number; - -/* - * Now it is a 1-to-1 mapping between bit and port values - */ -static inline u16 bit2port (u32 bit) -{ - return bit; -} - -static inline uword port2bit (u16 port) -{ - return port; -} - -/* - * Port bitmap structure - * THIS structure is not used to be REMOVED.... - */ - - -typedef struct { - u32 ipv4_address; /* native bit order */ - u16 vrf; - u16 pad; - u32 threshold_crossed; - uword bm[(BITS_PER_INST + BITS(uword)-1)/BITS(uword)]; -} cnat_portmap_t; - -//cnat_portmap_t *cnat_portmap; - - -typedef struct { - u32 inuse; - u32 delete_time; - u32 ipv4_address; /* native bit order */ - u32 last_sent_timestamp; - uword bm[(BITS_PER_INST + BITS(uword)-1)/BITS(uword)]; - u32 dyn_full; - u32 private_ip_users_count; /* number of private ip's(subscribers) to this - public ip */ -} cnat_portmap_v2_t; - - -typedef enum { - PORT_SINGLE=0, - PORT_PAIR=1, - PORT_S_EVEN=2, - PORT_S_ODD=3, -} port_pair_t; - -typedef enum { - PORT_TYPE_DYNAMIC=0, - PORT_TYPE_STATIC=1, - PORT_TYPE_RTSP=2, -} port_type_t; - - -typedef enum { - PORT_ALLOC_ANY=1, - PORT_ALLOC_DIRECTED=2, -} port_alloc_t; - -#define PORT_PROBE_LIMIT 20 - - -/* - * randq1 - * Linear congruential random number generator with - * extensively studied properties. See Numerical Recipes in C - * 2nd Ed. page 284. Known to behave according to the test vector - * supplied in the text, on X86 and Octeon. - */ -static inline u32 randq1 (u32 prev) -{ - return (1664525L*prev + 1013904223L); -} - -cnat_errno_t -cnat_static_port_alloc_v2( - cnat_portmap_v2_t *pm, - port_alloc_t atype, - port_pair_t pair_type, - u32 i_ipv4_address, - u16 i_port, - u32 *index, - u32 *o_ipv4_address, - u16 *o_port, - u16 static_port_range -#ifndef NO_BULK_LOGGING - , bulk_alloc_size_t bulk_size, - int *nfv9_log_req -#endif /* NO_BULK_LOGGING */ - , u16 ip_n_to_1 - ); - -cnat_errno_t -cnat_mapped_static_port_alloc_v2 ( - cnat_portmap_v2_t *pm, - port_alloc_t atype, - u32 *index, - u32 ipv4_address, - u16 port -#ifndef NO_BULK_LOGGING - , int *nfv9_log_req, - bulk_alloc_size_t bulk_size -#endif - , u16 ip_n_to_1 - ); - -cnat_errno_t -cnat_dynamic_port_alloc_v2( - cnat_portmap_v2_t *pm, - port_alloc_t atype, - port_pair_t pair_type, - u32 *index, - u32 *o_ipv4_address, - u16 *o_port, - u16 static_port_range -#ifndef NO_BULK_LOGGING - , bulk_alloc_size_t bulk_size, - int *nfv9_log_req -#endif - , u16 ip_n_to_1, - u32 *rseed_ip - ); - - -cnat_errno_t -cnat_dynamic_port_alloc_rtsp ( - cnat_portmap_v2_t *pm, - port_alloc_t atype, - port_pair_t pair_type, - u16 start_range, - u16 end_range, - u32 *index, - u32 *o_ipv4_address, - u16 *o_port -#ifndef NO_BULK_LOGGING - , bulk_alloc_size_t bulk_size, - int *nfv9_log_req -#endif - , u32 *rseed_ip - ); - -void cnat_port_free_v2( - cnat_portmap_v2_t *pm, - int index, - port_pair_t ptype, - u16 base_port, - u16 static_port_range); - -void cnat_portmap_dump_v2(cnat_portmap_v2_t *pm, - u16 print_limit); - - - -cnat_errno_t -nat64_static_port_alloc ( - cnat_portmap_v2_t *pm, - port_alloc_t atype, - port_pair_t pair_type, - u32 *i_ipv6_address, - u16 i_port, - u32 *index, - u32 *o_ipv4_address, - u16 *o_port); - - - -#endif /* __CNAT_PORTS_H__ */ diff --git a/plugins/plugins/vcgn/cnat_show.c b/plugins/plugins/vcgn/cnat_show.c deleted file mode 100644 index 68c52756..00000000 --- a/plugins/plugins/vcgn/cnat_show.c +++ /dev/null @@ -1,810 +0,0 @@ -/* - *------------------------------------------------------------------ - * cnat_show.c - translation database definitions - * - * Copyright (c) 2007-2014 Cisco and/or its affiliates. - * 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 -#include -#include -#include -#include -#include -#include - -#include "cnat_db.h" -#include "cnat_config.h" -#include "cnat_global.h" -#include "cnat_logging.h" -#include "spp_ctx.h" -#include "spp_timers.h" -#include "platform_common.h" -#include "cnat_syslog.h" -#include "cnat_v4_pptp_alg.h" -#include "platform_common.h" - -#ifndef TOBE_PORTED -/* The following variable is in cnat_config_msg_handler.c which - * is to be ported later.. if required - */ -u32 total_address_pool_allocated = 0; -#endif - -#ifndef NO_BULK_LOGGING -#define CNAT_MY_VRFMAP_PRINT \ -PLATFORM_DEBUG_PRINT("i-uidx 0x%x o-uidx 0x%x i-vrfid 0x%x o-vrfid 0x%x\n" \ - "status %d del time 0x%x tcp mss 0x%x pm list 0x%x\n" \ - "bulk size %d\n" \ - "ip n:1 %d\n" \ - "NFV9 template index 0x%x\n" \ - "SYSLOG template index 0x%x\n" \ - "Netflow Session Logging %d \n" \ - "Syslog Session Logging %d \n" \ - "PCP Server 0x%x, Port %u \n", \ - my_vrfmap->i_vrf, my_vrfmap->o_vrf, my_vrfmap->i_vrf_id, \ - my_vrfmap->o_vrf_id, my_vrfmap->status, my_vrfmap->delete_time, \ - my_vrfmap->tcp_mss, my_vrfmap->portmap_list, \ - BULKSIZE_FROM_VRFMAP(my_vrfmap), \ - my_vrfmap->ip_n_to_1, \ - my_vrfmap->nfv9_logging_index, \ - my_vrfmap->syslog_logging_index,\ - my_vrfmap->nf_logging_policy, \ - my_vrfmap->syslog_logging_policy, \ - my_vrfmap->pcp_server_addr, \ - my_vrfmap->pcp_server_port); -#else -#define CNAT_MY_VRFMAP_PRINT \ -PLATFORM_DEBUG_PRINT("i-uidx 0x%x o-uidx 0x%x i-vrfid 0x%x o-vrfid 0x%x\n" \ - "status %d del time 0x%x tcp mss 0x%x pm list 0x%x\n" \ - "NFV9 template index 0x%x\n ip n:1 %d\n", \ - my_vrfmap->i_vrf, my_vrfmap->o_vrf, my_vrfmap->i_vrf_id, \ - my_vrfmap->o_vrf_id, my_vrfmap->status, my_vrfmap->delete_time, \ - my_vrfmap->tcp_mss, my_vrfmap->portmap_list, \ - my_vrfmap->nfv9_logging_index, my_vrfmap->ip_n_to_1); -#endif /* NO_BULK_LOGGING */ - -#define CNAT_MY_LOGGING_INFO_PRINT \ -do { \ - cnat_syslog_logging_info_t *my_syslog_info = 0; \ - PLATFORM_DEBUG_PRINT("SYSLOG config: \n"); \ - pool_foreach (my_syslog_info, cnat_syslog_logging_info_pool, ({ \ - if (my_syslog_info->i_vrf == my_vrfmap->i_vrf) { \ - PLATFORM_DEBUG_PRINT(" \ - ipv4[0x%x], port[%u], hostname[%s]\n", \ - my_syslog_info->ipv4_address, my_syslog_info->port, \ - my_syslog_info->header_hostname); \ - break; \ - } \ - })); \ -}while (0) \ -; - - -void printf_ipv4(u32 ad) -{ - u8 a __attribute__((unused)), b __attribute__((unused)), - c __attribute__((unused)), d __attribute__((unused)); - - a = ad>>24; - b = (ad>>16) & 0xFF; - c = (ad>>8) & 0xFF; - d = (ad>>0) & 0xFF; - - PLATFORM_DEBUG_PRINT("%d.%d.%d.%d", a, b, c, d); -} -void cnat_main_db_entry_dump (cnat_main_db_entry_t *db) -{ - PLATFORM_DEBUG_PRINT("Main DB entry at %p, index %ld dst_ip %x\n", - db, db - cnat_main_db, db->dst_ipv4); - /* only dump hash next index if it's non EMPTY */ - if (db->out2in_hash.next != EMPTY || db->in2out_hash.next != EMPTY) - PLATFORM_DEBUG_PRINT("out2in hash %u, in2out hash %u\n", - db->out2in_hash.next, - db->in2out_hash.next); - PLATFORM_DEBUG_PRINT("out2in key ipv4 0x%08X, port 0x%04X (%5d), vrf %d, protocol %s\n", - db->out2in_key.k.ipv4, - db->out2in_key.k.port, - db->out2in_key.k.port, - db->out2in_key.k.vrf & CNAT_VRF_MASK, - (db->out2in_key.k.vrf & CNAT_PRO_MASK) == CNAT_UDP ? "UDP" : - ((db->in2out_key.k.vrf & CNAT_PRO_MASK) == CNAT_TCP ? "TCP" : - ((db->in2out_key.k.vrf & CNAT_PRO_MASK) == CNAT_ICMP ? "ICMP" : "PPTP ALG"))); - - PLATFORM_DEBUG_PRINT("in2out key ipv4 0x%08X, port 0x%04X (%5d), vrf %d, protocol %s\n", - db->in2out_key.k.ipv4, - db->in2out_key.k.port, - db->in2out_key.k.port, - db->in2out_key.k.vrf & CNAT_VRF_MASK, - (db->in2out_key.k.vrf & CNAT_PRO_MASK) == CNAT_UDP ? "UDP" : - ((db->in2out_key.k.vrf & CNAT_PRO_MASK) == CNAT_TCP ? "TCP" : - ((db->in2out_key.k.vrf & CNAT_PRO_MASK) == CNAT_ICMP ? "ICMP" : "UNKNOWN"))); - - PLATFORM_DEBUG_PRINT("user %d, user ports (nxt) %d (prev) %d, vrfmap_index 0x%x\n", - db->user_index, db->user_ports.next, db->user_ports.prev, - db->vrfmap_index); - PLATFORM_DEBUG_PRINT("timeout %d \n", db->timeout); - PLATFORM_DEBUG_PRINT("flags 0x%x ", db->flags); - - if (db->flags & CNAT_DB_FLAG_TCP_ACTIVE) { - PLATFORM_DEBUG_PRINT(" TCP_ACTIVE "); - } else if (db->flags & CNAT_DB_FLAG_UDP_ACTIVE) { - PLATFORM_DEBUG_PRINT(" UDP_ACTIVE "); - } else if (db->flags & CNAT_DB_FLAG_STATIC_PORT) { - PLATFORM_DEBUG_PRINT(" STATIC_PORT "); - } - - PLATFORM_DEBUG_PRINT(" ALG dlt0 0x%02X dlt1 0x%02X\n", db->alg.alg_dlt[0], db->alg.alg_dlt[1]); - PLATFORM_DEBUG_PRINT("\n"); - - PLATFORM_DEBUG_PRINT("out2in_pkts: %u\n", db->out2in_pkts); - PLATFORM_DEBUG_PRINT("in2out_pkts: %u\n", db->in2out_pkts); - PLATFORM_DEBUG_PRINT("entry_expires: %u current time: %u\n", db->entry_expires, cnat_current_time); - PLATFORM_DEBUG_PRINT("-------------------------\n"); -} - -void cnat_user_db_entry_dump (cnat_user_db_entry_t *up) -{ - u32 db_entry_index, first_db_entry_index; - cnat_main_db_entry_t *ep; - - PLATFORM_DEBUG_PRINT("User DB entry at %p, index %ld\n", - up, up - cnat_user_db); - PLATFORM_DEBUG_PRINT("translation list head index %u, %u translations portmapindex 0x%x\n", - up->translation_list_head_index, - up->ntranslations, up->portmap_index); - PLATFORM_DEBUG_PRINT("source ipv4 0x%x, source port 0x%x, vrf %d\n", - up->key.k.ipv4, - up->key.k.port, - up->key.k.vrf); - first_db_entry_index = db_entry_index = up->translation_list_head_index; - if (first_db_entry_index != EMPTY) { - PLATFORM_DEBUG_PRINT("Port translation list:\n"); - do { - PLATFORM_DEBUG_PRINT(" [%d]\n", db_entry_index); - ep = cnat_main_db + db_entry_index; - db_entry_index = ep->user_ports.next; - } while (first_db_entry_index != db_entry_index); - } else { - PLATFORM_DEBUG_PRINT("WARNING: empty translation list!\n"); - } - PLATFORM_DEBUG_PRINT("-------------------------\n"); -} - -void cnat_user_db_entry_dump_summary (cnat_user_db_entry_t *up) -{ - u32 db_entry_index, first_db_entry_index; - u32 total_entries = 0; - - PLATFORM_DEBUG_PRINT("User DB entry at %p, index %ld\n", - up, up - cnat_user_db); - PLATFORM_DEBUG_PRINT("translation list head index %u, %u translations portmapindex 0x%x\n", - up->translation_list_head_index, - up->ntranslations, up->portmap_index); - PLATFORM_DEBUG_PRINT("source ipv4 0x%x, source port 0x%x, vrf %d\n", - up->key.k.ipv4, - up->key.k.port, - up->key.k.vrf); - first_db_entry_index = db_entry_index = up->translation_list_head_index; - if (first_db_entry_index != EMPTY) { - PLATFORM_DEBUG_PRINT("Port translation list:\n"); - do { - total_entries++; - } while (first_db_entry_index != db_entry_index); - PLATFORM_DEBUG_PRINT("TOTAL_ENTRIES: %d\n", total_entries); - } else { - PLATFORM_DEBUG_PRINT("WARNING: empty translation list!\n"); - } - PLATFORM_DEBUG_PRINT("-------------------------\n"); -} - -/* for internal development and UT only */ -void cnat_db_dump_main_by_index (int argc, unsigned long *argv) -{ - u32 index, i, len; - u32 active_count, scan_count; - - if (argc != 1) { - PLATFORM_DEBUG_PRINT("invalid input %d\n", argc); - return; - } - - index = argv[0]; - - len = vec_len(cnat_main_db); - - active_count = pool_elts(cnat_main_db); - - if (index >= active_count) { - PLATFORM_DEBUG_PRINT("Index %u >= total active entries %u\n", index, active_count); - return; - } - - scan_count = 0; - for (i=0; i< len; i++) { - if(pool_is_free_index(cnat_main_db, i)) continue; - - if (index == scan_count) { - cnat_main_db_entry_dump(cnat_main_db + i); - break; - } - scan_count++; - } -} - -void cnat_db_dump_main (int argc, unsigned long *argv) -{ - cnat_main_db_entry_t *db; - - pool_foreach(db, cnat_main_db, ({ - cnat_main_db_entry_dump(db); - })); -} - -void cnat_db_dump_main_summary (int argc, unsigned long *argv) -{ - cnat_main_db_entry_t *db; - u32 num_entries = 0; - - pool_foreach(db, cnat_main_db, ({ - num_entries++; - })); - - PLATFORM_DEBUG_PRINT("\nNum main entries %d\n", num_entries); -} - -void cnat_db_dump_user (int argc, unsigned long *argv) -{ - cnat_user_db_entry_t *up; - - pool_foreach(up, cnat_user_db, ({ - cnat_user_db_entry_dump(up); - })); -} - -void cnat_db_dump_user_summary (int argc, unsigned long *argv) -{ - cnat_user_db_entry_t *up; - - pool_foreach(up, cnat_user_db, ({ - cnat_user_db_entry_dump_summary(up); - })); -} - -void cnat_db_dump_hashes (int argc, unsigned long *argv) -{ - int i; - - PLATFORM_DEBUG_PRINT("Main DB out2in hash:\n"); - for (i = 0; i < vec_len(cnat_out2in_hash); i++) { - if (cnat_out2in_hash[i].next != EMPTY) { - PLATFORM_DEBUG_PRINT("[%d]: %u\n", i, cnat_out2in_hash[i].next); - } - } - PLATFORM_DEBUG_PRINT("Main DB in2out hash:\n"); - for (i = 0; i < vec_len(cnat_in2out_hash); i++) { - if (cnat_in2out_hash[i].next != EMPTY) { - PLATFORM_DEBUG_PRINT("[%d]: %u\n", i, cnat_in2out_hash[i].next); - } - } - - PLATFORM_DEBUG_PRINT("User hash:\n"); - for (i = 0; i < vec_len(cnat_user_hash); i++) { - if (cnat_user_hash[i].next != EMPTY) { - PLATFORM_DEBUG_PRINT("[%d]: %u\n", i, cnat_user_hash[i].next); - } - } - PLATFORM_DEBUG_PRINT("-------------------------\n"); -} - - -#ifdef OLD_VRFMAP - -void cnat_db_dump_cdb (int argc, unsigned long *argv) -{ - int k; - int verbose=0; - int all = 0; - - if (argc > 0) { - verbose = 1; - } - - if (argc > 1) { - all = 1; - } - - PLATFORM_DEBUG_PRINT ("%d vrfmap vectors \n", vec_len(cnat_portmap_by_vrf)); - - for (k = 0; k < vec_len(cnat_portmap_by_vrf); k++) { - PLATFORM_DEBUG_PRINT("index%d: status %d i_vrf 0x%x o_vrf 0x%x\n", k, - cnat_portmap_by_vrf[k].status, - cnat_portmap_by_vrf[k].i_vrf, - cnat_portmap_by_vrf[k].o_vrf); - cnat_db_dump_address_portmap(verbose, all, - cnat_portmaps[k], - cnat_portmaps_inuse[k]); - } -} - -void cnat_db_dump_i_vrf (int argc, unsigned long *argv) -{ - u32 k; - u32 vrf =0; - int verbose=0; - int all = 0; - - if (!argc) { - PLATFORM_DEBUG_PRINT("need vrf input ,return\n"); - return; - } - - if (argc > 0) { - vrf = argv[0]; - } - - if (argc > 1) { - verbose = 1; - } - - if (argc > 2) { - all = 1; - } - - PLATFORM_DEBUG_PRINT ("%d vrfmap vectors \n", vec_len(cnat_portmap_by_vrf)); - - for (k = 0; k < vec_len(cnat_portmap_by_vrf); k++) { - if (cnat_portmap_by_vrf[k].i_vrf == vrf) { - PLATFORM_DEBUG_PRINT("%d: i_vrf 0x%x o_vrf 0x%x\n", k, - cnat_portmap_by_vrf[k].i_vrf, - cnat_portmap_by_vrf[k].o_vrf); - cnat_db_dump_address_portmap(verbose, all, - cnat_portmaps[k], - cnat_portmaps_inuse[k]); - return; - } - } - PLATFORM_DEBUG_PRINT("not found\n"); -} - -void cnat_db_dump_o_vrf (int argc, unsigned long *argv) -{ - u32 k; - int verbose=0; - int all = 0; - u32 vrf =0; - - if (!argc) { - PLATFORM_DEBUG_PRINT("need vrf input ,return\n"); - return; - } - - if (argc > 0) { - vrf = argv[0]; - } - - if (argc > 1) { - verbose = 1; - } - - if (argc > 2) { - all = 1; - } - - PLATFORM_DEBUG_PRINT ("%d vrfmap vectors \n", vec_len(cnat_portmap_by_vrf)); - - for (k = 0; k < vec_len(cnat_portmap_by_vrf); k++) { - if (cnat_portmap_by_vrf[k].o_vrf == vrf) { - PLATFORM_DEBUG_PRINT("index%d: status %d i_vrf 0x%x o_vrf 0x%x\n", k, - cnat_portmap_by_vrf[k].status, - cnat_portmap_by_vrf[k].i_vrf, - cnat_portmap_by_vrf[k].o_vrf); - cnat_db_dump_address_portmap(verbose, all, - cnat_portmaps[k], - cnat_portmaps_inuse[k]); - return; - } - } - PLATFORM_DEBUG_PRINT("not found\n"); -} -#endif - -#ifdef TOBE_PORTED -/* This does not seem to be used */ -void cnat_db_mem_usage_cmd (int argc, unsigned long *argv) -{ - pool_header_t * p; - _VEC *_v; - u32 bitmap_bytes=0, free_indices_bytes=0, vec_bytes=0, total_bytes=0; - - if (cnat_main_db) { - p = pool_header(cnat_main_db); - if (p->free_bitmap) { - _v = _vec_find(p->free_bitmap); - bitmap_bytes = _v->alen; - } else { - bitmap_bytes = 0; - } - if (p->free_indices) { - _v = _vec_find(p->free_indices); - free_indices_bytes = _v->alen; - } else { - free_indices_bytes = 0; - } - _v = _vec_find(cnat_main_db); - vec_bytes = _v->alen; - } else { - vec_bytes = 0; - } - - total_bytes = bitmap_bytes + free_indices_bytes + vec_bytes; - - PLATFORM_DEBUG_PRINT ("Main DB: %d total bytes, %d bitmap, %d indices, %d vec\n", - total_bytes, bitmap_bytes, free_indices_bytes, vec_bytes); - PLATFORM_DEBUG_PRINT (" vector length %d\n", vec_len(cnat_main_db)); - - if (cnat_user_db) { - p = pool_header(cnat_user_db); - if (p->free_bitmap) { - _v = _vec_find(p->free_bitmap); - bitmap_bytes = _v->alen; - } else { - bitmap_bytes = 0; - } - if (p->free_indices) { - _v = _vec_find(p->free_indices); - free_indices_bytes = _v->alen; - } else { - free_indices_bytes = 0; - } - _v = _vec_find(cnat_user_db); - vec_bytes = _v->alen; - } else { - vec_bytes = 0; - } - - total_bytes = bitmap_bytes + free_indices_bytes + vec_bytes; - - PLATFORM_DEBUG_PRINT ("User DB: %d total bytes, %d bitmap, %d indices, %d vec\n", - total_bytes, bitmap_bytes, free_indices_bytes, vec_bytes); - PLATFORM_DEBUG_PRINT (" vector length %d\n", vec_len(cnat_user_db)); - - _v = _vec_find(cnat_out2in_hash); - PLATFORM_DEBUG_PRINT("out2in hash: %d total bytes\n", _v->alen); - - _v = _vec_find(cnat_in2out_hash); - PLATFORM_DEBUG_PRINT("in2out hash: %d total bytes\n", _v->alen); -} -#endif - -static void print_server_ip_address (vlib_main_t *vm, u32 ip) -{ - unsigned char bytes[4]; - bytes[0] = ip & 0xFF; - bytes[1] = (ip >> 8) & 0xFF; - bytes[2] = (ip >> 16) & 0xFF; - bytes[3] = (ip >> 24) & 0xFF; - vlib_cli_output(vm, "\tIP Address : %d.%d.%d.%d\n", bytes[0], bytes[1], bytes[2], bytes[3]); -} - -void cnat_nfv9_show_collector (vlib_main_t *vm, cnat_nfv9_logging_info_t *my_nfv9_logging_info) -{ - nfv9_server_info_t *server = nfv9_server_info_pool + - my_nfv9_logging_info->server_index; -#if 0 - vlib_cli_output(vm,"\tVRF - 0x%x - %s\n", my_nfv9_logging_info->i_vrf, - my_nfv9_logging_info->deleted?"DELETED":"ACTIVE"); -#endif - print_server_ip_address(vm, clib_net_to_host_u32(server->ipv4_address)); - vlib_cli_output(vm,"\tPort : %d\n", server->port); - vlib_cli_output(vm,"\tTimeout : %d\n", server->timeout_rate); - vlib_cli_output(vm,"\tRefresh Rate : %d\n", server->refresh_rate); - vlib_cli_output(vm,"\tMax Pkt Size : %d\n", my_nfv9_logging_info->max_length_minus_max_record_size); - - return; -} - -void cnat_db_dump_policy (int argc, unsigned long *argv) -{ - - PLATFORM_CNAT_DB_DUMP_POLICY_PRINT(); - - if (cnat_nfv9_global_info.cnat_nfv9_init_done) { - if (cnat_nfv9_global_info.cnat_nfv9_global_collector_index != EMPTY) { - cnat_nfv9_logging_info_t *my_nfv9_logging_info; - nfv9_server_info_t *server __attribute__((unused)); - - my_nfv9_logging_info = cnat_nfv9_logging_info_pool + - cnat_nfv9_global_info.cnat_nfv9_global_collector_index; - server = nfv9_server_info_pool + - my_nfv9_logging_info->server_index; - - PLATFORM_DEBUG_PRINT("NFv9 logging ip 0x%x port 0x%x refresh-rate %d timeout %d\n", - server->ipv4_address, - server->port, - server->refresh_rate, - server->timeout_rate); - PLATFORM_DEBUG_PRINT("NFv9 path_mtu = %d\n", - my_nfv9_logging_info->max_length_minus_max_record_size); - } else { - PLATFORM_DEBUG_PRINT("NFv9 global logging is not configured\n"); - } - } else { - PLATFORM_DEBUG_PRINT("NFv9 LOGGING is not configured\n"); - } - -} - -#ifdef OLD_VRFMAP -void cnat_show_cdb (int verbose) -{ - int k, l, i; - for (i = 0; i < vec_len(cnat_portmap_by_vrf); i++) { - PLATFORM_DEBUG_PRINT("i_vrf %d : o_vrf %d\n", - cnat_portmap_by_vrf[i].i_vrf, - cnat_portmap_by_vrf[i].o_vrf); - } - - PLATFORM_DEBUG_PRINT("port limit %d\n", cnat_main_db_max_ports_per_user); - - PLATFORM_DEBUG_PRINT ("%d portmap vectors\n", vec_len(cnat_portmaps)); - - for (k = 0; k < vec_len(cnat_portmaps); k++) { - cnat_portmap_t *pm; - u16 *inuse; - pm = cnat_portmaps[k]; - inuse = cnat_portmaps_inuse[k]; - for (l = 0; l < vec_len(pm); l++) { - if (inuse[l] || verbose ) { - u32 net_address; - net_address = - spp_host_to_net_byte_order_32((pm+l)->ipv4_address); - printf_ipv4(net_address); - PLATFORM_DEBUG_PRINT (": %d inuse\n", inuse[l]); - if (verbose && inuse[l]) { - cnat_portmap_dump (pm+l, inuse+l); - } - } - } - } -} -#endif - - - -/* v2 show command */ -void cnat_show_address_portmap_sumary (cnat_portmap_v2_t *pm) -{ - cnat_portmap_v2_t *my_pm =0; - u32 first_address = 0; - u32 second_address = 0; - u32 last_address = 0; - u32 i, pm_len; - - if ((pm_len = vec_len(pm))) { - PLATFORM_DEBUG_PRINT("%d portmap in this list 0x%lx\n", - pm_len, (u32)pm); - for (i = 0; i < pm_len; i++) { - my_pm = pm + i; - if (!first_address) { - first_address = my_pm->ipv4_address; - } else if (!second_address) { - second_address = my_pm->ipv4_address; - } - last_address = my_pm->ipv4_address; - } - - if (first_address) { - PLATFORM_DEBUG_PRINT("1. 0x%08x", first_address); - } - if (second_address) { - PLATFORM_DEBUG_PRINT(", 2. 0x%08x", second_address); - } - - if ((last_address != first_address) && - (last_address != second_address)) { - PLATFORM_DEBUG_PRINT(", ....., %d. 0x%08x", pm_len, last_address); - } - PLATFORM_DEBUG_PRINT("\n"); - } else { - PLATFORM_DEBUG_PRINT("ZERO POOL ADDRESSES in this list 0x%x \n", (u32)pm); - } -} - - -void cnat_show_address_portmap (int verbose, int all, - cnat_portmap_v2_t *pm, u16 port_limit) -{ - cnat_portmap_v2_t *my_pm =0; - u32 i, pm_len; - - pm_len = vec_len(pm); - if (!all) { - cnat_show_address_portmap_sumary(pm); - } else { - PLATFORM_DEBUG_PRINT("%d portmap in this list 0x%x \n", pm_len, (u32)pm); - } - - for (i = 0; i < pm_len; i++) { - - my_pm = pm + i; - if (all) { - PLATFORM_DEBUG_PRINT("pm:0x%x ip address:0x%x del_time 0x%x inuse:%d\n", - (u32)my_pm, my_pm->ipv4_address, my_pm->delete_time, my_pm->inuse); - } else if (my_pm->inuse) { - PLATFORM_DEBUG_PRINT("pm:0x%x ip address:0x%x inuse:%d\n", - (u32)my_pm, my_pm->ipv4_address, my_pm->inuse); - } - - if (verbose && (my_pm->inuse)) { - if(PREDICT_FALSE(!port_limit)) { - cnat_portmap_dump_v2 (my_pm, cnat_main_db_max_ports_per_user); - } - else { - cnat_portmap_dump_v2 (my_pm, port_limit); - } - } - } - - PLATFORM_DEBUG_PRINT("\n"); -} - - -void cnat_show_cdb_v2 (int verbose, int all) -{ - cnat_vrfmap_t *my_vrfmap = 0; - cnat_portmap_v2_t *pm =0; - PLATFORM_DEBUG_PRINT("port limit %d\n", cnat_main_db_max_ports_per_user); - PLATFORM_DEBUG_PRINT("total address pool allocated %d\n", total_address_pool_allocated); - PLATFORM_DEBUG_PRINT("icmp rate limit %d (per core %d)\n", - cnat_main_db_icmp_rate_limit, cnat_main_db_icmp_rate_limit_core); - PLATFORM_DEBUG_PRINT("dynamic port range start %d\n", cnat_static_port_range); - if (pptp_cfg.enable == PPTP_DISABLED) { - PLATFORM_DEBUG_PRINT("PPTP alg disabled \n"); - } else { - PLATFORM_DEBUG_PRINT("PPTP alg enabled \n"); - } - - if (ftp_alg_enabled) { - PLATFORM_DEBUG_PRINT("FTP alg enabled\n"); - } else { - PLATFORM_DEBUG_PRINT("FTP alg disabled\n"); - } - - pool_foreach (my_vrfmap, cnat_map_by_vrf, ({ - CNAT_MY_VRFMAP_PRINT - CNAT_MY_LOGGING_INFO_PRINT - PLATFORM_DEBUG_PRINT("per vrf port limit %d\n", my_vrfmap->port_limit); - pm = my_vrfmap->portmap_list; - cnat_show_address_portmap(verbose, all, pm, my_vrfmap->port_limit); - - })); -} - - -void cnat_show_cdb_command_v2(int argc, unsigned long *argv) -{ - int verbose=0; - int all = 0; - - if (argc > 0) { - verbose = 1; - } - - if (argc > 1) { - all = 1; - } - - cnat_show_cdb_v2(verbose, all); -} - -void cnat_show_ivrf_command_v2 (int argc, unsigned long *argv) -{ - u32 vrf =0; - int verbose=0; - int all = 0; - cnat_vrfmap_t *my_vrfmap = 0; - cnat_portmap_v2_t *pm =0; - - if (!argc) { - PLATFORM_DEBUG_PRINT("need vrf input ,return\n"); - return; - } - if (argc > 0) { - vrf = argv[0]; - } - if (argc > 1) { - verbose = 1; - } - if (argc > 2) { - all = 1; - } - PLATFORM_DEBUG_PRINT ("%lld vrfmap vectors \n", pool_elts(cnat_map_by_vrf)); - pool_foreach (my_vrfmap, cnat_map_by_vrf, ({ - if (my_vrfmap->i_vrf == vrf) { - CNAT_MY_VRFMAP_PRINT - pm = my_vrfmap->portmap_list; - cnat_show_address_portmap(verbose, all, pm,my_vrfmap->port_limit); - return; - } - })); - PLATFORM_DEBUG_PRINT("not found\n"); -} - -void cnat_show_ovrf_command_v2 (int argc, unsigned long *argv) -{ - u32 not_found =1; - u32 vrf =0; - int verbose=0; - int all = 0; - cnat_vrfmap_t *my_vrfmap = 0; - cnat_portmap_v2_t *pm =0; - - if (!argc) { - PLATFORM_DEBUG_PRINT("need vrf input ,return\n"); - return; - } - if (argc > 0) { - vrf = argv[0]; - } - if (argc > 1) { - verbose = 1; - } - if (argc > 2) { - all = 1; - } - PLATFORM_DEBUG_PRINT("%d vrfmap vectors \n", pool_elts(cnat_map_by_vrf)); - pool_foreach (my_vrfmap, cnat_map_by_vrf, ({ - if (my_vrfmap->o_vrf == vrf) { - CNAT_MY_VRFMAP_PRINT - pm = my_vrfmap->portmap_list; - cnat_show_address_portmap(verbose, all, pm,my_vrfmap->port_limit); - not_found = 0; - } - })); - if (not_found) { - PLATFORM_DEBUG_PRINT("not found\n"); - } -} - -void cnat_timeout_db_entry_dump (cnat_timeout_db_entry_t *up) -{ - u32 db_entry_index __attribute__((unused)), - first_db_entry_index __attribute__((unused)); - - PLATFORM_DEBUG_PRINT("Timeout DB entry at index %ld\n", up - cnat_timeout_db); - PLATFORM_DEBUG_PRINT("Desnt key 0x%16llx\n", up->t_key.timeout_key.key64); - PLATFORM_DEBUG_PRINT("Timeout value %d\n", up->t_key.timeout_value); - PLATFORM_DEBUG_PRINT("Hash Next 0x%x\n", up->t_hash.next); - -} - -void cnat_db_dump_timeout () -{ - cnat_timeout_db_entry_t *up; - pool_header_t *h; - u32 used __attribute__((unused)), free __attribute__((unused)); - - h = pool_header(cnat_timeout_db); - free = vec_len(h->free_indices); - used = (vec_len(cnat_timeout_db) - free); - - PLATFORM_DEBUG_PRINT("Timeout DB Free %d, Used %d\n",free, used); - - pool_foreach(up, cnat_timeout_db, ({ - cnat_timeout_db_entry_dump(up); - })); -} - diff --git a/plugins/plugins/vcgn/cnat_show_api.h b/plugins/plugins/vcgn/cnat_show_api.h deleted file mode 100644 index 5904c7e2..00000000 --- a/plugins/plugins/vcgn/cnat_show_api.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * 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 __CNAT_SHOW_API_H__ -#define __CNAT_SHOW_API_H__ - -typedef struct _spp_api_cnat_v4_show_inside_entry_req { - u16 _spp_msg_id; - u16 vrf_id; - u32 ipv4_addr; - u16 start_port; - u16 end_port; - u8 flags; - u8 all_entries; - u8 protocol; -} spp_api_cnat_v4_show_inside_entry_req_t; - -typedef struct _spp_api_cnat_v4_show_outside_entry_req { - u16 _spp_msg_id; - u16 vrf_id; - u32 ipv4_addr; - u16 start_port; - u16 end_port; - u8 flags; - u8 protocol; -} spp_api_cnat_v4_show_outside_entry_req_t; - - -#endif diff --git a/plugins/plugins/vcgn/cnat_show_response.h b/plugins/plugins/vcgn/cnat_show_response.h deleted file mode 100644 index bec1bd97..00000000 --- a/plugins/plugins/vcgn/cnat_show_response.h +++ /dev/null @@ -1,580 +0,0 @@ -/* - *------------------------------------------------------------------ - * cnat_show_response.h show command response structs - * - * Copyright (c) 2007-2013 Cisco and/or its affiliates. - * 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 __CNAT_SHOW_RESPONSE_H__ -#define __CNAT_SHOW_RESPONSE_H__ - -/* - * Flags indicating the type of translation entry - */ -#define CNAT_TRANSLATION_ENTRY_ALL 0x0 -#define CNAT_TRANSLATION_ENTRY_STATIC 0x1 -#define CNAT_TRANSLATION_ENTRY_ALG 0x2 -#define CNAT_TRANSLATION_ENTRY_DYNAMIC 0x4 - -/* for PCP support */ -#define CNAT_TRANSLATION_ENTRY_PCPI_DYNAMIC 0x08 -#define CNAT_TRANSLATION_ENTRY_PCPE_DYNAMIC 0x10 - -#define MAX_NODE_NAME_LEN 18 -#define MAX_CTR_NAME_LEN 10 - -/* - * show translation entry response structures - */ -typedef struct { - u16 call_id; - u16 cnat_call_id; /* mapped call Id */ - u16 dst_call_id; /* dest call id */ -} cnat_v4_show_gre_entry; - -typedef struct { - u16 msg_id; - u16 rc; /* o/p parameter. */ - u16 num_entries; /* Number of entries sent as output */ - u16 vrf_id; /* vrf id */ - u32 pns_ip; - cnat_v4_show_gre_entry entries[0]; -} cnat_v4_show_gre_entry_resp; - -/* - * show translation entry response structures - */ -typedef struct { - u32 ipv4_addr; - u16 src_port; - u16 cnat_port; /* port which replaced the src port */ - u8 protocol; - u8 pad; - u16 flags; - u16 nsessions; - u32 in2out_packets; - u32 out2in_packets; -} cnat_v4_show_translation_entry; - -typedef struct { - u16 msg_id; - u8 rc; /* o/p parameter. */ - u8 num_entries; /* Number of entries sent as output */ - u16 vrf_id; /* vrf id */ - u16 pad; - cnat_v4_show_translation_entry entries[0]; -} cnat_v4_show_entry_resp; - -/* - * show free/used ipv4 address/port response structure - */ -typedef struct { - u32 ip_addr; - u32 free_used_ports; -} cnat_v4_show_free_used_entry; - -typedef struct { - u16 msg_id; - u8 rc; - u8 count; - u32 max_ports; - cnat_v4_show_free_used_entry entry_list[0]; -} cnat_v4_show_free_used_entry_resp; - -/* - * Node name to id mapping - */ -typedef struct { - u8 node_id; - u8 pad; - char node_name[MAX_NODE_NAME_LEN]; -} cnat_statistics_node_name; - -typedef struct { - u16 msg_id; - u8 rc; - u8 num_nodes; - cnat_statistics_node_name node_name_array[0]; -} cnat_statistics_node_name_mapping_resp; - -/* - * Counter name to id mapping - */ -typedef struct { - u8 node_id; - u8 counter_id; - char counter_name[MAX_CTR_NAME_LEN]; -} cnat_statistics_counter_name; - -typedef struct { - u16 msg_id; - u8 rc; - u8 num_counters; - cnat_statistics_counter_name counter_name_array[0]; -} cnat_statistics_counter_name_mapping_resp; - - -/* - * Node name to id mapping - */ -typedef struct { - u16 msg_id; - u8 rc; - u8 num_nodes; - u32 pad; - u64 counters [0]; -} cnat_statistics_counter_values; - -/* - * Summary Stats - */ -typedef struct { - u32 eaddr; - u32 ports_used; -} pool_address_usage_t; - -typedef struct { - u16 msg_id; - u8 rc; - u8 pad; - u16 max_pkt_size; - u16 pool_address_copied; - u32 active_translations; - u32 translation_create_rate; - u32 translation_delete_rate; - u32 in2out_forwarding_rate; - u32 out2in_forwarding_rate; - u32 dummy; - u64 in2out_drops_port_limit_exceeded; - u64 in2out_drops_system_limit_reached; - u64 in2out_drops_resource_depletion; - u64 no_translation_entry_drops; - u64 pptp_active_tunnels; - u64 pptp_active_channels; - u64 pptp_ctrlmsg_drops; - u32 no_sessions; - - u32 pool_address_totally_free; - u32 pool_address_used; /* The following array size will be lesser of - (pool_address_used, 200) */ - u32 num_subscribers; - u64 drops_sessiondb_limit_exceeded; - u64 in2out_drops_src_ip_no_config; // for deterministic nat on brahmos - pool_address_usage_t pool_address_usage[0]; -} cnat_show_statistics_summary_resp; - - -typedef struct { - u16 msg_id; - u8 rc; - u8 pad; - u64 o2i_tcp_seq_mismatch_drop; - u64 o2i_tcp_seq_mismatch; - u64 o2i_sessions_created; - u64 o2i_end_point_filter_drop; -} cnat_show_counters_summary_resp; - - -typedef struct { - u16 msg_id; - u8 rc; - u8 pad; - - /* - * XLAT statistics - */ - u64 v6_to_v4_tcp_input_count; - u64 v6_to_v4_tcp_non_translatable_drop_count; - u64 v6_to_v4_tcp_invalid_next_hdr_drop_count; - u64 v6_to_v4_tcp_no_db_drop_count; - u64 v6_to_v4_tcp_output_count; - - u64 v4_to_v6_tcp_input_count; - u64 v4_to_v6_tcp_no_db_drop_count; - u64 v4_to_v6_tcp_output_count; - - u64 v6_to_v4_udp_input_count; - u64 v6_to_v4_udp_non_translatable_drop_count; - u64 v6_to_v4_udp_invalid_next_hdr_drop_count; - u64 v6_to_v4_udp_no_db_drop_count; - u64 v6_to_v4_udp_output_count; - - u64 v4_to_v6_udp_input_count; - u64 v4_to_v6_udp_no_db_drop_count; - u64 v4_to_v6_udp_output_count; - u64 v4_to_v6_udp_frag_crc_zero_drop_count; - u64 v4_to_v6_udp_crc_zero_recycle_sent_count; - u64 v4_to_v6_udp_crc_zero_recycle_drop_count; - - u64 v6_to_v4_icmp_qry_input_count; - u64 v6_to_v4_icmp_no_db_drop_count; - u64 v6_to_v4_icmp_frag_drop_count; - u64 v6_to_v4_icmp_invalid_next_hdr_drop_count; - u64 v6_to_v4_icmp_non_translatable_drop_count; - u64 v6_to_v4_icmp_non_translatable_fwd_count; - u64 v6_to_v4_icmp_unsupported_type_drop_count; - u64 v6_to_v4_icmp_err_output_count; - u64 v6_to_v4_icmp_qry_output_count; - - u64 v4_to_v6_icmp_qry_input_count; - u64 v4_to_v6_icmp_no_db_drop_count; - u64 v4_to_v6_icmp_frag_drop_count; - u64 v4_to_v6_icmp_unsupported_type_drop_count; - u64 v4_to_v6_icmp_err_output_count; - u64 v4_to_v6_icmp_qry_output_count; - - u64 v6_to_v4_subsequent_frag_input_count; - u64 v6_to_v4_subsequent_frag_non_translatable_drop_count; - u64 v6_to_v4_subsequent_frag_invalid_next_hdr_drop_count; - u64 v6_to_v4_subsequent_frag_no_db_drop_count; - u64 v6_to_v4_subsequent_frag_output_count; - - u64 v4_to_v6_subsequent_frag_input_count; - u64 v4_to_v6_subsequent_frag_no_db_drop_count; - u64 v4_to_v6_subsequent_frag_output_count; - - u64 v4_to_v6_subsequent_frag_drop_count; - u64 v4_to_v6_subsequent_frag_throttled_count; - u64 v4_to_v6_subsequent_frag_timeout_drop_count; - u64 v4_to_v6_subsequent_frag_tcp_input_count; - u64 v4_to_v6_subsequent_frag_udp_input_count; - u64 v4_to_v6_subsequent_frag_icmp_input_count; - - u64 v6_to_v4_options_input_count; - u64 v6_to_v4_options_drop_count; - u64 v6_to_v4_options_forward_count; - u64 v6_to_v4_options_no_db_drop_count; - u64 v6_to_v4_unsupp_proto_count; - - u64 v4_to_v6_options_input_count; - u64 v4_to_v6_options_drop_count; - u64 v4_to_v6_options_forward_count; - u64 v4_to_v6_options_no_db_drop_count; - u64 v4_to_v6_unsupp_proto_count; - - u64 v4_icmp_gen_count; - u64 v6_icmp_gen_count; -} xlat_show_statistics_summary_resp; - -typedef struct { - u16 msg_id; - u8 rc; - u8 pad; - /* Total v4 packets to BR */ - u64 v4_to_v6_input_total_count; - /* Total v4 tunneled packets to BR */ - u64 v4_to_v6_41_input_total_count; - /* proto 41 packets without minimum, of 40, v6 payload */ - u64 v4_to_v6_41_insuff_v6payld_count; - /* total proto 41 packets being considered for decap */ - u64 v4_to_v6_41_valid_count; - /* proto 41 packets that failed security check*/ - u64 v4_to_v6_41_sec_check_fail_count; - /* packets with no active db entry */ - u64 v4_to_v6_no_db_drop_count; - /* proto 41 packets actually getting decapped */ - u64 v4_to_v6_41_decap_count; - /* total v4 packets which are neither icmp nor 41 */ - u64 v4_to_v6_unsupported_protocol_count; - /* v4 tunneled packets with invalid v6 source address */ - u64 v4_to_v6_41_invalid_v6_source; - /* total icmpv4 packets destined to BR */ - u64 v4_forus_icmp_input_count; - /* total icmpv4 echo replies by BR */ - u64 v4_icmp_reply_count; - /* total icmpv4 error messages translated to icmpv6 by BR */ - u64 v4_to_v6_icmp_translation_count; - /* total packets with icmpv4 type/code which are not supported by BR */ - u64 v4_icmp_unsupported_count; - /* total icmpv4 packets which are rate-limited by BR */ - u64 v4_icmp_throttled_count; - /* total ICMPv4 error messages which could not be translated */ - u64 v4_icmp_non_translatable_drop_count; - - /* ipv4 defrag stats */ - u64 v4_to_v6_frag_input_count; - u64 v4_to_v6_frag_sec_check_fail_count; - u64 v4_to_v6_frag_reassem_count; - u64 v4_to_v6_frag_timeout_drop_count; - u64 v4_to_v6_frag_icmp_input_count; - u64 v4_to_v6_frag_41_insuff_v6payld_count; - u64 v4_to_v6_frag_no_db_drop_count; - u64 v4_to_v6_frag_unsupported_protocol_count; - u64 v4_to_v6_frag_41_invalid_v6_source; - u64 v4_to_v6_frag_throttled_count; - u64 v4_to_v6_frag_dup_count; - u64 v4_to_v6_frag_reassem_frag_count; - u64 v4_to_v6_frag_disable_count; - u64 v4_to_v6_frag_drop_count; - - /* total v6 packets input to BR */ - u64 v6_to_v4_total_input_count; - /* v6 packets with no active db entry */ - u64 v6_to_v4_no_db_drop_count; - /* forus v6 packets with next header other than icmpv6 */ - u64 v6_to_v4_forus_unsupp_proto_count; - /* total v6 packets that got tunneled */ - u64 v6_to_v4_encap_count; - /* total icmpv6 packets destined to BR */ - u64 v6_forus_icmp_input_count; - /* total icmpv6 echo replies by BR */ - u64 v6_icmp_reply_count; - /* total icmpv6 PTB messages generated by BR */ - u64 v6_ptb_generated_count; - /* total ipv6 packets for which PTBv6 was NOT generated by BR */ - u64 v6_ptb_not_generated_drop_count; - /* total icmpv6 Neighbor Advertisements generated by BR */ - u64 v6_na_generated_count; - /* total icmpv6 TTL expiry messages generated by BR */ - u64 v6_ttl_expiry_generated_count; - /* total ICMPv6 fragments, which are dropped by BR */ - u64 v6_to_v4_frag_icmp_input_count; - /* total packets with icmpv6 type/code which are not supported by BR */ - u64 v6_icmp_unsupported_count; - /* total icmpv6 packets which are rate-limited by BR */ - u64 v6_icmp_throttled_count; -} v6rd_show_statistics_summary_resp; - -typedef struct { - u16 msg_id; - u8 rc; - u8 pad; - - /* Total Incoming Count */ - u64 v4_input_count; - /* Total Drop Count */ - u64 v4_drop_count; - /* Total Output Count */ - u64 v4_to_v6_output_count; - /* TCP Incoming Count */ - u64 v4_tcp_input_count; - /* TCP Output Count */ - u64 v4_tcp_output_count; - /* UDP Incoming Count */ - u64 v4_udp_input_count; - /* UDP Output Count */ - u64 v4_udp_output_count; - /* ICMPv4 Incoming Count */ - u64 v4_icmp_input_count; - /* ICMPv4 Output Count */ - u64 v4_to_v6_icmp_output_count; - /* Invalid UIDB Drop Count */ - u64 v4_invalid_uidb_drop_count; - /* NoDb Drop Count */ - u64 v4_no_db_drop_count; - /* TTL Expire Drop Count */ - u64 v4_ttl_expire_drop_count; - /* Invalid IP Destination Drop Count */ - u64 v4_invalid_destination_prefix_drop_count; - /* Packet Execeeding Path MTU Drop Count */ - u64 v4_path_mtu_exceed_count; - /* Unsupported Protocol Drop Count */ - u64 v4_invalid_proto_type_drop_count; - /* ICMPv4 Generated for TTL Expire Count */ - u64 v4_ttl_expiry_generated_count; - /* ICMPv4 Generated for Error Count */ - u64 v4_icmp_error_gen_count; - /* ICMPv4 Packets Rate-Limited Count */ - u64 v4_icmp_throttled_drop_count; - /* TCP MSS Changed Count */ - u64 v4_tcp_mss_changed_count; - - /* Total Incoming Count */ - u64 v6_input_count; - /* Total Drop Count */ - u64 v6_drop_count; - /* Total Output Count */ - u64 v6_to_v4_output_count; - /* TCP Incoming Count */ - u64 v6_tcp_input_count; - /* TCP Output Count */ - u64 v6_tcp_output_count; - /* UDP Incoming Count */ - u64 v6_udp_input_count; - /* UDP Output Count */ - u64 v6_udp_output_count; - /* ICMPv4 Incoming Count */ - u64 v6_icmpv4_input_count; - /* ICMPv4 Output Count */ - u64 v6_icmpv4_output_count; - /* Invalid UIDB Drop Count */ - u64 v6_invalid_uidb_drop_count; - /* NoDb Drop Count */ - u64 v6_no_db_drop_count; - /* TTL Expire Drop Count */ - u64 v6_ttl_expire_drop_count; - /* Invalid IPv6 Destination Drop Count */ - u64 v6_invalid_destination_drop_count; - /* Invalid Source Prefix Drop Count */ - u64 v6_invalid_source_prefix_drop_count; - /* Unsupported Protocol Drop Count */ - u64 v6_invalid_proto_type_drop_count; - /* ICMPv6 Input Count */ - u64 v6_icmp_input_count; - /* ICMPv6 Invalid UIDB Drop Count */ - u64 v6_icmp_invalid_uidb_drop_count; - /* ICMPv6 NoDb Drop Count */ - u64 v6_icmp_no_db_drop_count; - /* ICMPv6 TTL Expire Drop Count */ - u64 v6_icmp_ttl_expire_drop_count; - /* ICMPv6 Invalid IPv6 Destination Drop Count */ - u64 v6_icmp_invalid_destination_drop_count; - /* ICMPv6 Unsupported Type Drop Count */ - u64 v6_icmp_unsupported_type_drop_count; - /* ICMPv6 Invalid NxtHdr Drop Count*/ - u64 v6_icmp_unsupported_nxthdr_drop_count; - /* ICMPv6 Frag Drop Count */ - u64 v6_icmp_frag_drop_count; - /* ICMPv6 Forus Count */ - u64 v6_forus_icmp_input_count; - /* ICMPv6 Echo Response Received Count */ - u64 v6_received_echo_response_count; - /* ICMPv6 Echo Replies Count */ - u64 v6_echo_reply_count; - /* ICMPv6 Translated to ICMPV4 Output Count*/ - u64 v6_to_v4_icmp_output_count; - /* ICMPv6 Generated for TTL Expire Count */ - u64 v6_ttl_expiry_generated_count; - /* ICMPv6 Generated for Error Count */ - u64 v6_icmp_error_gen_count; - /* ICMPv6 Packets Rate-Limited Count */ - u64 v6_icmp_throttled_drop_count; - /* TCP MSS Changed Count */ - u64 v6_tcp_mss_changed_count; - - /*Total Input Count*/ - u64 v4_to_v6_frag_input_count; - /*Total Drop Count*/ - u64 v4_to_v6_frag_drop_count; - /*Reassembled Output Count*/ - u64 v4_to_v6_frag_reassem_count; - - /*TCP Input Count*/ - u64 v4_to_v6_frag_tcp_input_count; - /*UDP Input Count*/ - u64 v4_to_v6_frag_udp_input_count; - /*ICMPv4 Input Count*/ - u64 v4_to_v6_frag_icmp_input_count; - - /*Invalid UIDB Drop Count */ - u64 v4_to_v6_frag_invalid_uidb_drop_count; - /*NoDb Drop Count*/ - u64 v4_to_v6_frag_no_db_drop_count; - /*Unsupported Protocol Drop Count*/ - u64 v4_to_v6_frag_invalid_proto_type_drop_count; - /*Throttled Count*/ - u64 v4_to_v6_frag_throttled_count; - /*Timeout Drop Count*/ - u64 v4_to_v6_frag_timeout_drop_count; - /*Duplicates Drop Count*/ - u64 v4_to_v6_frag_dup_count; - - /*Total Input Count*/ - u64 v6_to_v4_inner_frag_input_count; - /*Total Drop Count*/ - u64 v6_to_v4_inner_frag_drop_count; - /*Total Output Count*/ - u64 v6_to_v4_inner_frag_output_count; - - /*TCP Input Count*/ - u64 v6_to_v4_inner_frag_tcp_input_count; - /*UDP Input Count*/ - u64 v6_to_v4_inner_frag_udp_input_count; - /*ICMPv4 Input Count*/ - u64 v6_to_v4_inner_frag_icmp_input_count; - - /*Invalid Source Prefix Drop Count*/ - u64 v6_to_v4_inner_frag_invalid_source_prefix_drop_count; - /*Unsupported Protocol Drop Count*/ - u64 v6_to_v4_inner_frag_invalid_proto_type_drop_count; - /*Throttled Count*/ - u64 v6_to_v4_inner_frag_throttled_count; - /*Timeout Drop Count*/ - u64 v6_to_v4_inner_frag_timeout_drop_count; - /*Duplicates Drop Count*/ - u64 v6_to_v4_inner_frag_dup_count; - - /*ICMPv6 Generated for Error Count */ - u64 v6_to_v4_inner_frag_icmp_error_gen_count; - /*ICMPv6 Packets Rate-Limited Count */ - u64 v6_to_v4_inner_frag_icmp_throttled_drop_count; - - /*TCP MSS Changed Count */ - u64 v6_to_v4_inner_frag_tcp_mss_changed_count; - -} mape_show_statistics_summary_resp; - -/* - * The following are the command types for Generic Command cases - */ -#define CNAT_DEBUG_GENERIC_COMMAND_READ_MEM 1 -#define CNAT_DEBUG_GENERIC_COMMAND_WRITE_MEM 2 -#define CNAT_DEBUG_GENERIC_COMMAND_DB_SUMMARY 3 -#define CNAT_DEBUG_GENERIC_COMMAND_USER_DB_PM 4 -#define CNAT_DEBUG_GET_CGN_DB_SUMMARY 5 - -typedef enum { - CNAT_DEBUG_GENERIC_COMMAND_DUMP_POLICY, - CNAT_DEBUG_GENERIC_COMMAND_DUMP_MAIN_DB, - CNAT_DEBUG_GENERIC_COMMAND_DUMP_USER_DB, - CNAT_DEBUG_GENERIC_COMMAND_DUMP_HASHES_DB, - CNAT_DEBUG_GENERIC_COMMAND_DUMP_VRF_MAP, - CNAT_DEBUG_GENERIC_COMMAND_DUMP_SUMMARY_DB, - CNAT_DEBUG_GENERIC_COMMAND_DUMP_STATS, - CNAT_DEBUG_GENERIC_COMMAND_CLEAR_STATS, - CNAT_DEBUG_GENERIC_COMMAND_DUMP_NODE_COUNTER, - CNAT_DEBUG_GENERIC_COMMAND_CLEAR_NODE_COUNTER, - CNAT_DEBUG_GENERIC_COMMAND_DUMP_CNAT_COUNTER, - CNAT_DEBUG_GENERIC_COMMAND_DUMP_VA, - CNAT_DEBUG_GENERIC_COMMAND_SHOW_CONFIG, - CNAT_DEBUG_GENERIC_COMMAND_SHOW_NFV9, - CNAT_DEBUG_GENERIC_COMMAND_SHOW_IVRF, - CNAT_DEBUG_GENERIC_COMMAND_SHOW_OVRF, - CNAT_DEBUG_SPP_LOG, - CNAT_DEBUG_GENERIC_COMMAND_DEBUG_OPTIONS, - CNAT_DEBUG_GENERIC_COMMAND_DUMP_DEBUG_LEVELS, - CNAT_DEBUG_GENERIC_COMMAND_DEBUG_FLAGS, - CNAT_READ_TEMP_SENSORS, - CNAT_BLOCK_OCTEON_SENSOR_READ, - CNAT_DEBUG_GENERIC_COMMAND_DUMP_MAIN_DB_SUMMARY, - CNAT_DEBUG_GENERIC_COMMAND_DUMP_USER_DB_SUMMARY, - CNAT_DEBUG_DUMP_6RD_STATS, - CNAT_DEBUG_TIMEOUT_DB_SUMMARY, - CNAT_NAT64_STFUL_DEBUG_COMMAND, - CNAT_DEBUG_SET_BULK_SIZE, - CNAT_DEBUG_SHOW_BULK_STAT, - CNAT_DEBUG_CLEAR_BULK_STAT, - CNAT_DEBUG_SHOW_BULK_ALLOC, - CNAT_DEBUG_NAT64, - CNAT_DEBUG_NAT44_IN2OUT_FRAG_STATS, -} cnat_debug_dump_type_t; - -typedef enum { - CNAT_DEBUG_FLAG_UDP_INSIDE_CHECKSUM_MODIFY, - CNAT_DEBUG_FLAG_UDP_OUTSIDE_CHECKSUM_MODIFY, - CNAT_DEBUG_FLAG_UDP_INSIDE_PACKET_DUMP, - CNAT_DEBUG_FLAG_UDP_OUTSIDE_PACKET_DUMP, -} cnat_debug_flag_type_t; - -typedef struct { - u16 spp_msg_id; - u8 rc; - u8 core; - u32 num_bytes; - u8 raw_data[0]; -} cnat_generic_command_resp; - -extern u32 db_free_entry (void * p); -#endif /*__CNAT_SHOW_RESPONSE_H__*/ diff --git a/plugins/plugins/vcgn/cnat_syslog.c b/plugins/plugins/vcgn/cnat_syslog.c deleted file mode 100644 index 91758f14..00000000 --- a/plugins/plugins/vcgn/cnat_syslog.c +++ /dev/null @@ -1,1787 +0,0 @@ -/* - *------------------------------------------------------------------ - * cnat_syslog.c - * - * Copyright (c) 2011-2013 Cisco and/or its affiliates. - * 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 -#include "cnat_syslog.h" -#include "platform_common.h" -#include "cnat_db.h" -#include "cnat_log_common.h" -#include - -#define SYSLOG_DELIMITER ' ' -#define SYSLOG_FIELD_ABSENT '-' -/* #define SHOW_SYSLOG_TIMESTAMP 1 TO DO. Remove this later */ -/* - * Defining the below macro here for now. Assumption is, syslog packets - * are sent out via same channel as that of NFV9. - * Has to be overridden if this assumption is false. - */ -#define PLATFORM_SYSLOG_DISP_NODE_IDX PLATFORM_NFV9_DISP_NODE_IDX - -cnat_syslog_global_info_t cnat_syslog_global_info; -cnat_syslog_logging_info_t *cnat_syslog_logging_info_pool; -cnat_syslog_global_counters_t cnat_syslog_global_counter; -extern u32 syslog_debug_flag; - -#define CNAT_SYSLOG_DEBUG_CODE 2 - -#if CNAT_SYSLOG_DEBUG_CODE > 3 -#define SYSLOG_COND if(my_instance_number == 0) - -#define SYSLOG_DEBUG_PRINTF1(a) SYSLOG_COND printf(a); -#define SYSLOG_DEBUG_PRINTF2(a, b) SYSLOG_COND printf(a, b); -#define SYSLOG_DEBUG_PRINTF3(a, b, c) SYSLOG_COND printf(a, b, c); -#define SYSLOG_DEBUG_PRINTF4(a, b, c, d) SYSLOG_COND printf(a, b, c, d); - -#else - -#define SYSLOG_DEBUG_PRINTF1(a) -#define SYSLOG_DEBUG_PRINTF2(a, b) -#define SYSLOG_DEBUG_PRINTF3(a, b, c) -#define SYSLOG_DEBUG_PRINTF4(a, b, c, d) - -#endif - - -void syslog_params_show(u32 logging_index) -{ - cnat_syslog_logging_info_t *log_info __attribute__((unused)); - if(logging_index == EMPTY) { - PLATFORM_DEBUG_PRINT("\nSyslog logging not configured\n"); - return; - } - - log_info = cnat_syslog_logging_info_pool + logging_index; - - PLATFORM_DEBUG_PRINT("\nSyslog parameters --\n"); - PLATFORM_DEBUG_PRINT("IPV4 address: %x, port %d, max log size %d\n", - log_info->ipv4_address, - log_info->port, log_info->max_length_minus_max_record_size); - PLATFORM_DEBUG_PRINT("Host name: %s, priority %d", - log_info->header_hostname, log_info->header_priority); - -} - -/* Util function to copy a number as ASCII in to a buf in a - * faster way (should be faster than sprintf) - */ - -const unsigned char ascii_numbers[][3] = - { {'0', '0', '0'}, - {'1', '0', '0'}, - {'2', '0', '0'}, - {'3', '0', '0'}, - {'4', '0', '0'}, - {'5', '0', '0'}, - {'6', '0', '0'}, - {'7', '0', '0'}, - {'8', '0', '0'}, - {'9', '0', '0'}, - {'1', '0', '0'}, - {'1', '1', '0'}, - {'1', '2', '0'}, - {'1', '3', '0'}, - {'1', '4', '0'}, - {'1', '5', '0'}, - {'1', '6', '0'}, - {'1', '7', '0'}, - {'1', '8', '0'}, - {'1', '9', '0'}, - {'2', '0', '0'}, - {'2', '1', '0'}, - {'2', '2', '0'}, - {'2', '3', '0'}, - {'2', '4', '0'}, - {'2', '5', '0'}, - {'2', '6', '0'}, - {'2', '7', '0'}, - {'2', '8', '0'}, - {'2', '9', '0'}, - {'3', '0', '0'}, - {'3', '1', '0'}, - {'3', '2', '0'}, - {'3', '3', '0'}, - {'3', '4', '0'}, - {'3', '5', '0'}, - {'3', '6', '0'}, - {'3', '7', '0'}, - {'3', '8', '0'}, - {'3', '9', '0'}, - {'4', '0', '0'}, - {'4', '1', '0'}, - {'4', '2', '0'}, - {'4', '3', '0'}, - {'4', '4', '0'}, - {'4', '5', '0'}, - {'4', '6', '0'}, - {'4', '7', '0'}, - {'4', '8', '0'}, - {'4', '9', '0'}, - {'5', '0', '0'}, - {'5', '1', '0'}, - {'5', '2', '0'}, - {'5', '3', '0'}, - {'5', '4', '0'}, - {'5', '5', '0'}, - {'5', '6', '0'}, - {'5', '7', '0'}, - {'5', '8', '0'}, - {'5', '9', '0'}, - {'6', '0', '0'}, - {'6', '1', '0'}, - {'6', '2', '0'}, - {'6', '3', '0'}, - {'6', '4', '0'}, - {'6', '5', '0'}, - {'6', '6', '0'}, - {'6', '7', '0'}, - {'6', '8', '0'}, - {'6', '9', '0'}, - {'7', '0', '0'}, - {'7', '1', '0'}, - {'7', '2', '0'}, - {'7', '3', '0'}, - {'7', '4', '0'}, - {'7', '5', '0'}, - {'7', '6', '0'}, - {'7', '7', '0'}, - {'7', '8', '0'}, - {'7', '9', '0'}, - {'8', '0', '0'}, - {'8', '1', '0'}, - {'8', '2', '0'}, - {'8', '3', '0'}, - {'8', '4', '0'}, - {'8', '5', '0'}, - {'8', '6', '0'}, - {'8', '7', '0'}, - {'8', '8', '0'}, - {'8', '9', '0'}, - {'9', '0', '0'}, - {'9', '1', '0'}, - {'9', '2', '0'}, - {'9', '3', '0'}, - {'9', '4', '0'}, - {'9', '5', '0'}, - {'9', '6', '0'}, - {'9', '7', '0'}, - {'9', '8', '0'}, - {'9', '9', '0'}, - {'1', '0', '0'}, - {'1', '0', '1'}, - {'1', '0', '2'}, - {'1', '0', '3'}, - {'1', '0', '4'}, - {'1', '0', '5'}, - {'1', '0', '6'}, - {'1', '0', '7'}, - {'1', '0', '8'}, - {'1', '0', '9'}, - {'1', '1', '0'}, - {'1', '1', '1'}, - {'1', '1', '2'}, - {'1', '1', '3'}, - {'1', '1', '4'}, - {'1', '1', '5'}, - {'1', '1', '6'}, - {'1', '1', '7'}, - {'1', '1', '8'}, - {'1', '1', '9'}, - {'1', '2', '0'}, - {'1', '2', '1'}, - {'1', '2', '2'}, - {'1', '2', '3'}, - {'1', '2', '4'}, - {'1', '2', '5'}, - {'1', '2', '6'}, - {'1', '2', '7'}, - {'1', '2', '8'}, - {'1', '2', '9'}, - {'1', '3', '0'}, - {'1', '3', '1'}, - {'1', '3', '2'}, - {'1', '3', '3'}, - {'1', '3', '4'}, - {'1', '3', '5'}, - {'1', '3', '6'}, - {'1', '3', '7'}, - {'1', '3', '8'}, - {'1', '3', '9'}, - {'1', '4', '0'}, - {'1', '4', '1'}, - {'1', '4', '2'}, - {'1', '4', '3'}, - {'1', '4', '4'}, - {'1', '4', '5'}, - {'1', '4', '6'}, - {'1', '4', '7'}, - {'1', '4', '8'}, - {'1', '4', '9'}, - {'1', '5', '0'}, - {'1', '5', '1'}, - {'1', '5', '2'}, - {'1', '5', '3'}, - {'1', '5', '4'}, - {'1', '5', '5'}, - {'1', '5', '6'}, - {'1', '5', '7'}, - {'1', '5', '8'}, - {'1', '5', '9'}, - {'1', '6', '0'}, - {'1', '6', '1'}, - {'1', '6', '2'}, - {'1', '6', '3'}, - {'1', '6', '4'}, - {'1', '6', '5'}, - {'1', '6', '6'}, - {'1', '6', '7'}, - {'1', '6', '8'}, - {'1', '6', '9'}, - {'1', '7', '0'}, - {'1', '7', '1'}, - {'1', '7', '2'}, - {'1', '7', '3'}, - {'1', '7', '4'}, - {'1', '7', '5'}, - {'1', '7', '6'}, - {'1', '7', '7'}, - {'1', '7', '8'}, - {'1', '7', '9'}, - {'1', '8', '0'}, - {'1', '8', '1'}, - {'1', '8', '2'}, - {'1', '8', '3'}, - {'1', '8', '4'}, - {'1', '8', '5'}, - {'1', '8', '6'}, - {'1', '8', '7'}, - {'1', '8', '8'}, - {'1', '8', '9'}, - {'1', '9', '0'}, - {'1', '9', '1'}, - {'1', '9', '2'}, - {'1', '9', '3'}, - {'1', '9', '4'}, - {'1', '9', '5'}, - {'1', '9', '6'}, - {'1', '9', '7'}, - {'1', '9', '8'}, - {'1', '9', '9'}, - {'2', '0', '0'}, - {'2', '0', '1'}, - {'2', '0', '2'}, - {'2', '0', '3'}, - {'2', '0', '4'}, - {'2', '0', '5'}, - {'2', '0', '6'}, - {'2', '0', '7'}, - {'2', '0', '8'}, - {'2', '0', '9'}, - {'2', '1', '0'}, - {'2', '1', '1'}, - {'2', '1', '2'}, - {'2', '1', '3'}, - {'2', '1', '4'}, - {'2', '1', '5'}, - {'2', '1', '6'}, - {'2', '1', '7'}, - {'2', '1', '8'}, - {'2', '1', '9'}, - {'2', '2', '0'}, - {'2', '2', '1'}, - {'2', '2', '2'}, - {'2', '2', '3'}, - {'2', '2', '4'}, - {'2', '2', '5'}, - {'2', '2', '6'}, - {'2', '2', '7'}, - {'2', '2', '8'}, - {'2', '2', '9'}, - {'2', '3', '0'}, - {'2', '3', '1'}, - {'2', '3', '2'}, - {'2', '3', '3'}, - {'2', '3', '4'}, - {'2', '3', '5'}, - {'2', '3', '6'}, - {'2', '3', '7'}, - {'2', '3', '8'}, - {'2', '3', '9'}, - {'2', '4', '0'}, - {'2', '4', '1'}, - {'2', '4', '2'}, - {'2', '4', '3'}, - {'2', '4', '4'}, - {'2', '4', '5'}, - {'2', '4', '6'}, - {'2', '4', '7'}, - {'2', '4', '8'}, - {'2', '4', '9'}, - {'2', '5', '0'}, - {'2', '5', '1'}, - {'2', '5', '2'}, - {'2', '5', '3'}, - {'2', '5', '4'}, - {'2', '5', '5'} - }; - -inline static int -byte_to_ascii_decimal_unaligned( - unsigned char *ptr, unsigned char num) -{ - *ptr++ = ascii_numbers[num][0]; - if(PREDICT_FALSE(num < 10)) { - return 1; - } - *ptr++ = ascii_numbers[num][1]; - if(PREDICT_FALSE(num < 100)) { - return 2; - } - *ptr++ = ascii_numbers[num][2]; - return 3; -} - -/* Copies the dotted decimal format of ipv4 - * in to the space provided and - * returns the number of bytes copied - */ -inline static int __attribute__((unused)) -copy_ipv4_addr(unsigned char *ptr, u32 ipv4) -{ - unsigned char *temp = ptr; - temp += byte_to_ascii_decimal_unaligned(temp, (ipv4 >> 24)); - *temp++ = '.'; - temp += byte_to_ascii_decimal_unaligned(temp, ((ipv4 >> 16) & 0xFF)); - *temp++ = '.'; - temp += byte_to_ascii_decimal_unaligned(temp, ((ipv4 >> 8) & 0xFF)); - *temp++ = '.'; - temp += byte_to_ascii_decimal_unaligned(temp, (ipv4 & 0xFF)); - - return (temp - ptr); -} - -#ifdef TOBE_PORTED -/* - * edt: * * cnat_syslog_fill_ip_header - * - * Tries to fill the fields of the IP header before it - * is sent to the L3 infra node. - * - * Argument: cnat_syslog_logging_info_t *logging_info - * structure that contains the packet context - */ -inline -void cnat_syslog_fill_ip_header (cnat_syslog_logging_info_t *logging_info) -{ - spp_ctx_t *ctx; - - /* - * Fill in the IP header and port number of the Netflow collector - * The L3 Infra node will fill in the rest of the fields - */ - ctx = logging_info->current_logging_context; - fill_ip_n_udp_hdr(ctx, logging_info->ipv4_address, - logging_info->port, logging_info->pkt_length); - -} -#else -inline -void cnat_syslog_fill_ip_header (cnat_syslog_logging_info_t *logging_info) -{ - return; -} -#endif - -#ifndef TOBE_PORTED -void cnat_syslog_logging_init() -{ - return; -} - -void cnat_syslog_log_mapping_create(cnat_main_db_entry_t * db, - cnat_vrfmap_t *vrfmap) -{ - return; -} - -void cnat_syslog_log_mapping_delete(cnat_main_db_entry_t * db, - cnat_vrfmap_t *vrfmap) -{ - return; -} - -void cnat_syslog_ds_lite_port_limit_exceeded( - dslite_key_t * key, - dslite_table_entry_t *dslite_entry) -{ - return; -} - -void cnat_syslog_nat44_mapping_create(cnat_main_db_entry_t *db, - cnat_vrfmap_t *vrfmap, cnat_session_entry_t * sdb -#ifndef NO_BULK_LOGGING - , int bulk_alloc -#endif - ) -{ - return; -} - -/* Following are in cnat_util.c which are not ported */ -/* This function is defined in cnat_util.c which need to be ported */ -cnat_icmp_msg_t icmp_msg_gen_allowed () -{ - return 1; -} - -void cnat_syslog_nat44_mapping_delete(cnat_main_db_entry_t *db, - cnat_vrfmap_t *vrfmap, cnat_session_entry_t *sdb -#ifndef NO_BULK_LOGGING - , int bulk_alloc -#endif - ) -{ - return; -} - -u32 -cnat_get_unix_time_in_seconds (void) -{ - return 0; -} -#else /* TOBE_PORTED */ -void -cnat_syslog_dump_logging_context (u32 value1, - cnat_syslog_logging_info_t *logging_info, - u32 value2) -{ - u8 *pkt_ptr; - u32 i; - - if (PREDICT_TRUE(syslog_debug_flag == 0)) { - return; - } - /* - * Reduce the logging to few cores, to enable easier debugging - */ - if ((my_instance_number & 0x7) != 0) { - return; - } - printf("\nDumping %s packet at locn %d: time 0x%x", - (value2 == 1) ? "CURRENT" : "QUEUED", - value1, - cnat_get_unix_time_in_seconds()); - - printf("\ni_vrf 0x%x, ip_address 0x%x, port %d, pkt len %d", - 0 /* TO DP Add vrf like nfv9_logging_info->i_vrf */, - logging_info->ipv4_address, - logging_info->port, - logging_info->pkt_length); - printf("\n"); - - if (value2 == 1) { - pkt_ptr = logging_info->current_logging_context->packet_data; - } else { - pkt_ptr = logging_info->queued_logging_context->packet_data; - } - - /* - * Dump along with 8 bytes of SHIM header - */ - for (i = 0; i < - (logging_info->pkt_length + CNAT_NFV9_IP_HDR_OFFSET); - i = i + 1) { - u8 c1, c2, c3; - - if (i == 0) { - printf("\nL2_HEADER + SHIM_HEADER: \n"); - } else if (i == CNAT_NFV9_IP_HDR_OFFSET) { - printf("\nIP_HEADER: \n"); - } else if (i == CNAT_NFV9_UDP_HDR_OFFSET) { - printf("\nUDP_HEADER: \n"); - } else if (i == CNAT_NFV9_HDR_OFFSET) { - printf("\nSyslog content..\n"); - while(i < - (logging_info->pkt_length + CNAT_NFV9_HDR_OFFSET)) { - printf("%c", (u8)(*(pkt_ptr + i))); - i++; - if((u8)(*(pkt_ptr + i)) == '[') /* new record begins */ - printf("\n"); - } - return; - } - - c3 = *(pkt_ptr + i); - c2 = c3 & 0xf; - c1 = (c3 >> 4) & 0xf; - - printf("%c%c ", - ((c1 <= 9) ? (c1 + '0') : (c1 - 10 + 'a')), - ((c2 <= 9) ? (c2 + '0') : (c2 - 10 + 'a'))); - - } - - printf("\n"); -} - - -/* - * edt: * * cnat_syslog_send_pkt - * - * Tries to send a logging pkt. If the packet cannot be sent - * because of rewrite_output node cannot process it, queue - * it temporarily and try to send it later. - * - * Argument: cnat_syslog_logging_info_t *logging_info - * structure that contains the packet context - */ -inline -void cnat_syslog_send_pkt (cnat_syslog_logging_info_t *logging_info) -{ - spp_node_t *output_node; - - cnat_syslog_fill_ip_header(logging_info); - - output_node = spp_get_nodes() + - cnat_syslog_global_info.cnat_syslog_disp_node_index; - - cnat_syslog_dump_logging_context (2, logging_info, 1); - - if (PREDICT_TRUE(output_node->sf.nused < SPP_MAXDISPATCH)) { - /* - * Move the logging context to output node - */ - logging_info->current_logging_context->current_length = - logging_info->pkt_length; - PLATFORM_SET_CTX_RU_TX_FROM_NODE(logging_info->current_logging_context, \ - NODE_LOGGING); - spp_dispatch_make_node_runnable(output_node); - output_node->sf.ctxs[output_node->sf.nused++] = - logging_info->current_logging_context; - - if(PREDICT_FALSE(syslog_debug_flag > 10)) - printf("\nSyslog: 2. Sending Current packet\n"); - } else { - /* - * Queue the context into the logging_info structure, - * We will try to send it later. Currently, we will - * restrict to only one context queued. - */ - cnat_syslog_global_counter.downstream_constipation_count++; - if(PREDICT_FALSE(syslog_debug_flag > 10)) - printf("\nSyslog: 2. Downstream congestion \n"); - - /* - * Attach the current logging context which is full to the - * queued context list in logging_info structure - */ - logging_info->queued_logging_context = - logging_info->current_logging_context; - } - - /* - * Whether the context is queued or not, set the current context index - * to EMPTY, as the earlier context can no more be used to send - * more logging records. - */ - logging_info->current_logging_context = NULL; -} - - -/* - * edt: * * cnat_syslog_send_queued_pkt - * - * Tries to send a logging pkt that has been queued earlier - * because it could not be sent due to downstream constipation - * - * Argument: cnat_syslog_logging_info_t *logging_info - * structure that contains the packet context - */ -inline -void cnat_syslog_send_queued_pkt (cnat_syslog_logging_info_t *logging_info) -{ - spp_node_t *output_node; - - output_node = spp_get_nodes() + - cnat_syslog_global_info.cnat_syslog_disp_node_index; - - cnat_syslog_dump_logging_context(1, logging_info, 2); - - if(PREDICT_TRUE(output_node->sf.nused < SPP_MAXDISPATCH)) { - /* - * Move the logging context to output node - */ - /** This looks like a bug to me .. need to confirm ***** - logging_info->queued_logging_context->current_length = - nfv9_logging_info->pkt_length; ***/ - PLATFORM_SET_CTX_RU_TX_FROM_NODE(logging_info->queued_logging_context, - NODE_LOGGING) - spp_dispatch_make_node_runnable(output_node); - output_node->sf.ctxs[output_node->sf.nused++] = - logging_info->queued_logging_context; - - SYSLOG_DEBUG_PRINTF1("\nSYSLOG: 1. Sending Queued packet\n") - - /* - * Context has been queued, it will be freed after the pkt - * is sent. Clear this from the logging_context_info structure - */ - logging_info->queued_logging_context = NULL; - - } else { - cnat_syslog_global_counter.downstream_constipation_count++; - } -} - -/* - * edt: * * handle_pending_syslog_pkts - * - * Timer handler for sending any pending syslog record - * - */ -inline -void handle_pending_syslog_pkts() -{ - spp_node_t *output_node; - cnat_syslog_logging_info_t *my_logging_info = 0; - u32 current_timestamp = cnat_get_sys_up_time_in_ms(); - i16 sf_nused; - - output_node = spp_get_nodes() + - cnat_syslog_global_info.cnat_syslog_disp_node_index; - - sf_nused = output_node->sf.nused; - - pool_foreach (my_logging_info, cnat_syslog_logging_info_pool, ({ - /* - * Check if no more logging contexts can be queued - */ - if (PREDICT_FALSE(sf_nused >= SPP_MAXDISPATCH)) { - break; - } - if (my_logging_info->queued_logging_context) - cnat_syslog_send_queued_pkt (my_logging_info); - - if(my_logging_info->current_logging_context && - ((current_timestamp - - my_logging_info->current_logging_context_timestamp) - > 1000)) { - /* - * If there is a current logging context and timestamp - * indicates it is pending for long, send it out - * Also if there is a queued context send it out as well - */ - SYSLOG_DEBUG_PRINTF4("\nLOG_TIMER: queued %p, curr %p, sf_nused %d", - my_logging_info->queued_logging_context, - my_logging_info->current_logging_context, - sf_nused); - cnat_syslog_send_pkt(my_logging_info); - } - })); -} - -const unsigned char hex_numbers_single_digit[] = - { '0', '1', '2', '3', '4', '5', '6', '7', '8', - '9', 'a', 'b', 'c', 'd', 'e', 'f' }; - -inline static int u16_to_ascii_decimal_aligned( - unsigned char *ptr, u16 num, u16 min_digits) -{ - /* The logic below is replicated in - * function u16_to_ascii_decimal_unaligned - * except the use of min_digits - * Replication is done to optimize run time - * if you fix a bug here, check u16_to_ascii_decimal_unaligned - * as well (and vice versa) - */ - unsigned char *temp = ptr; - int no_leading_zeros = 0; - - if(num > 9999 || min_digits == 5) { - *temp++ = hex_numbers_single_digit[num/10000]; - num = num%10000; - no_leading_zeros = 1; - } - - if(no_leading_zeros || num > 999 || min_digits == 4) { - *temp++ = hex_numbers_single_digit[num/1000]; - num = num%1000; - no_leading_zeros = 1; - } - - if(no_leading_zeros || num > 99 || min_digits == 3) { - *temp++ = hex_numbers_single_digit[num/100]; - num = num%100; - no_leading_zeros = 1; - } - - if(no_leading_zeros || num > 9 || min_digits == 2) { - *temp++ = hex_numbers_single_digit[num/10]; - num = num%10; - } - - *temp++ = hex_numbers_single_digit[num]; - - return temp-ptr; -} - -inline static int u16_to_ascii_decimal_unaligned( - unsigned char *ptr, u16 num) -{ - /* - * return u16_to_ascii_decimal_aligned(ptr, num, 0); - * should do the job.. however, to opimize the run time - * the code of u16_to_ascii_decimal_aligned is being - * repeated here without the use of min_digits - * if you fix a bug here, please check - * u16_to_ascii_decimal_aligned as well (and vice versa) - */ - unsigned char *temp = ptr; - int no_leading_zeros = 0; - - if(num > 9999) { - *temp++ = hex_numbers_single_digit[num/10000]; - num = num%10000; - no_leading_zeros = 1; - } - - if(no_leading_zeros || num > 999) { - *temp++ = hex_numbers_single_digit[num/1000]; - num = num%1000; - no_leading_zeros = 1; - } - - if(no_leading_zeros || num > 99) { - *temp++ = hex_numbers_single_digit[num/100]; - num = num%100; - no_leading_zeros = 1; - } - - if(no_leading_zeros || num > 9) { - *temp++ = hex_numbers_single_digit[num/10]; - num = num%10; - } - - *temp++ = hex_numbers_single_digit[num]; - - return temp-ptr; -} - -static int syslog_get_timestamp(unsigned char *ts) -{ - static const char *months[] = {"Jan ", "Feb ", "Mar ", "Apr ", "May ", - "Jun ", "Jul ", "Aug ", "Sep ", "Oct ", "Nov ", "Dec " }; - - unsigned char *temp = ts; - /* Inserts time stamp in the syslog format and returns lenght - * assumes that ts has sufficient space - */ - /* China Telecom has demanded that the time stamp has to be - * in the format '2011 Jun 7 12:34:08' - */ - time_t time = (time_t)cnat_get_unix_time_in_seconds(); - struct tm tm1; - - gmtime_r(&time, &tm1); - /* Now put the pieces together */ - /* Year */ - ts += u16_to_ascii_decimal_unaligned(ts, (tm1.tm_year + 1900)); - *ts++ = SYSLOG_DELIMITER; - /* Month */ - clib_memcpy(ts, months[tm1.tm_mon], 4); - ts += 4; /* DELIMITER taken care */ - /* day */ - ts += u16_to_ascii_decimal_unaligned(ts, tm1.tm_mday); - *ts++ = SYSLOG_DELIMITER; - /* hours */ - ts += u16_to_ascii_decimal_aligned(ts, tm1.tm_hour, 2); - *ts++ = ':'; - /* minutes */ - ts += u16_to_ascii_decimal_aligned(ts, tm1.tm_min, 2); - *ts++ = ':'; - /* seconds */ - ts += u16_to_ascii_decimal_aligned(ts, tm1.tm_sec, 2); - return ts - temp; -} - -/* Ensure that the order of the below array matches with - * syslog_service_type enum - */ -static char *syslog_service_string[] = { "NAT44", "DSLITE" }; - -/* Ensure that the order of below array matches with - * syslog_event_type_t enum - */ -typedef struct { - char *event_name; - int name_length; -} syslog_event_description_type; - -const static syslog_event_description_type sys_log_event[] = { - { "UserbasedA", 10 }, /* yes, 10 is strlen of "UserbasedA" */ - { "UserbasedW", 10 }, - { "SessionbasedA", 13 }, - { "SessionbasedW", 13 }, - { "SessionbasedAD", 14 }, - { "SessionbasedWD", 14 }, - { "Portblockrunout", 15 }, - { "TCPseqmismatch", 14}, - { "Invalid", 7 } -}; - -inline static int syslog_fill_header(const cnat_syslog_logging_info_t *log_info, - syslog_service_type_t s_type) -{ - /* Forms the syslog header and returns the lenght - * Assumes that header has sufficient space - */ - - /* Sample header (as agreed for China Telecom requirements -- - * <134> 1 2011 May 31 10:30:45 192.168.2.3 - - NAT44 - - */ - - unsigned char *temp, *header; - int count; - temp = header = (unsigned char *) - &(log_info->current_logging_context->packet_data[CNAT_NFV9_HDR_OFFSET]); - *temp++ = '<'; - temp += byte_to_ascii_decimal_unaligned(temp, - log_info->header_priority); - *temp++ = '>'; - *temp++ = SYSLOG_DELIMITER; - *temp++ = '1'; /* Syslog version -- always set to 1 */ - *temp++ = SYSLOG_DELIMITER; - temp += syslog_get_timestamp(temp); - *temp++ = SYSLOG_DELIMITER; - count = strlen(log_info->header_hostname); - clib_memcpy(temp, log_info->header_hostname, count); - temp += count; - *temp++ = SYSLOG_DELIMITER; - *temp++ = SYSLOG_FIELD_ABSENT; /* App name - nil value */ - *temp++ = SYSLOG_DELIMITER; - *temp++ = SYSLOG_FIELD_ABSENT; /* Proc ID - nil value for now */ - *temp++ = SYSLOG_DELIMITER; - /* Now the msg id */ - count = strlen(syslog_service_string[s_type]); - clib_memcpy(temp, syslog_service_string[s_type], count); - temp += count; - *temp++ = SYSLOG_DELIMITER; - *temp++ = SYSLOG_FIELD_ABSENT; /* No structured elements */ - *temp++ = SYSLOG_DELIMITER; -#ifdef SHOW_SYSLOG_TIMESTAMP - printf("\nSysLog TS: %s : Length %d", header, temp - header); -#endif /* SHOW_SYSLOG_TIMESTAMP */ - return temp-header; -} - -extern void cnat_logging_init(); - -/* one time call at the beginning */ -void cnat_syslog_logging_init() -{ - if(PREDICT_TRUE(cnat_syslog_global_info.cnat_syslog_init_done)) - return; /* Already done */ - - cnat_logging_init(); - cnat_syslog_global_info.cnat_syslog_disp_node_index = - spp_lookup_node_index(PLATFORM_SYSLOG_DISP_NODE_IDX); - ASSERT(cnat_syslog_global_info.cnat_syslog_disp_node_index != (u16)~0); - - cnat_syslog_global_info.cnat_syslog_init_done = 1; -} - -/* - * edt: * * cnat_syslog_create_logging_context - * - * Tries to create a logging context with packet buffer - * to send a new logging packet - * - * Argument: cnat_syslog_logging_info_t *logging_info - * structure that contains the logging info and will store - * the packet context as well. - */ -inline -void cnat_syslog_create_logging_context ( - cnat_syslog_logging_info_t *logging_info, - syslog_service_type_t s_type) -{ - spp_ctx_t *ctx; - - /* - * If queued_logging_context_index is non-EMPTY, we already have a logging - * packet queued to be sent. First try sending this before allocating - * a new context. We can have only one active packet context per - * logging_info structure - */ - - if (PREDICT_FALSE(logging_info->queued_logging_context != NULL)) { - cnat_syslog_send_queued_pkt(logging_info); - /* - * If we cannot still send the queued pkt, just return - * Downstream Constipation count would have increased anyway - */ - if (logging_info->queued_logging_context != NULL) { - cnat_syslog_global_counter.logging_context_creation_deferred_count++; - return; - } - } - - /* - * If no context can be allocated, return silently - * calling routine will handle updating the error counters - */ - if (spp_ctx_alloc(&ctx, 1) < 1) { - cnat_syslog_global_counter.logging_context_creation_fail_count++; - SYSLOG_DEBUG_PRINTF1("\nCould not allocate ctx for syslog"); - return; - } - - // Allocate packet buffer (used for AVSM currently) - PLATFORM_ALLOC_NFV9_PKT_BUFFER(ctx, 0); - - logging_info->current_logging_context = ctx; - - PLATFORM_SET_CTX_RU_TX_FROM_NODE(ctx, NODE_LOGGING); - - ctx->flags = SPP_CTX_END_OF_PACKET; - ctx->next_ctx_this_packet = (spp_ctx_t*) SPP_CTX_NO_NEXT_CTX; - ctx->current_header = &ctx->packet_data[CNAT_NFV9_HDR_OFFSET]; - - logging_info->pkt_length = syslog_fill_header(logging_info, s_type); - logging_info->pkt_length += (CNAT_NFV9_HDR_OFFSET - - CNAT_NFV9_IP_HDR_OFFSET); - logging_info->current_logging_context_timestamp = - cnat_get_sys_up_time_in_ms(); - -} - -inline static int u16_to_ascii_hex_unaligned( - unsigned char *ptr, u16 num) -{ - unsigned char nibble, *temp; - int no_leading_zeros = 0; - temp = ptr; - nibble = (num >> 12); - if(nibble) { - *temp++ = hex_numbers_single_digit[nibble]; - no_leading_zeros = 1; - } - - nibble = (num >> 8) & 0xF; - if(nibble || no_leading_zeros) { - *temp++ = hex_numbers_single_digit[nibble]; - no_leading_zeros = 1; - } - - nibble = (num >> 4) & 0xF; - if(nibble || no_leading_zeros) { - *temp++ = hex_numbers_single_digit[nibble]; - } - - *temp++ = hex_numbers_single_digit[num & 0xF]; - - return temp-ptr; -} - -inline static int ipv6_int_2_str(u32 ipv6[], unsigned char *ipv6_str) -{ -/* DC stands for Double Colon. - * Refer http://tools.ietf.org/html/rfc5952 for - * more details on text representations of - * IPV6 address - */ -#define DC_NOT_USED_YET 0 -#define DC_IN_USE 1 /* Zeros are skipped */ -#define DC_ALREADY_USED 2 /* Cannot skip zeros anymore */ - int i; - u16 *ipv6_temp = (u16 *)ipv6; - unsigned char *temp = ipv6_str; - int double_colon = DC_NOT_USED_YET; - for(i = 0; i < 7; i++) { - if(ipv6_temp[i]) { - ipv6_str += u16_to_ascii_hex_unaligned(ipv6_str, ipv6_temp[i]); - *ipv6_str++ = ':'; - if(double_colon == DC_IN_USE) { /* Cannot use DC anymore */ - double_colon = DC_ALREADY_USED; - } - } else { - if(double_colon == DC_IN_USE) { - /* Skip this zero as well */ - continue; - } else if((ipv6_temp[i+1]) - /* DC makes sense if there is more than one contiguous zero */ - || (double_colon != DC_NOT_USED_YET)) { - ipv6_str += u16_to_ascii_hex_unaligned(ipv6_str, - ipv6_temp[i]); - *ipv6_str++ = ':'; - } else { /* Start using DC */ - *ipv6_str++ = ':'; /* The 2nd colon */ - double_colon = DC_IN_USE; - } - } - } - if(ipv6_temp[7]) { - ipv6_str += u16_to_ascii_hex_unaligned(ipv6_str, ipv6_temp[7]); - } else if(double_colon != DC_IN_USE) { - *ipv6_str++ = '0'; - } - *ipv6_str = 0; - - return ipv6_str - temp; -} - -/* insert syslog record for nat44 */ - -void cnat_syslog_insert_nat44_record( - cnat_syslog_logging_info_t *log_info, - cnat_main_db_entry_t *db, cnat_vrfmap_t *vrfmap, - cnat_session_entry_t *sdb, int bulk_alloc, syslog_event_type_t e_type) -{ - /* This record should like this - - * [EventName - * < Translated Source IP> - * - * ] - */ - u32 original_source = db->in2out_key.k.ipv4; - u32 translated_ip = db->out2in_key.k.ipv4; - cnat_user_db_entry_t *udb = cnat_user_db + db->user_index; - unsigned char *temp, *record; - u32 network_order_ipv6[4]; - - SYSLOG_CONFIG_DEBUG_PRINTF(4,"In Function %s\n", __func__); - temp = record = &(log_info->current_logging_context->packet_data[ - CNAT_NFV9_IP_HDR_OFFSET + log_info->pkt_length]); - - if (PREDICT_FALSE(!udb)) { - SYSLOG_DEBUG_PRINTF1("\nnull udb!"); - return; - } - - /* Now we point to the location where record needs to be inserted */ - *record++ = '['; /* Open the record */ - - /* Copy the record type */ - clib_memcpy(record, sys_log_event[e_type].event_name, - sys_log_event[e_type].name_length); - record += sys_log_event[e_type].name_length; - *record++ = SYSLOG_DELIMITER; - - /* Copy the Protocol type */ - if(PREDICT_FALSE( - e_type == sessionbased_assign || e_type == sessionbased_withdraw || - e_type == sessionbased_assignD || e_type == sessionbased_withdrawD)) { - u16 my_proto_mask; - my_proto_mask = db->in2out_key.k.vrf & CNAT_PRO_MASK; - if(PREDICT_TRUE(my_proto_mask == CNAT_TCP)) { - *record++ = '6'; - } else if(PREDICT_TRUE(my_proto_mask == CNAT_UDP)) { - *record++ = '1'; - *record++ = '7'; - } else if(PREDICT_TRUE(my_proto_mask == CNAT_ICMP)) { - *record++ = '1'; - } else { /* Default, assume GRE (for PPTP) */ - *record++ = '4'; - *record++ = '7'; - } - } else { - *record++ = SYSLOG_FIELD_ABSENT; - } - *record++ = SYSLOG_DELIMITER; - - /* Copy the Original Source IP */ - record += copy_ipv4_addr(record, original_source); - *record++ = SYSLOG_DELIMITER; - - /* copy configured VRF NAME */ - clib_memcpy(record, log_info->vrf_name, log_info->vrf_name_len); - record += log_info->vrf_name_len; - *record++ = SYSLOG_DELIMITER; - - /* No IPV6 source address for nat44 */ - *record++ = SYSLOG_FIELD_ABSENT; - *record++ = SYSLOG_DELIMITER; - - /* Copy the translated IP address */ - record += copy_ipv4_addr(record, translated_ip); - *record++ = SYSLOG_DELIMITER; - - /* Copy the Original port */ - if(e_type == sessionbased_assign || e_type == sessionbased_withdraw || - e_type == sessionbased_assignD || e_type == sessionbased_withdrawD) { - record += u16_to_ascii_decimal_unaligned( - record, db->in2out_key.k.port); - } else { - *record++ = SYSLOG_FIELD_ABSENT; - } - *record++ = SYSLOG_DELIMITER; - - /* Copy the start outside port */ - record += u16_to_ascii_decimal_unaligned(record, bulk_alloc); - *record++ = SYSLOG_DELIMITER; - - /* Copy the last outside port */ - if(e_type == userbased_assign || e_type == userbased_withdraw) { - record += u16_to_ascii_decimal_unaligned(record, - (bulk_alloc + BULKSIZE_FROM_VRFMAP(vrfmap) - 1)); - } else { - *record++ = SYSLOG_FIELD_ABSENT; - } - *record++ = SYSLOG_DELIMITER; - - /* Copy destination ip and port in case for DBL*/ - if(PREDICT_FALSE(e_type == sessionbased_assignD || e_type == sessionbased_withdrawD)) { - if(PREDICT_TRUE(sdb == NULL)) { - record += copy_ipv4_addr(record,db->dst_ipv4); - *record++ = SYSLOG_DELIMITER; - record += u16_to_ascii_decimal_unaligned(record, db->dst_port); - } else { - record += copy_ipv4_addr(record, sdb->v4_dest_key.k.ipv4); - *record++ = SYSLOG_DELIMITER; - record += u16_to_ascii_decimal_unaligned(record, sdb->v4_dest_key.k.port); - } - } else { - *record++ = '-'; - *record++ = SYSLOG_DELIMITER; - *record++ = '-'; - } - *record++ = SYSLOG_DELIMITER; - - *record++ = ']'; /* End of the reocrd */ - - log_info->pkt_length += record - temp; -} - -void cnat_syslog_insert_record( - cnat_syslog_logging_info_t *log_info, - cnat_main_db_entry_t *db, dslite_table_entry_t *dslite_entry, - cnat_session_entry_t *sdb, int bulk_alloc, syslog_event_type_t e_type) -{ - /* This record should like this - - * [EventName - * < Translated Source IP> - * - * ] - */ - u32 original_source = db->in2out_key.k.ipv4; - u32 translated_ip = db->out2in_key.k.ipv4; - cnat_user_db_entry_t *udb = cnat_user_db + db->user_index; - unsigned char *temp, *record; - u32 network_order_ipv6[4]; - - temp = record = &(log_info->current_logging_context->packet_data[ - CNAT_NFV9_IP_HDR_OFFSET + log_info->pkt_length]); - - if (PREDICT_FALSE(!udb)) { - SYSLOG_DEBUG_PRINTF1("\nnull udb!"); - return; - } - - /* Now we point to the location where record needs to be inserted */ - *record++ = '['; /* Open the record */ - - /* Copy the record type */ - clib_memcpy(record, sys_log_event[e_type].event_name, - sys_log_event[e_type].name_length); - record += sys_log_event[e_type].name_length; - *record++ = SYSLOG_DELIMITER; - - /* Copy the Protocol type */ - if(PREDICT_FALSE( - e_type == sessionbased_assign || e_type == sessionbased_withdraw || - e_type == sessionbased_assignD || e_type == sessionbased_withdrawD)) { - u16 my_proto_mask; - my_proto_mask = db->in2out_key.k.vrf & CNAT_PRO_MASK; - if(PREDICT_TRUE(my_proto_mask == CNAT_TCP)) { - *record++ = '6'; - } else if(PREDICT_TRUE(my_proto_mask == CNAT_UDP)) { - *record++ = '1'; - *record++ = '7'; - } else { - *record++ = '1'; - } - } else { - *record++ = SYSLOG_FIELD_ABSENT; - } - - *record++ = SYSLOG_DELIMITER; - - /* Copy the Original Source IP */ -#ifdef DSLITE_USER_IPV4 - record += copy_ipv4_addr(record, original_source); -#else - /* - * Do not include inside ipv4 address for B4 element level port limiting - */ - *record++ = SYSLOG_FIELD_ABSENT; -#endif - *record++ = SYSLOG_DELIMITER; - - /* copy configured VRF NAME */ - clib_memcpy(record, log_info->vrf_name, log_info->vrf_name_len); - record += log_info->vrf_name_len; - *record++ = SYSLOG_DELIMITER; - - /* Copy the IPV6 source address */ - /* CSCtt16960 Fix. */ - network_order_ipv6[0] = htonl(udb->ipv6[0]); - network_order_ipv6[1] = htonl(udb->ipv6[1]); - network_order_ipv6[2] = htonl(udb->ipv6[2]); - network_order_ipv6[3] = htonl(udb->ipv6[3]); - - inet_ntop(AF_INET6,network_order_ipv6,record,INET6_ADDRSTRLEN); - record += strlen(record); - *record++ = SYSLOG_DELIMITER; - - /* Copy the translated IP address */ - record += copy_ipv4_addr(record, translated_ip); - *record++ = SYSLOG_DELIMITER; - - /* Copy the Original port */ - if(e_type == sessionbased_assign || e_type == sessionbased_withdraw || - e_type == sessionbased_assignD || e_type == sessionbased_withdrawD) { - record += u16_to_ascii_decimal_unaligned( - record, db->in2out_key.k.port); - } else { - *record++ = SYSLOG_FIELD_ABSENT; - } - *record++ = SYSLOG_DELIMITER; - - /* Copy the start outside port */ - record += u16_to_ascii_decimal_unaligned(record, bulk_alloc); - *record++ = SYSLOG_DELIMITER; - - /* Copy the last outside port */ - if(e_type == userbased_assign || e_type == userbased_withdraw) { - record += u16_to_ascii_decimal_unaligned(record, - (bulk_alloc + BULKSIZE_FROM_VRFMAP(dslite_entry) - 1)); - } else { - *record++ = SYSLOG_FIELD_ABSENT; - } - *record++ = SYSLOG_DELIMITER; - - if(PREDICT_FALSE(e_type == sessionbased_assignD || e_type == sessionbased_withdrawD)) { - if(sdb == NULL) { - record += copy_ipv4_addr(record, db->dst_ipv4); - *record++ = SYSLOG_DELIMITER; - record += u16_to_ascii_decimal_unaligned(record, db->dst_port); - } else { - record += copy_ipv4_addr(record, sdb->v4_dest_key.k.ipv4); - *record++ = SYSLOG_DELIMITER; - record += u16_to_ascii_decimal_unaligned(record, sdb->v4_dest_key.k.port); - } - } else { - *record++ = '-'; - *record++ = SYSLOG_DELIMITER; - *record++ = '-'; - } - *record++ = SYSLOG_DELIMITER; - - *record++ = ']'; /* End of the reocrd */ - - log_info->pkt_length += record - temp; -} - -#define SYSLOG_PRECHECK(entry, s_type) \ - if(PREDICT_FALSE((entry)->syslog_logging_index == EMPTY)) { \ - SYSLOG_DEBUG_PRINTF1("\n1. Log Mapping failed") \ - return; \ - } \ - logging_info = \ - cnat_syslog_logging_info_pool + (entry)->syslog_logging_index; \ - if(PREDICT_FALSE(logging_info->current_logging_context == NULL)) { \ - cnat_syslog_create_logging_context(logging_info, s_type); \ - if(PREDICT_FALSE(logging_info->current_logging_context == NULL)) { \ - SYSLOG_DEBUG_PRINTF1("\n2. Log Mapping failed") \ - return; \ - } \ - } - -void cnat_syslog_nat44_mapping_create(cnat_main_db_entry_t *db, - cnat_vrfmap_t *vrfmap, cnat_session_entry_t * sdb -#ifndef NO_BULK_LOGGING - , int bulk_alloc -#endif - ) -{ - cnat_syslog_logging_info_t *logging_info = 0; - syslog_event_type_t e_type; - int start_port; - - SYSLOG_CONFIG_DEBUG_PRINTF(4,"In Function %s\n", __func__); - SYSLOG_PRECHECK(vrfmap, NAT44) - -#ifndef NO_BULK_LOGGING - if(bulk_alloc > 0) { /* new bulk alloc - use bulk add template */ - e_type = userbased_assign; - start_port = bulk_alloc; - } else if(bulk_alloc == CACHE_ALLOC_NO_LOG_REQUIRED) { - return; /* No logging required.. bulk port usage */ - } - else { /* Individual logging .. fall back to old method */ -#endif - if(vrfmap->syslog_logging_policy == SESSION_LOG_ENABLE) { - e_type = sessionbased_assignD; - } else { - e_type = sessionbased_assign; - } - start_port = db->out2in_key.k.port; -#ifndef NO_BULK_LOGGING - } -#endif - - cnat_syslog_insert_nat44_record(logging_info, db, vrfmap, sdb, - start_port, e_type); - - /* - * If we have exceeded the packet length, let us send the - * packet now. There is buffer of additional bytes beyond - * max_pkt_length to ensure that the last add/delete record - * can be stored safely. - */ - - if (PREDICT_FALSE(logging_info->pkt_length > - logging_info->max_length_minus_max_record_size)) { - cnat_syslog_send_pkt(logging_info); - } -} - -void cnat_syslog_ds_lite_mapping_create(cnat_main_db_entry_t *db, - dslite_table_entry_t *dslite_entry, cnat_session_entry_t *sdb -#ifndef NO_BULK_LOGGING - , int bulk_alloc -#endif - ) -{ - cnat_syslog_logging_info_t *logging_info = 0; - syslog_event_type_t e_type; - int start_port; - - SYSLOG_PRECHECK(dslite_entry, DSLite) - -#ifndef NO_BULK_LOGGING - if(bulk_alloc > 0) { /* new bulk alloc - use bulk add template */ - e_type = userbased_assign; - start_port = bulk_alloc; - } else if(bulk_alloc == CACHE_ALLOC_NO_LOG_REQUIRED) { - return; /* No logging required.. bulk port usage */ - } - else { /* Individual logging .. fall back to old method */ -#endif - if(PREDICT_FALSE(dslite_entry->syslog_logging_policy == SESSION_LOG_ENABLE)) { - e_type = sessionbased_assignD; - } else { - e_type = sessionbased_assign; - } - start_port = db->out2in_key.k.port; -#ifndef NO_BULK_LOGGING - } -#endif - - cnat_syslog_insert_record(logging_info, db, dslite_entry, sdb, - start_port, e_type); - - /* - * If we have exceeded the packet length, let us send the - * packet now. There is buffer of additional bytes beyond - * max_pkt_length to ensure that the last add/delete record - * can be stored safely. - */ - - if (PREDICT_FALSE(logging_info->pkt_length > - logging_info->max_length_minus_max_record_size)) { - cnat_syslog_send_pkt(logging_info); - } -} - -void cnat_syslog_nat44_mapping_delete(cnat_main_db_entry_t *db, - cnat_vrfmap_t *vrfmap, cnat_session_entry_t *sdb -#ifndef NO_BULK_LOGGING - , int bulk_alloc -#endif - ) -{ - cnat_syslog_logging_info_t *logging_info = 0; - syslog_event_type_t e_type; - int start_port; - - SYSLOG_CONFIG_DEBUG_PRINTF(4,"In Function %s\n", __func__); - SYSLOG_PRECHECK(vrfmap, NAT44) - -#ifndef NO_BULK_LOGGING - if(bulk_alloc > 0) { /* new bulk alloc - use bulk add template */ - e_type = userbased_withdraw; - start_port = bulk_alloc; - } else if(bulk_alloc == CACHE_ALLOC_NO_LOG_REQUIRED) { - return; /* No logging required.. bulk port usage */ - } - else { /* Individual logging .. fall back to old method */ -#endif - if(vrfmap->syslog_logging_policy == SESSION_LOG_ENABLE) { - e_type = sessionbased_withdrawD; - } else { - e_type = sessionbased_withdraw; - } - start_port = db->out2in_key.k.port; -#ifndef NO_BULK_LOGGING - } -#endif - cnat_syslog_insert_nat44_record(logging_info, db, vrfmap, sdb, - start_port, e_type); - /* - * If we have exceeded the packet length, let us send the - * packet now. There is buffer of additional bytes beyond - * max_pkt_length to ensure that the last add/delete record - * can be stored safely. - */ - if (PREDICT_FALSE(logging_info->pkt_length > - logging_info->max_length_minus_max_record_size)) { - cnat_syslog_send_pkt(logging_info); - } -} - -void cnat_syslog_ds_lite_mapping_delete(cnat_main_db_entry_t *db, - dslite_table_entry_t *dslite_entry, cnat_session_entry_t *sdb -#ifndef NO_BULK_LOGGING - , int bulk_alloc -#endif - ) -{ - cnat_syslog_logging_info_t *logging_info = 0; - syslog_event_type_t e_type; - int start_port; - - SYSLOG_PRECHECK(dslite_entry, DSLite) - -#ifndef NO_BULK_LOGGING - if(bulk_alloc > 0) { /* new bulk alloc - use bulk add template */ - e_type = userbased_withdraw; - start_port = bulk_alloc; - } else if(bulk_alloc == CACHE_ALLOC_NO_LOG_REQUIRED) { - return; /* No logging required.. bulk port usage */ - } - else { /* Individual logging .. fall back to old method */ -#endif - if(PREDICT_FALSE(dslite_entry->syslog_logging_policy == SESSION_LOG_ENABLE)) { - e_type = sessionbased_withdrawD; - } else { - e_type = sessionbased_withdraw; - } - start_port = db->out2in_key.k.port; -#ifndef NO_BULK_LOGGING - } -#endif - cnat_syslog_insert_record(logging_info, db, dslite_entry, sdb, - start_port, e_type); - - /* - * If we have exceeded the packet length, let us send the - * packet now. There is buffer of additional bytes beyond - * max_pkt_length to ensure that the last add/delete record - * can be stored safely. - */ - - if (PREDICT_FALSE(logging_info->pkt_length > - logging_info->max_length_minus_max_record_size)) { - cnat_syslog_send_pkt(logging_info); - } -} - -void cnat_syslog_dslite_insert_port_exceeded( - cnat_syslog_logging_info_t *log_info, - dslite_key_t * key) -{ - /* This record should like this - - * [Portblockrunout - * - - - - -] - */ - u32 network_order_ipv6[4]; - unsigned char *temp, *record; - - temp = record = &(log_info->current_logging_context->packet_data[ - CNAT_NFV9_IP_HDR_OFFSET + log_info->pkt_length]); - - /* Now we point to the location where record needs to be inserted */ - *record++ = '['; /* Open the record */ - - /* Copy the record type */ - clib_memcpy(record, sys_log_event[port_block_runout].event_name, - sys_log_event[port_block_runout].name_length); - record += sys_log_event[port_block_runout].name_length; - *record++ = SYSLOG_DELIMITER; - - u16 my_proto_mask; - my_proto_mask = key->ipv4_key.k.vrf & CNAT_PRO_MASK; - if(PREDICT_TRUE(my_proto_mask == CNAT_TCP)) { - *record++ = '6'; - } else if(PREDICT_TRUE(my_proto_mask == CNAT_UDP)) { - *record++ = '1'; - *record++ = '7'; - } else { - *record++ = '1'; - } - *record++ = SYSLOG_DELIMITER; - - /* Copy the Original Source IP */ - record += copy_ipv4_addr(record, key->ipv4_key.k.ipv4); - *record++ = SYSLOG_DELIMITER; - - /* copy configured VRF NAME */ - clib_memcpy(record, log_info->vrf_name, log_info->vrf_name_len); - record += log_info->vrf_name_len; - *record++ = SYSLOG_DELIMITER; - - /* Copy the IPV6 source address */ - network_order_ipv6[0] = htonl(key->ipv6[0]); - network_order_ipv6[1] = htonl(key->ipv6[1]); - network_order_ipv6[2] = htonl(key->ipv6[2]); - network_order_ipv6[3] = htonl(key->ipv6[3]); - - inet_ntop(AF_INET6,network_order_ipv6,record,INET6_ADDRSTRLEN); - record += strlen(record); - *record++ = SYSLOG_DELIMITER; - - *record++ = SYSLOG_FIELD_ABSENT; /* No translated source ip */ - *record++ = SYSLOG_DELIMITER; - - record += u16_to_ascii_decimal_unaligned( - record, key->ipv4_key.k.port); - *record++ = SYSLOG_DELIMITER; - - *record++ = SYSLOG_FIELD_ABSENT; /* No translated start port */ - *record++ = SYSLOG_DELIMITER; - - *record++ = SYSLOG_FIELD_ABSENT; /* No translated end port */ - *record++ = SYSLOG_DELIMITER; - - /*No Destination Info*/ - *record++ = '-'; - *record++ = SYSLOG_DELIMITER; - *record++ = '-'; - *record++ = SYSLOG_DELIMITER; - - *record++ = ']'; /* End of the reocrd */ - - log_info->pkt_length += record - temp; -} - -void cnat_syslog_ds_lite_port_limit_exceeded( - dslite_key_t * key, - dslite_table_entry_t *dslite_entry) -{ - cnat_syslog_logging_info_t *logging_info = 0; - - SYSLOG_PRECHECK(dslite_entry, DSLite) - - cnat_syslog_dslite_insert_port_exceeded(logging_info, key); - - /* - * If we have exceeded the packet length, let us send the - * packet now. There is buffer of additional bytes beyond - * max_pkt_length to ensure that the last add/delete record - * can be stored safely. - */ - - if (PREDICT_FALSE(logging_info->pkt_length > - logging_info->max_length_minus_max_record_size)) { - cnat_syslog_send_pkt(logging_info); - } -} - -void cnat_syslog_nat44_insert_port_exceeded( - cnat_syslog_logging_info_t *log_info, - cnat_key_t * key) -{ - /* This record should like this - - * [Portblockrunout - * - - - - - -] - */ - unsigned char *temp, *record; - - temp = record = &(log_info->current_logging_context->packet_data[ - CNAT_NFV9_IP_HDR_OFFSET + log_info->pkt_length]); - - /* Now we point to the location where record needs to be inserted */ - *record++ = '['; /* Open the record */ - - /* Copy the record type */ - clib_memcpy(record, sys_log_event[port_block_runout].event_name, - sys_log_event[port_block_runout].name_length); - record += sys_log_event[port_block_runout].name_length; - *record++ = SYSLOG_DELIMITER; - - u16 my_proto_mask; - my_proto_mask = key->k.vrf & CNAT_PRO_MASK; - if(PREDICT_TRUE(my_proto_mask == CNAT_TCP)) { - *record++ = '6'; - } else if(PREDICT_TRUE(my_proto_mask == CNAT_UDP)) { - *record++ = '1'; - *record++ = '7'; - } else { - *record++ = '1'; - } - *record++ = SYSLOG_DELIMITER; - - /* Copy the Original Source IP */ - record += copy_ipv4_addr(record, key->k.ipv4); - *record++ = SYSLOG_DELIMITER; - - /* copy configured VRF NAME */ - clib_memcpy(record, log_info->vrf_name, log_info->vrf_name_len); - record += log_info->vrf_name_len; - *record++ = SYSLOG_DELIMITER; - - /* No IPV6 source address for nat44 */ - *record++ = '-'; - *record++ = SYSLOG_DELIMITER; - - *record++ = '-'; /* No translated source ip */ - *record++ = SYSLOG_DELIMITER; - - record += u16_to_ascii_decimal_unaligned( - record, key->k.port); - *record++ = SYSLOG_DELIMITER; - - *record++ = '-'; /* No translated start port */ - *record++ = SYSLOG_DELIMITER; - - *record++ = '-'; /* No translated end port */ - *record++ = SYSLOG_DELIMITER; - - /*No Destination Info*/ - *record++ = '-'; - *record++ = SYSLOG_DELIMITER; - *record++ = '-'; - *record++ = SYSLOG_DELIMITER; - - *record++ = ']'; /* End of the reocrd */ - - log_info->pkt_length += record - temp; -} - -void cnat_syslog_nat44_port_limit_exceeded( - cnat_key_t * key, - cnat_vrfmap_t *vrfmap) -{ - cnat_syslog_logging_info_t *logging_info = 0; - - SYSLOG_PRECHECK(vrfmap, NAT44) - - cnat_syslog_nat44_insert_port_exceeded(logging_info, key); - - /* - * If we have exceeded the packet length, let us send the - * packet now. There is buffer of additional bytes beyond - * max_pkt_length to ensure that the last add/delete record - * can be stored safely. - */ - - if (PREDICT_FALSE(logging_info->pkt_length > - logging_info->max_length_minus_max_record_size)) { - cnat_syslog_send_pkt(logging_info); - } -} - -void cnat_syslog_nat44_insert_tcp_seq_mismatch( - cnat_syslog_logging_info_t *log_info, - cnat_main_db_entry_t *db) -{ - /* This record should like this - - * [TCPseqmismatch - * - - - -] - */ - unsigned char *temp, *record; - - temp = record = &(log_info->current_logging_context->packet_data[ - CNAT_NFV9_IP_HDR_OFFSET + log_info->pkt_length]); - - /* Now we point to the location where record needs to be inserted */ - *record++ = '['; /* Open the record */ - - /* Copy the record type */ - clib_memcpy(record, sys_log_event[tcp_seq_mismatch].event_name, - sys_log_event[tcp_seq_mismatch].name_length); - record += sys_log_event[tcp_seq_mismatch].name_length; - *record++ = SYSLOG_DELIMITER; - - /* Next field is TCP */ - *record++ = '6'; - *record++ = SYSLOG_DELIMITER; - - /* Copy the Original Source IP */ - record += copy_ipv4_addr(record, db->in2out_key.k.ipv4); - *record++ = SYSLOG_DELIMITER; - - /* copy configured VRF NAME */ - clib_memcpy(record, log_info->vrf_name, log_info->vrf_name_len); - record += log_info->vrf_name_len; - *record++ = SYSLOG_DELIMITER; - - /* No IPV6 source address for nat44 */ - *record++ = '-'; - *record++ = SYSLOG_DELIMITER; - - record += copy_ipv4_addr(record, db->out2in_key.k.ipv4); - *record++ = SYSLOG_DELIMITER; - - record += u16_to_ascii_decimal_unaligned( - record, db->in2out_key.k.port); - *record++ = SYSLOG_DELIMITER; - - record += u16_to_ascii_decimal_unaligned( - record, db->out2in_key.k.port); - *record++ = SYSLOG_DELIMITER; - - *record++ = '-'; /* No translated end port */ - *record++ = SYSLOG_DELIMITER; - - /*No Destination Info*/ - *record++ = '-'; - *record++ = SYSLOG_DELIMITER; - *record++ = '-'; - *record++ = SYSLOG_DELIMITER; - - *record++ = ']'; /* End of the reocrd */ - - log_info->pkt_length += record - temp; -} - -void cnat_syslog_nat44_tcp_seq_mismatch( - cnat_main_db_entry_t *db, - cnat_vrfmap_t *vrfmap) -{ - cnat_syslog_logging_info_t *logging_info = 0; - - SYSLOG_PRECHECK(vrfmap, NAT44) - - cnat_syslog_nat44_insert_tcp_seq_mismatch(logging_info, db); - - /* - * If we have exceeded the packet length, let us send the - * packet now. There is buffer of additional bytes beyond - * max_pkt_length to ensure that the last add/delete record - * can be stored safely. - */ - - if (PREDICT_FALSE(logging_info->pkt_length > - logging_info->max_length_minus_max_record_size)) { - cnat_syslog_send_pkt(logging_info); - } -} -#endif diff --git a/plugins/plugins/vcgn/cnat_syslog.h b/plugins/plugins/vcgn/cnat_syslog.h deleted file mode 100644 index 931f4b9c..00000000 --- a/plugins/plugins/vcgn/cnat_syslog.h +++ /dev/null @@ -1,190 +0,0 @@ -/* - *------------------------------------------------------------------ - * cnat_syslog.h - * - * Copyright (c) 2011-2013 Cisco and/or its affiliates. - * 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 __CNAT_SYSLOG_H__ -#define __CNAT_SYSLOG_H__ - -#include -#include -#include -#include - -#include "cnat_db.h" -#include "nat64_db.h" -#include "cnat_log_common.h" -#include "dslite_defs.h" - -#define SYSLOG_CONFIG_DEBUG_PRINTF(level, ...) \ - if (config_debug_level > level) PLATFORM_DEBUG_PRINT(__VA_ARGS__); - - -/* one time call at the beginning */ -void cnat_syslog_logging_init(); - -/* - * unconditional call - * will check logging config inside - */ -void cnat_syslog_log_mapping_create(cnat_main_db_entry_t * db, - cnat_vrfmap_t *vrfmap); - -/* - * unconditional call - * will check logging config inside - */ -void cnat_syslog_log_mapping_delete(cnat_main_db_entry_t * db, - cnat_vrfmap_t *vrfmap); - -void cnat_syslog_ds_lite_mapping_create(cnat_main_db_entry_t *db, - dslite_table_entry_t *dslite_entry, cnat_session_entry_t *sdb -#ifndef NO_BULK_LOGGING - , int bulk_alloc -#endif - ); - -void cnat_syslog_ds_lite_port_limit_exceeded( - dslite_key_t * key, - dslite_table_entry_t *dslite_entry); - -#define SYSLOG_TIMESTAMP_LENGTH 20 - -#define CNAT_SYSLOG_VERSION_NUMBER 1 -#define CNAT_SYSLOG_PRIORITY 16*8+6 -/* facility = local0 + severity = info */ - -#define MAX_SYSLOG_HOSTNAME_LEN 32 - -/* 6 for priority + space - * 2 for version + space - * 21 YYYY MMM DD HH:MM:SS + space - * 33 for hostname + space - * 4 for App Name (-) + space + Proc ID (-) + space - * 7 for Msg ID (DSLite is the longest Msg ID so far + space - * 2 for Structured data (-) + space - */ -#define MAX_SYSLOG_HEADER_LEN 75 - -/* 18 for Event Name (Portblockrunout is the longest as of now) - * 3 for L4 (including space) - * 16 for original souce IP + space - * 33 for inside vrf name + space - * 40 for original source IPV6 + space - * 16 for translated source IP + space - * 6 for original port + space - * 6 for translated first source port + space - * 5 for translated last source port - * 2 for [] enclosure - */ -#define MAX_SYSLOG_RECORD_LEN 145 - -typedef enum { - NAT44, - DSLite -} syslog_service_type_t; - -typedef enum { - userbased_assign, - userbased_withdraw, - sessionbased_assign, - sessionbased_withdraw, - sessionbased_assignD, - sessionbased_withdrawD, - port_block_runout, - tcp_seq_mismatch, - max_syslog_event_type -} syslog_event_type_t; - -/* - * This structure store the Syslog Logging information on per - * collector basis. This structure is allocated from a pool and index - * to this structure is stored VRF MAP structures - */ -typedef struct { - /* - * nat64_id will be 0 for nat44 config and i_vrf_id, i_vrf will be 0 - * for nat64 config. Nat64_id will be used while nat64 collector is - * search and i_vrf* for nat44 collector - */ - /* Similarly for ds_lite, ds_lite_id will be used and nat64_id, - * ivrf_id shall be set to 0 - */ - u32 i_vrf_id; /* Inside VRF ID corresponding to this collector */ - u16 i_vrf; /* Inside VRF (uidb_index) corresponding to this collector */ - u16 ds_lite_id; /* DS Lite instance for this collector */ - u16 port; /* Destination port number of the collector */ - - /* - * This field determines the maximum size of the Syslog information - * that can be stored in a logging packet - */ - u16 max_length_minus_max_record_size; - u32 ipv4_address; /* Destination IP address of the collector */ - /* - * Timestamp in UNIX seconds corresponding to when the current - * logging packet was created - */ - u32 current_logging_context_timestamp; - - /* - * Indicates if the entry is already deleted - */ - u8 deleted; - - u8 header_priority; - u16 pkt_length; - - char header_hostname[MAX_SYSLOG_HOSTNAME_LEN]; - char vrf_name[VRF_NAME_LEN_STORED]; - u16 vrf_name_len; - u8 logging_policy; - /* - * current logging context - */ - spp_ctx_t *current_logging_context; - spp_ctx_t *queued_logging_context; - -} cnat_syslog_logging_info_t; - - -/* - * Global structure for CGN APP configuration - */ -typedef struct { - - u16 cnat_syslog_disp_node_index; - - /* - * Whether we have initialized the Syslog information - */ - u8 cnat_syslog_init_done; - -} cnat_syslog_global_info_t; - -typedef struct { - u64 logging_context_creation_fail_count; - u64 downstream_constipation_count; - u64 logging_context_creation_deferred_count; -} cnat_syslog_global_counters_t; - -extern cnat_syslog_logging_info_t *cnat_syslog_logging_info_pool; -extern cnat_syslog_global_info_t cnat_syslog_global_info; - -#define SYSLOG_DEF_PATH_MTU 1500 - -#endif /* __CNAT_SYSLOG_H__ */ diff --git a/plugins/plugins/vcgn/cnat_util.c b/plugins/plugins/vcgn/cnat_util.c deleted file mode 100644 index c3697b6b..00000000 --- a/plugins/plugins/vcgn/cnat_util.c +++ /dev/null @@ -1,2256 +0,0 @@ -/* - *------------------------------------------------------------------ - * cnat_util.c - cnat helpers - * - * Copyright (c) 2009-2014 Cisco and/or its affiliates. - * 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 -#include -#include -#include -#include -#include -#include -#include - -#include "tcp_header_definitions.h" - -#if 0 -void spp_api_cnat_v4_config_dummy_t_handler -(spp_api_cnat_v4_config_dummy_t *mp); - -void spp_api_cnat_v4_config_dummy_max_t_handler -(spp_api_cnat_v4_config_dummy_max_t *mp); - -void spp_api_cnat_v4_config_icmp_timeout_t_handler -(spp_api_cnat_v4_config_icmp_timeout_t *mp); - -void spp_api_cnat_clear_db_request_t_handler -(spp_api_cnat_clear_db_request_t *mp); - -void spp_api_cnat_v4_debug_global_t_handler -(spp_api_cnat_v4_debug_global_t *mp); - -void spp_api_cnat_v4_show_outside_entry_req_t_handler -(spp_api_cnat_v4_show_outside_entry_req_t *mp); - -void spp_api_cnat_v4_show_inside_entry_req_t_handler -(spp_api_cnat_v4_show_inside_entry_req_t *mp); - -void spp_api_cnat_show_statistics_summary_req_t_handler -(spp_api_cnat_show_statistics_summary_req_t *mp); - -void cnat_db_create_db_entries_cmd (int argc, unsigned long *argv) -{ - int i, j ; - int nusers = 3000; - - cnat_db_key_bucket_t key_info; - cnat_main_db_entry_t *db; - cnat_gen_icmp_info info; - cnat_key_t dest_info_dummy; - - memset(&dest_info_dummy, 0, sizeof(cnat_key_t)); - printf ("Create %d users, 100 translations each...\n", nusers); - - for (i = 0; i < nusers; i++) { - for (j = 0; j < 100; j++) { - - key_info.k.k.vrf = CNAT_TCP | (1 & CNAT_VRF_MASK); - key_info.k.k.ipv4 = 0x0c000001+i; - key_info.k.k.port = 1024+j; - - db = cnat_get_main_db_entry_v2(&key_info, PORT_SINGLE, - PORT_TYPE_DYNAMIC, &info, &dest_info_dummy); - - if (db == 0) { - printf ("OOPS: cnat_main_db_create failed users %d trans %d\n", i, j); - return; /*jli*/ - } - - db->entry_expires = cnat_current_time; - - } - } -} - -void db_test_clear (int argc, unsigned long *argv) -{ - spp_api_cnat_clear_db_request_t mp; - - mp.wildcard = argv[0]; - mp.protocol = argv[1]; - mp.port_num = argv[2]; - mp.inside_vrf = argv[3]; - mp.ip_addr = argv[4]; - spp_api_cnat_clear_db_request_t_handler(&mp); -} - -/* test code*/ -void cnat_db_test_show (int argc, unsigned long *argv) -{ - - spp_api_cnat_v4_show_inside_entry_req_t mp1[2000]; - spp_api_cnat_v4_show_outside_entry_req_t mp2[30000]; - - if (argc > 1) { - if (argc != 7) { - printf("Usage: db test show dec((which)) dec((vrf)) dec((proto)) dec((ip)) dec((start_port)) dec((end_port)) dec((flags))\n"); - return; - } - - mp1[0].vrf_id = argv[1]; - mp1[0].protocol = argv[2];; - mp1[0].ipv4_addr = argv[3]; - mp1[0].start_port = argv[4]; - mp1[0].end_port = argv[5]; - mp1[0].flags = argv[6]; - mp1[0].all_entries = 0; - - if (argv[0] == 1) { - spp_api_cnat_v4_show_inside_entry_req_t_handler (&(mp1[0])); - } else { - spp_api_cnat_v4_show_outside_entry_req_t_handler (&(mp2[0])); - } - - return; - } else { - printf("inside entries \n"); - mp1[0].ipv4_addr = 0x016994CA; - mp1[0].vrf_id = 1; - mp1[0].all_entries = 0; - mp1[0].start_port = 32765; - mp1[0].end_port = 65535; - mp1[0].protocol = 2; - mp1[0].flags = 3; - - spp_api_cnat_v4_show_inside_entry_req_t_handler (&(mp1[0])); - - mp2[0].ipv4_addr = 0x640200c1; - mp2[0].vrf_id = 0; - mp2[0].start_port = 1025; - mp2[0].end_port = 62235; - mp2[0].protocol = 2; - mp2[0].flags = 3; - - spp_api_cnat_v4_show_outside_entry_req_t_handler (&(mp2[0])); - } - -#if 1 - { - spp_api_cnat_stats_node_mapping_t mp3[20000]; - spp_api_cnat_stats_counter_mapping_t mp4[20000]; - spp_api_cnat_stats_counter_values_t mp5[23000]; - - mp3[0].rc = 0; - spp_api_cnat_stats_node_mapping_t_handler (&mp3); - mp4[0].rc = 0; - spp_api_cnat_stats_counter_mapping_t_handler (&mp4); - - mp5[0].flag = 1; - spp_api_cnat_stats_counter_values_t_handler(&mp5); - } -#endif - -#if 0 - mp1.ipv4_addr = 0x0A010102; - mp1.vrf_id = 1; - mp1.all_entries = 1; - mp1.protocol = 1; - - spp_api_cnat_v4_show_inside_entry_req_t_handler (&mp1); - - - mp1.ipv4_addr = 0x0A010103; - mp1.vrf_id = 1; - mp1.all_entries = 1; - mp1.protocol = 2; - - spp_api_cnat_v4_show_inside_entry_req_t_handler (&mp1); - - mp6[0].inside_vrf_id = 1; - mp6[0].start_ipv4_address = 0x64020001; - mp6[0].end_ipv4_address = 0x64020101; - mp6[0].free_addr = 0; - mp6[0].flags = CNAT_TRANSLATION_ENTRY_STATIC; - - spp_api_cnat_v4_show_freeUsed_entry_req_t_handler(&mp6); - -#endif - printf("returned here"); - - return; -} - - - -void cnat_db_clear_all_entries (int argc, unsigned long *argv) -{ - cnat_main_db_entry_t * db; - u32 index; - - pool_header_t * p = vec_header(cnat_main_db, sizeof(pool_header_t) ); - - for(index = 0; index < vec_len(cnat_main_db); index++) { - - if ( !clib_bitmap_get(p->free_bitmap, index)) { - - db = cnat_main_db + index; - cnat_delete_main_db_entry_v2(db); - - } - } - -} - - -void spp_log_cmd (int argc, unsigned long *argv) -{ - u16 num_traces; - u16 error_code; - u16 num_args; - u32 arg[7]; - u8 i; - - num_traces = argv[0]; - - for (i = 0; i < num_traces; i++) { - error_code = argv[1 + 4*i]; - num_args = argv[2 + 4*i]; - arg[0] = argv[3 + 4*i]; - arg[1] = argv[4 + 4*i]; - - spp_printf(error_code, num_args, arg); - } -} - - -void cnat_db_create_random_entries (int argc, unsigned long *argv) -{ - - platform_cnat_db_create_random_entries(); -} - -#define MAX_DEPTH 10 - -void show_user_db_hash_chain_len() { - - u32 max_len, len, n, i, max_idx, index, used; - cnat_user_db_entry_t * udb; - u32 hash_depth[MAX_DEPTH]; - - memset(hash_depth, 0, sizeof(u32)*MAX_DEPTH); - - n = vec_len(cnat_user_hash); - - used = 0; - max_len = 0; - for(i=0;iuser_hash.next; - } - - if(len < (MAX_DEPTH-1) ) { - hash_depth[len]++; - } else { - hash_depth[MAX_DEPTH-1]++; - } - - if (max_len < len) { - max_len = len; - max_idx = cnat_user_hash[i].next; - } - } - - printf("Max user db hash length %u, total buckets %u used %u\n", - max_len, n, used); - - for( i=1; i<(MAX_DEPTH - 1); i++) { - printf("Hash chain len %02d, entries count %d\n", i, hash_depth[i]); - } - - printf("Hash chain len >%02d, entries count %d\n", - MAX_DEPTH-1, hash_depth[MAX_DEPTH-1]); - -} - -void show_main_db_hash_chain_len() { - - u32 max_len, len, n, i, max_idx, index, used; - cnat_main_db_entry_t * db; - u32 hash_depth[MAX_DEPTH]; - - memset(hash_depth, 0, sizeof(u32)*MAX_DEPTH); - - n = vec_len(cnat_in2out_hash); - - used = 0; - max_len = 0; - for(i=0;iin2out_hash.next; - } - - if(len < (MAX_DEPTH-1) ) { - hash_depth[len]++; - } else { - hash_depth[MAX_DEPTH-1]++; - } - - if (max_len < len) { - max_len = len; - max_idx = cnat_in2out_hash[i].next; - } - } - - printf("Max main db I2O hash length %u, total buckets %u used %u\n", - max_len, n, used); - - for( i=1; i<(MAX_DEPTH - 1); i++) { - printf("Hash chain len %02d, entries count %d\n", i, hash_depth[i]); - } - - printf("Hash chain len >%02d, entries count %d\n", - MAX_DEPTH-1, hash_depth[MAX_DEPTH-1]); - - - memset(hash_depth, 0, sizeof(u32)*MAX_DEPTH); - - n = vec_len(cnat_out2in_hash); - used = 0; - max_len = 0; - - for(i=0;iout2in_hash.next; - } - - if(len < (MAX_DEPTH-1) ) { - hash_depth[len]++; - } else { - hash_depth[MAX_DEPTH-1]++; - } - - if (max_len < len) { - max_len = len; - max_idx = cnat_in2out_hash[i].next; - } - } - - printf("Max main db O2I hash length %u, total buckets %u used %u\n", - max_len, n, used); - - for( i=1; i<(MAX_DEPTH - 1); i++) { - printf("Hash chain len %02d, entries count %d\n", i, hash_depth[i]); - } - - printf("Hash chain len >%02d, entries count %d\n", - MAX_DEPTH-1, hash_depth[MAX_DEPTH-1]); - - -} - -u32 db_free_entry (void * p) { - - pool_header_t * h; - u32 free; - - h = pool_header(p); - - free = p == 0 ? 0: vec_len(h->free_indices); - - return free; -} - -void cnat_db_summary (int argc, unsigned long *argv) { - - PLATFORM_DEBUG_PRINT("\n-----------------------------------------"); - PLATFORM_DEBUG_PRINT("\nSummary DB"); - PLATFORM_DEBUG_PRINT("\n-----------------------------------------\n"); - u32 count1, count2, i; -#ifndef NO_NAT64_DEF - extern void nat64_session_db_summary(); -#endif - /* main db active entry count*/ - count1 = vec_len(cnat_main_db); - count2 = db_free_entry(cnat_main_db); - - PLATFORM_DEBUG_PRINT("main db entries: total %u, active %u, free %u\n", count1, count1 - count2, count2); - - /* user db active entry count */ - count1 = vec_len(cnat_user_db); - count2 = db_free_entry(cnat_user_db); - - PLATFORM_DEBUG_PRINT("user db entries: total %u, active %u, free %u\n", count1, count1 - count2, count2); - - - /* user db active entry count */ -#ifndef NO_NAT64_DEF - nat64_session_db_summary(); -#endif - - /* main db hash i2o o2i usage count */ - count1 = 0; - count2 = 0; - - for (i=0; i< CNAT_MAIN_HASH_SIZE; i++) { - - if(cnat_in2out_hash[i].next != ~0) count1++; - if(cnat_out2in_hash[i].next != ~0) count2++; - - } - - PLATFORM_DEBUG_PRINT("main hash in2out: total %6u, used %u (%.2f%%)\n", - CNAT_MAIN_HASH_SIZE, count1, - (100.0*count1)/CNAT_MAIN_HASH_SIZE); - - PLATFORM_DEBUG_PRINT("main hash out2in: total %6u, used %u (%.2f%%)\n", - CNAT_MAIN_HASH_SIZE, count2, - (100.0 * count1)/CNAT_MAIN_HASH_SIZE); - - /* use db hashing usage count */ - - count1 = 0; - - for (i=0; i< CNAT_USER_HASH_SIZE; i++) { - if(cnat_user_hash[i].next != ~0) count1++; - } - - PLATFORM_DEBUG_PRINT("user db hash: total %6u, used %u (%.2f%%)\n", - CNAT_USER_HASH_SIZE, count1, - (100.0*count1)/CNAT_USER_HASH_SIZE); - - PLATFORM_DEBUG_PRINT("\nNull pointer exceptions:\n"); - PLATFORM_DEBUG_PRINT("packet_pool: null enq : %10u, null deq : %10u\n",null_enq_pkt, null_deq_pkt); - PLATFORM_DEBUG_PRINT("ctx_pool : null enq : %10u, null deq : %10u\n",null_enq_ctx, null_deq_ctx); - PLATFORM_DEBUG_PRINT("wqe_pool : null enq : %10u, null deq : %10u\n",null_enq_wqe, null_deq_wqe); - - PLATFORM_DEBUG_PRINT("\nReceived Packet Errors on SPI:\n"); - PLATFORM_DEBUG_PRINT("rcv_pkt_errs: %10u\n",rcv_pkt_errs); - - PLATFORM_DEBUG_PRINT("\nctx/sf allocation failure errors: \n"); -#ifndef CGN_PERF_SCALE_DEBUG - PLATFORM_DEBUG_PRINT("Warning: collection of error counts is disabled.\n"); - PLATFORM_DEBUG_PRINT("sf alloc errors: %10u, ctx alloc errors: %10u\n",sf_alloc_errs,ctx_alloc_errs); -#else - for(i=0;iTimestamp : %10u, sf errors: %10u, ctx errors: %10u\n",\ - i,err_cnt_arr[i].timestamp,\ - err_cnt_arr[i].sf_error_counter, \ - err_cnt_arr[i].ctx_error_counter); -#endif -} - -void cnat_db_hash_summary (int argc, unsigned long *argv) { - - show_main_db_hash_chain_len(); - - show_user_db_hash_chain_len(); -} - -/* - * cnat_port_alloc - * This function is now deprecated... - * - */ -#ifdef LB_PORT -int cnat_port_alloc (cnat_portmap_t *cnat_portmap, u16 *portmap_inuse, - int cnat_instance, - port_alloc_t atype, port_pair_t ptype, - int *index, u32 *ipv4_address, u16 *base_port) -#else -int cnat_port_alloc (cnat_portmap_t *cnat_portmap, u16 *portmap_inuse, - port_alloc_t atype, port_pair_t ptype, - int *index, u32 *ipv4_address, u16 *base_port) -#endif -{ - - return (0); -} - -/* - * cnat_port_free - * This function is now deprecated... - * - */ -#ifdef LB_PORT -void cnat_port_free (cnat_portmap_t *cnat_portmap, u16 *portmap_inuse, - int instance, int index, port_pair_t ptype, u16 base_port) -#else -void cnat_port_free (cnat_portmap_t *cnat_portmap, u16 *portmap_inuse, - int index, port_pair_t ptype, u16 base_port) -#endif -{ -} - -void spp_api_cnat_port_allocate_t_handler(spp_api_cnat_port_allocate_t *mp) -{ - int i, j, k1, k2; - int pm_index; - u32 ipv4_address; - u16 aport; - int rv; - char *out1, *out2, *out_f; - port_alloc_t pt1, pt2; - cnat_portmap_t *pm = 0; - u16 *pm_inuse = 0; - u32 *firstp =0; - u32 nr_ports =0; - u32 nodd_ports = 0; - u32 neven_ports = 0; -#ifdef LB_PORT - u32 my_instance = 1; -#endif - char out_r[12] = "allocated-r"; - char out_o[12] = "allocated-o"; - char out_e[12] = "allocated-e"; - - - /* - * this command is run after db create portmap - * vrf is hardcode to 1 - */ - - /* Already have a portmap vector for this VRF? */ - for (i = 0; i < vec_len(cnat_portmap_indices_by_vrf); i++) { - if (cnat_portmap_indices_by_vrf[i] == mp->vrf) { - pm = cnat_portmaps[i]; - pm_inuse = cnat_portmaps_inuse[i]; - goto found_portmaps; - } - } - - printf("need to run db create portmaps first 0x%d\n", - vec_len(cnat_portmap_indices_by_vrf)); - return; - -found_portmaps: - nr_ports = mp->nr_ports; - nodd_ports = mp->nodd_ports; - neven_ports = mp->neven_ports; - - if ((nr_ports + nodd_ports + neven_ports ) > (PORTS_PER_ADDR)) { - printf("invalid port# nr_ports %d + odd %d + even %d " - "should be less than 200 \n", nr_ports, nodd_ports, neven_ports); - return; - } - - /* - * first port - */ - firstp = nr_ports ? (&nr_ports) : (nodd_ports ? (&nodd_ports) : (&neven_ports)); - if (!(*firstp)) { - printf("invalid port# nr_ports %d odd %d even %d ", - nr_ports, nodd_ports, neven_ports); - } - out_f = nr_ports ? out_r : (nodd_ports ? out_o : out_e); - -#ifdef LB_PORT - rv = cnat_port_alloc (pm, pm_inuse, my_instance, - PORT_ALLOC_ANY, PORT_S_ODD, - &pm_index, &ipv4_address, &aport); -#else - rv = cnat_port_alloc (pm, pm_inuse, - PORT_ALLOC_ANY, PORT_S_ODD, - &pm_index, &ipv4_address, &aport); -#endif - - if (!rv) { - printf("failed-o\n"); - return; - } - printf("%s %8d %10x %8d\n", out_f, - pm_index, ipv4_address, aport); - - (*firstp)--; - - for (i=0; i < nr_ports; i++) { -#ifdef LB_PORT - rv = cnat_port_alloc (pm, pm_inuse, my_instance, - PORT_ALLOC_DIRECTED, PORT_SINGLE, - &pm_index, &ipv4_address, &aport); -#else - rv = cnat_port_alloc (pm, pm_inuse, - PORT_ALLOC_DIRECTED, PORT_SINGLE, - &pm_index, &ipv4_address, &aport); -#endif - if (rv) { - printf("%s %8d %10x %8d\n", out_r, - pm_index, ipv4_address, aport); - } else { - printf("%s failed\n", out_r); - return; - } - } - - if (nodd_ports > neven_ports) { - k1 = nodd_ports; - k2 = neven_ports; - pt1 = PORT_S_ODD; - pt2 = PORT_S_EVEN; - out1 = out_o; - out2 = out_e; - } else { - k1= neven_ports; - pt1 = PORT_S_EVEN; - k2 = nodd_ports; - pt2 = PORT_S_ODD; - out1 = out_e; - out2 = out_o; - } - - j = 0; - for (i=0; i < k1; i++) { -#ifdef LB_PORT - rv = cnat_port_alloc (pm, pm_inuse, my_instance, - PORT_ALLOC_DIRECTED, pt1, - &pm_index, &ipv4_address, &aport); -#else - rv = cnat_port_alloc (pm, pm_inuse, - PORT_ALLOC_DIRECTED, pt1, - &pm_index, &ipv4_address, &aport); -#endif - if (rv) { - printf("%s %8d %10x %8d\n", out1, - pm_index, ipv4_address, aport); - } else { - printf("%s failed\n", out1); - return; - } - - if (j < k2) { -#ifdef LB_PORT - rv = cnat_port_alloc (pm, pm_inuse, my_instance, - PORT_ALLOC_DIRECTED, pt2, - &pm_index, &ipv4_address, &aport); -#else - rv = cnat_port_alloc (pm, pm_inuse, - PORT_ALLOC_DIRECTED, pt2, - &pm_index, &ipv4_address, &aport); -#endif - - if (rv) { - printf("%s %8d %10x %8d\n", out2, - pm_index, ipv4_address, aport); - j++; - } else { - printf("%s failed\n", __FUNCTION__); - return; - } - } - } -} - -void cnat_db_summary_stats (int argc, unsigned long *argv) -{ - spp_api_cnat_show_statistics_summary_req_t mp[50000]; - - spp_api_cnat_show_statistics_summary_req_t_handler(&(mp[0])); -} - -void cnat_debug_global_test (int argc, unsigned long *argv) -{ - spp_api_cnat_v4_debug_global_t *mp; - spp_api_cnat_v4_config_dummy_t mp1; - spp_api_cnat_v4_config_icmp_timeout_t mp2[10]; - - mp = spp_msg_api_alloc (sizeof (*mp)); - memset(mp, 0, sizeof (*mp)); - - - mp->_spp_msg_id = SPP_API_CNAT_V4_DEBUG_GLOBAL; - mp->debug_flag = argv[0]; - - platform_send_msg(mp); - - mp2[0].default_value = 3; - - spp_api_cnat_v4_config_dummy_t_handler(&mp1); - spp_api_cnat_v4_config_icmp_timeout_t_handler(&(mp2[0])); -} - -void cnat_debug_inside_test (int argc, unsigned long *argv) -{ - - spp_api_cnat_v4_debug_in2out_private_addr_t *mp; - - mp = spp_msg_api_alloc (sizeof (*mp)); - memset(mp, 0, sizeof (*mp)); - - - mp->_spp_msg_id = SPP_API_CNAT_V4_DEBUG_IN2OUT_PRIVATE_ADDR; - - mp->start_addr = spp_host_to_net_byte_order_32(argv[0]); - mp->end_addr = spp_host_to_net_byte_order_32(argv[1]); - mp->i_vrf = spp_host_to_net_byte_order_16(argv[2]); - mp->debug_flag = spp_host_to_net_byte_order_32(argv[3]); - - platform_send_msg(mp); -} - -void cnat_config_ports_user (int argc, unsigned long *argv) -{ - spp_api_cnat_v4_config_port_limit_t *mp; - - mp = spp_msg_api_alloc (sizeof (*mp)); - memset(mp, 0, sizeof (*mp)); - - - mp->_spp_msg_id = SPP_API_CNAT_V4_CONFIG_PORT_LIMIT; - - mp->port_limit = spp_host_to_net_byte_order_16(argv[0]); - - platform_send_msg(mp); - -} - -void cnat_debug_outside_test (int argc, unsigned long *argv) -{ - - spp_api_cnat_v4_debug_out2in_public_addr_t *mp; - - mp = spp_msg_api_alloc (sizeof (*mp)); - memset(mp, 0, sizeof (*mp)); - - - mp->_spp_msg_id = SPP_API_CNAT_V4_DEBUG_OUT2IN_PUBLIC_ADDR; - - mp->start_addr = spp_host_to_net_byte_order_32(argv[0]); - mp->end_addr = spp_host_to_net_byte_order_32(argv[1]); - mp->o_vrf = spp_host_to_net_byte_order_16(argv[2]); - mp->debug_flag = spp_host_to_net_byte_order_32(argv[3]); - - platform_send_msg(mp); -} - -void cnat_debug_udp_dump (int argc, unsigned long *argv) -{ - - spp_api_cnat_p2mp_debug_request_t *mp; - - mp = spp_msg_api_alloc (sizeof (*mp)); - memset(mp, 0, sizeof (*mp)); - - - mp->_spp_msg_id = SPP_API_CNAT_P2MP_DEBUG_REQUEST; - mp->dump_type = - spp_host_to_net_byte_order_16(CNAT_DEBUG_GENERIC_COMMAND_DEBUG_FLAGS); - - if (spp_host_to_net_byte_order_32(argv[0]) == 1) { - mp->param[0] = spp_host_to_net_byte_order_32( - CNAT_DEBUG_FLAG_UDP_INSIDE_PACKET_DUMP); - } else { - mp->param[0] = spp_host_to_net_byte_order_32( - CNAT_DEBUG_FLAG_UDP_OUTSIDE_PACKET_DUMP); - } - mp->param[1] = spp_host_to_net_byte_order_32(argv[1]); - - platform_send_msg(mp); - - - -} - -void cnat_debug_udp_crc (int argc, unsigned long *argv) -{ - spp_api_cnat_p2mp_debug_request_t *mp; - - mp = spp_msg_api_alloc (sizeof (*mp)); - memset(mp, 0, sizeof (*mp)); - - - mp->_spp_msg_id = SPP_API_CNAT_P2MP_DEBUG_REQUEST; - mp->dump_type = - spp_host_to_net_byte_order_16(CNAT_DEBUG_GENERIC_COMMAND_DEBUG_FLAGS); - - if (spp_host_to_net_byte_order_32(argv[0]) == 1) { - mp->param[0] = spp_host_to_net_byte_order_32( - CNAT_DEBUG_FLAG_UDP_INSIDE_CHECKSUM_MODIFY); - } else { - mp->param[0] = spp_host_to_net_byte_order_32( - CNAT_DEBUG_FLAG_UDP_OUTSIDE_CHECKSUM_MODIFY); - } - mp->param[1] = spp_host_to_net_byte_order_32(argv[1]); - - platform_send_msg(mp); - -} - -void cnat_db_allocate_port_cmd (int argc, unsigned long *argv) -{ - spp_api_cnat_port_allocate_t *mp; - - - if (!argc) { - printf("no port# defined\n"); - return; - } - - if ( argc < 3) { - printf("no port# defined\n"); - return; - } - - if ((argc == 3) && (argv[0] == 0) && (argv[1] == 0) && (argv[2] == 0)) { - printf("no port# defined\n"); - return; - } - - mp = spp_msg_api_alloc (sizeof (*mp)); - memset(mp, 0, sizeof (*mp)); - - - mp->_spp_msg_id = SPP_API_CNAT_PORT_ALLOCATE; - mp->nr_ports = argv[0]; - mp->nodd_ports = argv[1]; - mp->neven_ports = argv[2]; - mp->vrf = 1; - - platform_send_msg(mp); -} - - -void spp_api_cnat_port_clear_t_handler(spp_api_cnat_port_clear_t *mp) -{ - u32 i; - cnat_portmap_t *pm = 0; - u16 *pm_inuse = 0; -#ifdef LB_PORT - u32 my_instance = 1; -#endif - - - /* - * this command is run after db create port - * vrf is hardcode to 1 - */ - - /* Already have a portmap vector for this VRF? */ - for (i = 0; i < vec_len(cnat_portmap_indices_by_vrf); i++) { - if (cnat_portmap_indices_by_vrf[i] == mp->vrf) { - pm = cnat_portmaps[i]; - pm_inuse = cnat_portmaps_inuse[i]; - goto found_portmaps; - } - } - - printf("portmap is not created 0x%d\n", - vec_len(cnat_portmap_indices_by_vrf)); - return; - -found_portmaps: - if (mp->pm_index >= vec_len(pm)) { - printf("invalid port_index 0x%d >= 0x%d\n", - mp->pm_index, vec_len(pm)); - return; - } - -#ifdef LB_PORT - cnat_port_free(pm, pm_inuse, my_instance, - mp->pm_index, PORT_SINGLE, mp->port); -#else - cnat_port_free(pm, pm_inuse, - mp->pm_index, PORT_SINGLE, mp->port); -#endif - printf("\n pm_index %d port %d is deleted\n", mp->pm_index, mp->port); -} - - - -void cnat_db_clear_port_cmd (int argc, unsigned long *argv) -{ - spp_api_cnat_port_clear_t *mp; - - if (!argc) { - printf("no port# defined\n"); - return; - } - - if ( argc < 2 ) { - printf("no port# defined\n"); - return; - } - - if (argc > 2) { - printf("too many port# defined\n"); - return; - } - - mp = spp_msg_api_alloc (sizeof (*mp)); - memset(mp, 0, sizeof (*mp)); - - - mp->_spp_msg_id = SPP_API_CNAT_PORT_CLEAR; - mp->pm_index = argv[0]; - mp->port = argv[1]; - mp->vrf = 1; - - platform_send_msg(mp); -} - - -void spp_api_cnat_v4_add_vrf_map_t_handler -(spp_api_cnat_v4_add_vrf_map_t *mp); - -void spp_api_cnat_v4_del_vrf_map_t_handler -(spp_api_cnat_v4_del_vrf_map_t *mp); - -void spp_api_cnat_v4_add_static_port_t_handler -(spp_api_cnat_v4_add_static_port_t *mp); - -void spp_api_cnat_v4_del_static_port_t_handler -(spp_api_cnat_v4_del_static_port_t *mp); - - -void cnat_db_create_vrfmap_cmd (int argc, unsigned long *argv) -{ - spp_api_cnat_v4_add_vrf_map_t *mp; - - if ((argc != 4)) { - printf("need right input\n"); - return; - } - - mp = spp_msg_api_alloc (sizeof (*mp)); - memset(mp, 0, sizeof (*mp)); - mp->_spp_msg_id = SPP_API_CNAT_V4_ADD_VRF_MAP; - mp->i_vrf = spp_host_to_net_byte_order_16(argv[0]); - mp->o_vrf = spp_host_to_net_byte_order_16(argv[1]); - mp->start_addr[0] = spp_host_to_net_byte_order_32(argv[2]); - mp->end_addr[0] = spp_host_to_net_byte_order_32(argv[3]); - - /* - * Some hardcoded values for the vrf ids - */ - mp->i_vrf_id = spp_host_to_net_byte_order_32(0x00000100 | mp->i_vrf); - mp->o_vrf_id = spp_host_to_net_byte_order_32(0x00000200 | mp->o_vrf); - - platform_send_msg(mp); -} - - -void cnat_db_delete_vrfmap_cmd (int argc, unsigned long *argv) -{ - spp_api_cnat_v4_del_vrf_map_t *mp; - - if (argc != 4) { - printf("need right input\n"); - return; - } - - mp = spp_msg_api_alloc (sizeof (*mp)); - memset(mp, 0, sizeof (*mp)); - mp->_spp_msg_id = SPP_API_CNAT_V4_DEL_VRF_MAP; - mp->i_vrf = spp_host_to_net_byte_order_16(argv[0]); - mp->start_addr[0] = spp_host_to_net_byte_order_32(argv[2]); - mp->end_addr[0] = spp_host_to_net_byte_order_32(argv[3]); - - platform_send_msg(mp); -} - -void cnat_db_add_svi_cmd (int argc, unsigned long *argv) -{ - spp_api_cnat_config_svi_params_t *mp; - - if (argc != 3) { - printf("need right input\n"); - return; - } - - - mp = spp_msg_api_alloc (sizeof (*mp)); - memset(mp, 0, sizeof (*mp)); - mp->_spp_msg_id = SPP_API_CNAT_CONFIG_SVI_PARAMS; - mp->uidb_index = spp_host_to_net_byte_order_16(argv[1]); - mp->svi_ipv4_addr = spp_host_to_net_byte_order_32(argv[2]); - platform_send_msg(mp); - return; -} - - - -void spp_api_cnat_port_create_t_handler(spp_api_cnat_port_create_t *mp) -{ - int i, j, k1, k2; - int my_index; - u32 ipv4_address; - u16 aport; - u32 pm_len =0; - cnat_errno_t rv; - u16 i_vrf; - char *out1, *out2, *out_f; - port_alloc_t pt1, pt2; - cnat_vrfmap_t *my_vrfmap; - cnat_portmap_v2_t *pm = 0; - u32 *firstp =0; - u32 nr_ports =0; - u32 nodd_ports = 0; - u32 neven_ports = 0; -#ifdef LB_PORT - u32 my_instance = 1; -#endif - char out_r[12] = "allocated-r"; - char out_o[12] = "allocated-o"; - char out_e[12] = "allocated-e"; -#ifndef NO_BULK_LOGGING - int nfv9_log_req; -#endif - - nr_ports = mp->nr_ports; - nodd_ports = mp->nodd_ports; - neven_ports = mp->neven_ports; - i_vrf = mp->vrf; - - /* - * this command is run after db create vrfmap - * or using vrf id in init function - */ - /* Already have a portmap vector for this VRF? */ - pool_foreach (my_vrfmap, cnat_map_by_vrf, ({ - if ((my_vrfmap->status == S_RUN) && - (my_vrfmap->i_vrf == i_vrf)) { - pm = my_vrfmap->portmap_list; - pm_len = vec_len(pm); - if (pm_len) { - goto found_portmaps; - } - } - })); - - printf("need to run db create vrfmaps first for this vrf0x%d\n", pm_len); - return; - -found_portmaps: - - if ((nr_ports + nodd_ports + neven_ports ) > (PORTS_PER_ADDR)) { - printf("invalid port# nr_ports %d + odd %d + even %d " - "should be less than 200 \n", nr_ports, nodd_ports, neven_ports); - return; - } - - /* - * first port - */ - firstp = nr_ports ? (&nr_ports) : (nodd_ports ? (&nodd_ports) : (&neven_ports)); - if (!(*firstp)) { - printf("invalid port# nr_ports %d odd %d even %d ", - nr_ports, nodd_ports, neven_ports); - } - out_f = nr_ports ? out_r : (nodd_ports ? out_o : out_e); - - rv = cnat_dynamic_port_alloc_v2 (pm, PORT_ALLOC_ANY, PORT_S_ODD, - &my_index, &ipv4_address, &aport, - cnat_static_port_range -#ifndef NO_BULK_LOGGING - , BULKSIZE_FROM_VRFMAP(my_vrfmap), - &nfv9_log_req -#endif - , 0, - &(my_vrfmap->rseed_ip) - ); - - if (rv != CNAT_SUCCESS) { - printf("failed-o\n"); - return; - } - printf("%s %8d %10x %8d\n", out_f, - my_index, ipv4_address, aport); - - (*firstp)--; - - for (i=0; i < nr_ports; i++) { - rv = cnat_dynamic_port_alloc_v2 (pm, PORT_ALLOC_DIRECTED, PORT_SINGLE, - &my_index, &ipv4_address, &aport, - cnat_static_port_range -#ifndef NO_BULK_LOGGING - , BULKSIZE_FROM_VRFMAP(my_vrfmap), - &nfv9_log_req -#endif - , 0, - &(my_vrfmap->rseed_ip) - ); - - if (rv == CNAT_SUCCESS) { - printf("%s %8d %10x %8d\n", out_r, - my_index, ipv4_address, aport); - } else { - printf("%s failed\n", __FUNCTION__); - return; - } - } - - if (nodd_ports > neven_ports) { - k1 = nodd_ports; - k2 = neven_ports; - pt1 = PORT_S_ODD; - pt2 = PORT_S_EVEN; - out1 = out_o; - out2 = out_e; - } else { - k1= neven_ports; - pt1 = PORT_S_EVEN; - k2 = nodd_ports; - pt2 = PORT_S_ODD; - out1 = out_e; - out2 = out_o; - } - - j = 0; - for (i=0; i < k1; i++) { - rv = cnat_dynamic_port_alloc_v2 (pm, PORT_ALLOC_DIRECTED, pt1, - &my_index, &ipv4_address, &aport, - cnat_static_port_range -#ifndef NO_BULK_LOGGING - , BULKSIZE_FROM_VRFMAP(my_vrfmap), - &nfv9_log_req -#endif - , 0, - &(my_vrfmap->rseed_ip) - ); - - if (rv == CNAT_SUCCESS) { - printf("%s %8d %10x %8d\n", out1, - my_index, ipv4_address, aport); - } else { - printf("%s failed\n", __FUNCTION__); - return; - } - - if (j < k2) { - rv = cnat_dynamic_port_alloc_v2 (pm, PORT_ALLOC_DIRECTED, pt2, - &my_index, &ipv4_address, &aport, - cnat_static_port_range -#ifndef NO_BULK_LOGGING - , BULKSIZE_FROM_VRFMAP(my_vrfmap), - &nfv9_log_req -#endif - , 0, - &(my_vrfmap->rseed_ip) - ); - - if (rv == CNAT_SUCCESS) { - printf("%s %8d %10x %8d\n", out2, - my_index, ipv4_address, aport); - j++; - } else { - printf("%s failed\n", __FUNCTION__); - return; - return; - } - } - } -} - - -void cnat_db_create_port_cmd (int argc, unsigned long *argv) -{ - spp_api_cnat_port_create_t *mp; - - if (argc != 4) { - printf("no proper input defined\n"); - return; - } - - if ((argv[0] == 0) && (argv[1] == 0) && (argv[2] == 0)) { - printf("no port# defined\n"); - return; - } - - mp = spp_msg_api_alloc (sizeof (*mp)); - memset(mp, 0, sizeof (*mp)); - - - mp->_spp_msg_id = SPP_API_CNAT_PORT_CREATE; - mp->nr_ports = argv[0]; - mp->nodd_ports = argv[1]; - mp->neven_ports = argv[2]; - mp->vrf = argv[3]; - - platform_send_msg(mp); -} - -void spp_api_cnat_port_delete_t_handler(spp_api_cnat_port_delete_t *mp) -{ - u32 pm_len; - cnat_vrfmap_t *my_vrfmap; - cnat_portmap_v2_t *pm = 0; - - u32 my_index, my_port; - u16 i_vrf; -#ifdef LB_PORT - u32 my_instance = 1; -#endif - - my_index = mp->pm_index; - my_port = mp->port; - i_vrf = mp->vrf; - - /* - * this command is run after db create port - */ - pool_foreach (my_vrfmap, cnat_map_by_vrf, ({ - if (my_vrfmap->i_vrf == i_vrf) { - pm = my_vrfmap->portmap_list; - pm_len = vec_len(pm); - if (pm_len) { - goto found_portmaps; - } - } - })); - - printf("portmap is not created 0x%d\n", - vec_len(cnat_portmap_indices_by_vrf)); - return; - -found_portmaps: - if (my_index >= pm_len) { - printf("invalid port_index 0x%d >= 0x%d\n", - my_index, pm_len); - return; - } - -#ifdef LB_PORT - cnat_port_free_v2(pm, my_instance, - my_index, PORT_SINGLE, mp->port,cnat_static_port_range); -#else - cnat_port_free_v2(pm, my_index, PORT_SINGLE, mp->port,cnat_static_port_range); -#endif - printf("\n pm_index %d port %d is deleted\n", mp->pm_index, mp->port); -} - -void cnat_db_delete_port_cmd (int argc, unsigned long *argv) -{ - spp_api_cnat_port_clear_t *mp; - - if (argc != 3) { - printf("no proper input defined\n"); - return; - } - - mp = spp_msg_api_alloc (sizeof (*mp)); - memset(mp, 0, sizeof (*mp)); - - - mp->_spp_msg_id = SPP_API_CNAT_PORT_DELETE; - mp->pm_index = argv[0]; - mp->port = argv[1]; - mp->vrf = argv[2]; - platform_send_msg(mp); -} - -void cnat_db_create_static_fwd_cmd (int argc, unsigned long *argv) -{ - spp_api_cnat_v4_add_static_port_t *mp; - - if (argc != 4) { - printf("need right input\n"); - return; - } - - mp = spp_msg_api_alloc (sizeof (*mp)); - memset(mp, 0, sizeof (*mp)); - mp->_spp_msg_id = SPP_API_CNAT_V4_ADD_STATIC_PORT; - mp->i_vrf = spp_host_to_net_byte_order_16(argv[0]); - mp->i_ip = spp_host_to_net_byte_order_32(argv[1]); - mp->i_port = spp_host_to_net_byte_order_16(argv[2]); - mp->proto = argv[3]; - - platform_send_msg(mp); - return; -} - -void cnat_db_create_static_fwd_stby_cmd (int argc, unsigned long *argv) -{ - spp_api_cnat_v4_add_static_port_t *mp; - - if (argc != 7) { - printf("need right input\n"); - return; - } - - mp = spp_msg_api_alloc (sizeof (*mp)); - memset(mp, 0, sizeof (*mp)); - mp->_spp_msg_id = SPP_API_CNAT_V4_ADD_STATIC_PORT; - mp->i_vrf = spp_host_to_net_byte_order_16(argv[0]); - mp->i_ip = spp_host_to_net_byte_order_32(argv[1]); - mp->i_port = spp_host_to_net_byte_order_16(argv[2]); - mp->proto = argv[3]; - mp->o_vrf_id = spp_host_to_net_byte_order_32(argv[4]); - mp->o_ip = spp_host_to_net_byte_order_32(argv[5]); - mp->o_port = spp_host_to_net_byte_order_16(argv[6]); - -printf("\ni_vrf %d, ip 0x%x, port %d, o_ip, port %d", mp->i_vrf, mp->i_ip, mp->i_port, mp->o_ip, mp->o_port); - - platform_send_msg(mp); - return; -} - -void cnat_db_delete_static_fwd_cmd (int argc, unsigned long *argv) -{ - spp_api_cnat_v4_del_static_port_t *mp; - - if (argc != 3) { - printf("need right input\n"); - return; - } - - mp = spp_msg_api_alloc (sizeof (*mp)); - memset(mp, 0, sizeof (*mp)); - mp->_spp_msg_id = SPP_API_CNAT_V4_DEL_STATIC_PORT; - mp->i_vrf = spp_host_to_net_byte_order_16(argv[0]); - mp->i_ip = spp_host_to_net_byte_order_32(argv[1]); - mp->i_port = spp_host_to_net_byte_order_16(argv[2]); - - platform_send_msg(mp); - return; -} - -void cnat_nfv9_create_cmd (int argc, unsigned long *argv) -{ - spp_api_cnat_v4_config_nfv9_logging_t *mp; - - if (argc < 3) { - printf("nfv9 create i_vrf ip_addr port [refresh_rate] [timeout] [mtu]"); - return; - } - - mp = spp_msg_api_alloc (sizeof (*mp)); - memset(mp, 0, sizeof (*mp)); - mp->_spp_msg_id = SPP_API_CNAT_V4_CONFIG_NFV9_LOGGING; - mp->enable = 1; - mp->i_vrf = spp_host_to_net_byte_order_16(argv[0]); - - mp->ipv4_address = spp_host_to_net_byte_order_32(argv[1]); - mp->port = spp_host_to_net_byte_order_16(argv[2]); - - if (argc > 3) { - mp->refresh_rate = spp_host_to_net_byte_order_16(argv[3]); - mp->timeout_rate = spp_host_to_net_byte_order_16(argv[4]); - mp->path_mtu = spp_host_to_net_byte_order_16(argv[5]); - } else { - mp->refresh_rate = spp_host_to_net_byte_order_16(1000); - mp->timeout_rate = spp_host_to_net_byte_order_16(30); - mp->path_mtu = spp_host_to_net_byte_order_16(1500); - } - platform_send_msg(mp); -} - -void cnat_delete_cgn (int argc, unsigned long *argv) -{ - void *mp_send; - spp_api_cnat_del_cgn_t *mp; - u32 mp_size; - - mp_size = sizeof(spp_api_cnat_del_cgn_t); - - mp = spp_msg_api_alloc(mp_size); - memset(mp, 0, mp_size); - - mp->_spp_msg_id = SPP_API_CNAT_DEL_CGN; - - mp_send = mp; - - platform_send_msg(mp); -} - -void cnat_debug_global_all (int argc, unsigned long *argv) -{ - spp_api_cnat_v4_debug_global_t *mp; - - mp = spp_msg_api_alloc (sizeof (*mp)); - memset(mp, 0, sizeof (*mp)); - - mp->_spp_msg_id = SPP_API_CNAT_V4_DEBUG_GLOBAL; - mp->debug_flag = CNAT_DEBUG_GLOBAL_ALL; - - platform_send_msg(mp); -} - -void cnat_debug_global_none (int argc, unsigned long *argv) -{ - spp_api_cnat_v4_debug_global_t *mp; - - mp = spp_msg_api_alloc (sizeof (*mp)); - memset(mp, 0, sizeof (*mp)); - - mp->_spp_msg_id = SPP_API_CNAT_V4_DEBUG_GLOBAL; - mp->debug_flag = CNAT_DEBUG_NONE; - - platform_send_msg(mp); -} - - -void cnat_bulk_cmd (int argc, unsigned long *argv) -{ - void *mp_send; - - if (argc < 1) { - printf("\nargc = %d", argc); - printf("\n1. bulk cmd [0=static-port, 1=bulk_vrf, 2=policy_knob]"); - return; - } - - - switch (argv[0]) { - case 0: - { - spp_api_cnat_v4_bulk_add_delete_static_port_t *mp; - spp_api_cnat_v4_add_static_port_t *mp_sp; - u32 mp_size = - sizeof(spp_api_cnat_v4_bulk_add_delete_static_port_t) + - (sizeof(spp_api_cnat_v4_add_static_port_t))*2; - - mp = spp_msg_api_alloc(mp_size); - memset(mp, 0, mp_size); - - mp->_spp_msg_id = SPP_API_CNAT_V4_BULK_ADD_DELETE_STATIC_PORT; - - mp->num_static_port_entries = spp_host_to_net_byte_order_32(3); - - mp_sp = (spp_api_cnat_v4_add_static_port_t *) &(mp->pad2); - - mp_sp->_spp_msg_id = spp_host_to_net_byte_order_16( - SPP_API_CNAT_V4_ADD_STATIC_PORT); - mp_sp->proto = 2; - mp_sp->i_vrf = spp_host_to_net_byte_order_16(0x1); - mp_sp->i_ip = spp_host_to_net_byte_order_32(0x11111111); - mp_sp->i_port = spp_host_to_net_byte_order_16(0x7777); - - mp_sp++; - - - mp_sp->_spp_msg_id = spp_host_to_net_byte_order_16( - SPP_API_CNAT_V4_ADD_STATIC_PORT); - mp_sp->proto = 1; - mp_sp->i_vrf = spp_host_to_net_byte_order_16(0x1); - mp_sp->i_ip = spp_host_to_net_byte_order_32(0x22222222); - mp_sp->i_port = spp_host_to_net_byte_order_16(0x6666); - - mp_sp++; - - - mp_sp->_spp_msg_id = spp_host_to_net_byte_order_16( - SPP_API_CNAT_V4_ADD_STATIC_PORT); - mp_sp->proto = 1; - mp_sp->i_vrf = spp_host_to_net_byte_order_16(0x1); - mp_sp->i_ip = spp_host_to_net_byte_order_32(0x33333333); - mp_sp->i_port = spp_host_to_net_byte_order_16(0x5555); - - mp_send = mp; - - } - break; - - case 1: - { - spp_api_cnat_v4_bulk_vrf_map_t *mp; - spp_api_cnat_v4_single_vrf_map_req *mp_sp; - - u32 mp_size = sizeof(spp_api_cnat_v4_bulk_vrf_map_t) + - (sizeof(spp_api_cnat_v4_single_vrf_map_req))*2; - - mp = spp_msg_api_alloc(mp_size); - memset(mp, 0, mp_size); - - mp->_spp_msg_id = SPP_API_CNAT_V4_BULK_VRF_MAP; - - mp->num_vrfmap_entries = spp_host_to_net_byte_order_32(3); - - mp_sp = (spp_api_cnat_v4_single_vrf_map_req *) - &(mp->vrf_policy_enable); - - mp_sp->i_vrf_id = spp_host_to_net_byte_order_32(0xe0000001); - mp_sp->o_vrf_id = spp_host_to_net_byte_order_32(0xe0000000); - mp_sp->i_vrf = spp_host_to_net_byte_order_16(0x1); - mp_sp->o_vrf = spp_host_to_net_byte_order_16(0x0); - mp_sp->start_addr = spp_host_to_net_byte_order_32(0x11111100); - mp_sp->end_addr = spp_host_to_net_byte_order_32(0x111111ff); - mp_sp->vrf_policy_enable = spp_host_to_net_byte_order_16(0x3); - mp_sp->tcp_mss_value = spp_host_to_net_byte_order_16(0x111); - mp_sp->vrf_nfv9_logging_ipv4_address = spp_host_to_net_byte_order_32(0x11000001); - mp_sp->vrf_nfv9_logging_udp_port = spp_host_to_net_byte_order_16(0x1001); - mp_sp->vrf_nfv9_refresh_rate = spp_host_to_net_byte_order_16(0x100); - mp_sp->vrf_nfv9_timeout_rate = spp_host_to_net_byte_order_16(0x10); - mp_sp->vrf_nfv9_path_mtu = spp_host_to_net_byte_order_16(0x100); - - mp_sp++; - - mp_sp->i_vrf_id = spp_host_to_net_byte_order_32(0xe0000002); - mp_sp->o_vrf_id = spp_host_to_net_byte_order_32(0xe0000000); - mp_sp->i_vrf = spp_host_to_net_byte_order_16(0x2); - mp_sp->o_vrf = spp_host_to_net_byte_order_16(0x0); - mp_sp->start_addr = spp_host_to_net_byte_order_32(0x22220000); - mp_sp->end_addr = spp_host_to_net_byte_order_32(0x2222ffff); - mp_sp->vrf_policy_enable = spp_host_to_net_byte_order_16(0x1); - mp_sp->tcp_mss_value = spp_host_to_net_byte_order_16(0x222); - mp_sp->vrf_nfv9_logging_ipv4_address = spp_host_to_net_byte_order_32(0x22000002); - mp_sp->vrf_nfv9_logging_udp_port = spp_host_to_net_byte_order_16(0x2002); - mp_sp->vrf_nfv9_refresh_rate = spp_host_to_net_byte_order_16(0x200); - mp_sp->vrf_nfv9_timeout_rate = spp_host_to_net_byte_order_16(0x20); - mp_sp->vrf_nfv9_path_mtu = spp_host_to_net_byte_order_16(0x200); - - mp_sp++; - - mp_sp->i_vrf_id = spp_host_to_net_byte_order_32(0xe0000003); - mp_sp->o_vrf_id = spp_host_to_net_byte_order_32(0xe0000007); - mp_sp->i_vrf = spp_host_to_net_byte_order_16(0x3); - mp_sp->o_vrf = spp_host_to_net_byte_order_16(0x7); - mp_sp->start_addr = spp_host_to_net_byte_order_32(0x33333000); - mp_sp->end_addr = spp_host_to_net_byte_order_32(0x33333fff); - mp_sp->vrf_policy_enable = spp_host_to_net_byte_order_16(0x1); - mp_sp->tcp_mss_value = spp_host_to_net_byte_order_16(0x333); - mp_sp->vrf_nfv9_logging_ipv4_address = spp_host_to_net_byte_order_32(0x33000003); - mp_sp->vrf_nfv9_logging_udp_port = spp_host_to_net_byte_order_16(0x3003); - mp_sp->vrf_nfv9_refresh_rate = spp_host_to_net_byte_order_16(0x300); - mp_sp->vrf_nfv9_timeout_rate = spp_host_to_net_byte_order_16(0x30); - mp_sp->vrf_nfv9_path_mtu = spp_host_to_net_byte_order_16(0x300); - - mp_send = mp; - } - break; - - case 2: - { - spp_api_cnat_v4_bulk_policy_knob_t *mp; - - u32 mp_size = - sizeof(spp_api_cnat_v4_bulk_policy_knob_t) + - (sizeof(spp_api_cnat_v4_single_vrf_map_req))*2; - - mp = spp_msg_api_alloc(mp_size); - memset(mp, 0, mp_size); - - mp->_spp_msg_id = SPP_API_CNAT_V4_BULK_POLICY_KNOB; - - mp->port_limit = spp_host_to_net_byte_order_16(345); - mp->icmp_timeout = spp_host_to_net_byte_order_16(300); - mp->udp_init_timeout = spp_host_to_net_byte_order_16(175); - mp->udp_act_timeout = spp_host_to_net_byte_order_16(133); - mp->tcp_init_timeout = spp_host_to_net_byte_order_16(222); - mp->tcp_act_timeout = spp_host_to_net_byte_order_16(2345); - - mp->nat_policy_enable = spp_host_to_net_byte_order_32(0x7); - - mp->global_nfv9_logging_ipv4_address = spp_host_to_net_byte_order_32(0x77777777); - mp->global_nfv9_logging_udp_port = spp_host_to_net_byte_order_16(0x7007); - mp->global_nfv9_refresh_rate = spp_host_to_net_byte_order_16(0x700); - mp->global_nfv9_timeout_rate = spp_host_to_net_byte_order_16(0x70); - mp->global_nfv9_path_mtu = spp_host_to_net_byte_order_16(0x700); - - mp_send = mp; - } - break; - - - default: - printf("\nargv[2] = %d", argv[2]); - printf("\n2. bulk cmd [0=static-port, 1=bulk_vrf, 2=policy_knob+bulk_vrf]"); - return; - - } - platform_send_msg(mp_send); -} - -void cnat_nfv9_delete_cmd (int argc, unsigned long *argv) -{ - spp_api_cnat_v4_config_nfv9_logging_t *mp; - - if (argc != 1) { - printf("nfv9 delete i_vrf "); - return; - } - - mp = spp_msg_api_alloc (sizeof (*mp)); - memset(mp, 0, sizeof (*mp)); - mp->_spp_msg_id = SPP_API_CNAT_V4_CONFIG_NFV9_LOGGING; - mp->enable = 0; - mp->i_vrf = spp_host_to_net_byte_order_16(argv[0]); - platform_send_msg(mp); -} - -void cnat_generic_cmd (int argc, unsigned long *argv) -{ - spp_api_cnat_generic_command_request_t *mp; - - if (argc != 9) { - printf("generic command core type p1 p2 p3 p4 p5 p6 p7 "); - return; - } - - /* - * Allocate a large buffer for message req and resp structure - */ - mp = spp_msg_api_alloc (MAX_DEBUG_BUFFER_SIZE); - memset(mp, 0, MAX_DEBUG_BUFFER_SIZE); - mp->_spp_msg_id = SPP_API_CNAT_GENERIC_COMMAND_REQUEST; - mp->core_num = argv[0]; - mp->params[0] = spp_host_to_net_byte_order_32(argv[1]); - mp->params[1] = spp_host_to_net_byte_order_32(argv[2]); - mp->params[2] = spp_host_to_net_byte_order_32(argv[3]); - mp->params[3] = spp_host_to_net_byte_order_32(argv[4]); - mp->params[4] = spp_host_to_net_byte_order_32(argv[5]); - mp->params[5] = spp_host_to_net_byte_order_32(argv[6]); - mp->params[6] = spp_host_to_net_byte_order_32(argv[7]); - mp->params[7] = spp_host_to_net_byte_order_32(argv[8]); - platform_send_msg(mp); -} - -u32 icmp_sent_timestamps; /* 32 KB array per core */ -u8 v4_pkt_count = 0; - -cnat_icmp_msg_t icmp_msg_gen_allowed () -{ -#ifdef DISABLE_ICMP_THROTTLE_FOR_DEBUG_PURPOSE - return CNAT_ICMP_MSG; -#else - u32 current_timestamp; - spp_node_main_vector_t *nmv; - u32 updated_timestamp; - - v4_pkt_count ++; - - nmv = spp_get_node_main_vectorized_inline(); - - current_timestamp = nmv->ticks / nmv->ticks_per_second; - - PLATFORM_UPDATE_TIMESTAMP - if (PREDICT_FALSE(icmp_sent_timestamps != updated_timestamp)) { - v4_pkt_count = 1; - /* update timestamp */ - icmp_sent_timestamps = updated_timestamp; - } - if (PREDICT_TRUE(v4_pkt_count <= cnat_main_db_icmp_rate_limit_core)) { - return CNAT_ICMP_MSG; - } else { - return CNAT_NO_ICMP_MSG; - } -#endif -} - -u32 v6_icmp_sent_timestamps; /* 32 KB array per core */ -u8 v6_pkt_count = 0; - -cnat_icmp_msg_t v6_icmp_msg_gen_allowed () -{ -#ifdef DISABLE_ICMP_THROTTLE_FOR_DEBUG_PURPOSE - return CNAT_ICMP_MSG; -#else - u32 current_timestamp; - spp_node_main_vector_t *nmv; - u32 updated_timestamp; - - nmv = spp_get_node_main_vectorized_inline(); - - current_timestamp = nmv->ticks / nmv->ticks_per_second; - PLATFORM_UPDATE_TIMESTAMP - v6_pkt_count ++; - - if (PREDICT_FALSE(v6_icmp_sent_timestamps != updated_timestamp)) { - v6_pkt_count = 1; - /* update timestamp */ - v6_icmp_sent_timestamps = updated_timestamp; - } - if (PREDICT_TRUE(v6_pkt_count <= cnat_main_db_icmp_rate_limit_core)) { - return CNAT_ICMP_MSG; - } else { - return CNAT_NO_ICMP_MSG; - } -#endif -} - -u32 v4_udp_crc_zero_timestamps; -u32 v4_udp_crc_zero_pkt_count = 0; -int v4_crc_zero_udp_allowed () -{ - PLATFORM_V4_CRC_ZERO_UDP_ALLOWED - /* Currently not supported for Brahmos. we need to take care of this */ - spp_node_main_vector_t *nmv; - u32 hash_value, current_timestamp; - - nmv = spp_get_node_main_vectorized_inline(); - - current_timestamp = nmv->ticks / nmv->ticks_per_second; - v4_udp_crc_zero_pkt_count++; - if (PREDICT_FALSE(v4_udp_crc_zero_timestamps != current_timestamp)) { - v4_udp_crc_zero_pkt_count = 1; - v4_udp_crc_zero_timestamps = current_timestamp; - } - if (PREDICT_TRUE(v4_udp_crc_zero_pkt_count <= - crc_zero_udp_rate_limit_core)) { - return 1; - } else { - return 0; - } -} - -/* - * ipv4_decr_ttl_n_calc_csum() - * - It decrements the TTL and calculates the incremental IPv4 checksum - */ - -ALWAYS_INLINE( -void ipv4_decr_ttl_n_calc_csum(ipv4_header *ipv4)) -{ - u32 checksum; - u16 old; - - old = ntohs(*(u16 *)&ipv4->ttl); - - /* Decrement TTL */ - ipv4->ttl--; - - /* Calculate incremental checksum */ - checksum = old + (~ntohs(*(u16 *)&ipv4->ttl) & 0xFFFF); - checksum += ntohs(ipv4->checksum); - checksum = (checksum & 0xFFFF) + (checksum >> 16); - ipv4->checksum = htons(checksum + (checksum >> 16)); -} - -ALWAYS_INLINE( -void calc_ipv4_checksum (ipv4_header *ipv4)) -{ - u16 *data = (u16 *) ipv4; - u32 checksum = 0; - - checksum = crc_calc(ipv4); - - /* Now produce the 1's complement */ - ipv4->checksum = spp_host_to_net_byte_order_16(((u16) (~(u16)checksum))); -} - -ALWAYS_INLINE( -void calc_v4_icmp_checksum (icmp_v4_t *icmp, int ipv4_payload_size)) -{ - u16 *data = (u16 *) icmp; - int num_hwords = (ipv4_payload_size)/2; - u32 checksum = 0; - - icmp->checksum = 0; - if (PREDICT_FALSE((ipv4_payload_size%2) != 0)) { - num_hwords += 1; - /* Append 0's in the last octet */ - *((u8 *)data + ipv4_payload_size) = 0; - } - while (num_hwords) { - checksum += (u32)spp_net_to_host_byte_order_16(data++); - num_hwords--; - } - - /* Add in the carry of the original sum */ - checksum = (checksum & 0xFFFF) + (checksum >> 16); - /* Add in the carry of the final sum */ - checksum = (checksum & 0xFFFF) + (checksum >> 16); - /* Now produce the 1's complement */ - icmp->checksum = spp_host_to_net_byte_order_16(((u16) (~(u16)checksum))); -} - -ALWAYS_INLINE( -void calc_v6_icmp_checksum (ipv6_header_t *ipv6, u16 ip_payload_size)) -{ - u16 *data; - u16 *data1; - int i; - icmp_v6_t *icmp; - int num_hwords = (ip_payload_size)/2; - u32 checksum = 0; - pseudo_v6_header_t pseudo_header; - - icmp = (icmp_v6_t *) ((u8 *)ipv6 + IPV6_HDR_LEN); - data = (u16 *) icmp; - icmp->checksum = 0; - -#if 1 - if (PREDICT_FALSE((ip_payload_size%2) != 0)) { - num_hwords += 1; - /* Append 0's in the last octet */ - *((u8 *)data + ip_payload_size) = 0; - } -#endif - - /* construct the pseudo header */ - - pseudo_header.src_addr[0] = ipv6->src_addr[0]; - pseudo_header.src_addr[1] = ipv6->src_addr[1]; - pseudo_header.src_addr[2] = ipv6->src_addr[2]; - pseudo_header.src_addr[3] = ipv6->src_addr[3]; - pseudo_header.dst_addr[0] = ipv6->dst_addr[0]; - pseudo_header.dst_addr[1] = ipv6->dst_addr[1]; - pseudo_header.dst_addr[2] = ipv6->dst_addr[2]; - pseudo_header.dst_addr[3] = ipv6->dst_addr[3]; - pseudo_header.payload_length = spp_host_to_net_byte_order_16(ip_payload_size); - pseudo_header.next_header = spp_host_to_net_byte_order_16(ipv6->next_header); - - data1 = (u16 *) &pseudo_header; - - /* sizeof(pseudo_v6_header_t) = 36 */ - for (i = 0; i < 18; i++) { - checksum += (u32)spp_net_to_host_byte_order_16(data1++); - } - -checksum_calc: - - if (PREDICT_TRUE(num_hwords)) { - checksum += (u32)spp_net_to_host_byte_order_16(data); - num_hwords--; - data++; - goto checksum_calc; - } - - /* Add in the carry of the original sum */ - checksum = (checksum & 0xFFFF) + (checksum >> 16); - /* Add in the carry of the final sum */ - checksum = (checksum & 0xFFFF) + (checksum >> 16); - /* Now produce the 1's complement */ - icmp->checksum = spp_host_to_net_byte_order_16(((u16) (~(u16)checksum))); -} - -void icmp_error_generate_v6 (spp_ctx_t *ctx, u8 icmp_type, - u8 icmp_code, u16 uidb_index) { - - u16 ip_hdr_len, ip_payload_size; - u32 *src_p, * dst_p; - icmp_v6_t *icmp; - int i; - ipv6_header_t *ip_old, *ip_new; - u16 icmp_payload_len; - - /* - * As per RFC 2463, we limit the maximum size of generated ICMPv6 message to * 1280. And hence if the packet is bigger than 1280, then it needs to be - * truncated. Also, if the packet had multiple chained buffers, we need to - * free all chained buffers, except the first one. - */ - free_all_but_first_chained_buffers(ctx); - - ip_hdr_len = IPV6_HDR_LEN; - /* offset to ip payload */ - - ip_old = (ipv6_header_t *)PLATFORM_CTX_CURRENT_HDR; - ip_new = (ipv6_header_t *) ((u8 *) PLATFORM_CTX_CURRENT_HDR - ICMPV6_ERR_SIZE); - icmp = (icmp_v6_t*) ( (u8*)ip_new + ip_hdr_len); - - icmp_payload_len = ip_hdr_len + - spp_net_to_host_byte_order_16(&(ip_old->payload_length)) ; - - ip_payload_size = ICMPV6_HDR_SIZE + icmp_payload_len; - /* - * There is no easy way to predict this case as the probablity that the IPv6 - * pkt is big depends on the type of traffic. Let us optimize the big - * pkt case as it involves more processing - * - * If the pkt size exceeds IPV6_MIN_PATH_MTU truncate it to IPV6_MIN_PATH_MTU - */ - if (PREDICT_TRUE((ip_payload_size + ip_hdr_len) > IPV6_MIN_PATH_MTU)) { - ip_payload_size = IPV6_MIN_PATH_MTU - ip_hdr_len; - } - - /* Following ICMP op has to be after ip header being copied */ - icmp->type = icmp_type; - icmp->code = icmp_code; - - ip_new->version_trafficclass_flowlabel = spp_host_to_net_byte_order_32( - VERSION_TRAFFICCLASS_FLOWLABEL); - ip_new->payload_length = spp_host_to_net_byte_order_16(ip_payload_size); - ip_new->next_header = IPV6_PROTO_ICMPV6; - ip_new->hop_limit = 64; - ip_new->dst_addr[0] = ip_old->src_addr[0]; - ip_new->dst_addr[1] = ip_old->src_addr[1]; - ip_new->dst_addr[2] = ip_old->src_addr[2]; - ip_new->dst_addr[3] = ip_old->src_addr[3]; - - ip_new->src_addr[0] = - spp_host_to_net_byte_order_32(svi_params_array[uidb_index].ipv6_addr[0]); - ip_new->src_addr[1] = - spp_host_to_net_byte_order_32(svi_params_array[uidb_index].ipv6_addr[1]); - ip_new->src_addr[2] = - spp_host_to_net_byte_order_32(svi_params_array[uidb_index].ipv6_addr[2]); - ip_new->src_addr[3] = - spp_host_to_net_byte_order_32(svi_params_array[uidb_index].ipv6_addr[3]); - /* calc checksum for icmp */ - - calc_v6_icmp_checksum(ip_new, ip_payload_size); -#if 0 - printf("Flow = 0x%x\n", ip_new->version_trafficclass_flowlabel); - printf("Hoplimit = 0x%x\n", ip_new->hop_limit); - printf("Length= 0x%x\n", ip_new->payload_length); - printf("Next header = 0x%x\n", ip_new->next_header); - printf("Src add0 = 0x%x\n", ip_new->src_addr[0]); - printf("Src add1 = 0x%x\n", ip_new->src_addr[1]); - printf("Src add2 = 0x%x\n", ip_new->src_addr[2]); - printf("Src add3 = 0x%x\n", ip_new->src_addr[3]); - printf("Dst add0 = 0x%x\n", ip_new->dst_addr[0]); - printf("Dst add1 = 0x%x\n", ip_new->dst_addr[1]); - printf("Dst add2 = 0x%x\n", ip_new->dst_addr[2]); - printf("Dst add3 = 0x%x\n", ip_new->dst_addr[3]); - printf("Icmp type = 0x%x\n", icmp->type); - printf("Icmp code = 0x%x\n", icmp->code); - - printf("\n\nICMP packet:\n"); - for (i = 0; i < 10; i ++) { - printf("0x%x " , *((u8 *)icmp + i)); - if ((i%16) == 15) { - printf("\n"); - } - } -#endif - - ctx->current_header -= ICMPV6_ERR_SIZE; - ctx->current_length = ip_payload_size + ip_hdr_len; - PLATFORM_CNAT_SET_TX_VRF(ctx,uidb_index); -} - -void icmp_error_generate_v2 (ipv4_header *ip, u8 icmp_type, - u8 icmp_code, u16 mtu, u32 src_ip) -{ - - u16 ip_hdr_len, ip_payload_size; - u32 *src_p, * dst_p; - icmp_v4_t *icmp; - - ip_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; /* offset to ip payload */ - icmp = (icmp_v4_t*) ( (u8*)ip + ip_hdr_len); - ip_payload_size = sizeof(icmp_v4_t) + ip_hdr_len + - ICMP_UNREACHABLE_IP_PAYLOAD_SIZE; - - src_p = (u32*) - ((u8*)ip + ip_hdr_len + ICMP_UNREACHABLE_IP_PAYLOAD_SIZE - 4); - dst_p = (u32*) ((u8*)src_p + sizeof(ipv4_header) + - sizeof(icmp_v4_t)); - - while(src_p >= (u32*)ip) *dst_p-- = *src_p--; - - /* Following ICMP op has to be after ip header being copied */ - icmp->type = icmp_type; - icmp->code = icmp_code; - icmp->identifier = 0; - icmp->sequence = 0; - if(PREDICT_FALSE(mtu != 0)) { - icmp->sequence = spp_host_to_net_byte_order_16(mtu); - } - - - /* build icmp header, keep original tos, identification values */ - ip->version_hdr_len_words = 0x45; - ip->total_len_bytes = sizeof(ipv4_header) + ip_payload_size; - ip->total_len_bytes = spp_host_to_net_byte_order_16(ip->total_len_bytes); - ip->frag_flags_offset = 0; - ip->ttl = 64; - ip->protocol = ICMP_PROT; - ip->checksum = 0; - ip->dest_addr = ip->src_addr; - ip->src_addr = spp_host_to_net_byte_order_32(src_ip); - - /* calc checksum for ip and icmp */ - - calc_ipv4_checksum(ip); - calc_v4_icmp_checksum( (icmp_v4_t *) ((u8*) ip + sizeof(ipv4_header)), - ip_payload_size); -} - -void icmp_error_generate (ipv4_header *ip, u8 icmp_type, - u8 icmp_code, u16 uidb_index) { - - u16 ip_hdr_len, ip_payload_size; - u32 *src_p, * dst_p; - icmp_v4_t *icmp; - - ip_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; /* offset to ip payload */ - icmp = (icmp_v4_t*) ( (u8*)ip + ip_hdr_len); - ip_payload_size = sizeof(icmp_v4_t) + ip_hdr_len + - ICMP_UNREACHABLE_IP_PAYLOAD_SIZE; - - src_p = (u32*) - ((u8*)ip + ip_hdr_len + ICMP_UNREACHABLE_IP_PAYLOAD_SIZE - 4); - dst_p = (u32*) ((u8*)src_p + sizeof(ipv4_header) + - sizeof(icmp_v4_t)); - - while(src_p >= (u32*)ip) *dst_p-- = *src_p--; - - /* Following ICMP op has to be after ip header being copied */ - icmp->type = icmp_type; - icmp->code = icmp_code; - icmp->identifier = 0; - icmp->sequence = 0; - - - /* build icmp header, keep original tos, identification values */ - ip->version_hdr_len_words = 0x45; - ip->total_len_bytes = sizeof(ipv4_header) + ip_payload_size; - ip->total_len_bytes = spp_host_to_net_byte_order_16(ip->total_len_bytes); - ip->frag_flags_offset = 0; - ip->ttl = 64; - ip->protocol = ICMP_PROT; - ip->checksum = 0; - ip->dest_addr = ip->src_addr; - - ip->src_addr = spp_host_to_net_byte_order_32(svi_params_array[uidb_index].ipv4_addr); - - /* calc checksum for ip and icmp */ - - calc_ipv4_checksum(ip); - calc_v4_icmp_checksum( (icmp_v4_t *) ((u8*) ip + sizeof(ipv4_header)), - ip_payload_size); -#if 0 - printf("version_hdr_len_words = 0x%x\n", ip->version_hdr_len_words); - printf("total_len_bytes = 0x%x\n", ip->total_len_bytes); - printf("Frag = 0x%x\n", ip->frag_flags_offset); - printf("ttl = 0x%x\n", ip->ttl); - printf("Protocol = 0x%x\n", ip->protocol); - printf("checksum = 0x%x\n", ip->checksum); - printf("Dest addr = 0x%x\n", ip->dest_addr); - printf("Src addr = 0x%x\n", ip->src_addr); - printf("Icmp type = 0x%x\n", icmp->type); - printf("Icmp code = 0x%x\n", icmp->code); -#endif - -} - -int icmpv4_generate_with_throttling_v2 (spp_ctx_t *ctx, ipv4_header *ipv4, - int icmp_type, int icmp_code, - u16 mtu, u32 src_ip) -{ - u16 ip_hdr_len; - icmp_v4_t *icmp; - u16 rx_uidb_index = ctx->ru.rx.uidb_index; - if (icmp_msg_gen_allowed()) { - free_all_but_first_chained_buffers(ctx); - icmp_error_generate_v2(ipv4, icmp_type, icmp_code, mtu, src_ip); - ctx->current_length = (u16) - ((u8*)ctx->current_header - ctx->packet_data) + - spp_net_to_host_byte_order_16(&ipv4->total_len_bytes); - PLATFORM_CNAT_SET_TX_VRF(ctx,rx_uidb_index); - return 1; - } else { - return 0; - } -} - -int icmpv4_generate_with_throttling (spp_ctx_t *ctx, ipv4_header *ipv4, - u16 rx_uidb_index) -{ - int icmp_type; - int icmp_code; - - if (icmp_msg_gen_allowed()) { - /* ICMP error would be small, so one buffer is enough. Clear the other */ - free_all_but_first_chained_buffers(ctx); - - icmp_type = ICMPV4_TIMEEXCEEDED; - icmp_code = ICMPV4_TIMTTL; - icmp_error_generate(ipv4, icmp_type, icmp_code, rx_uidb_index); - ctx->current_length = (u16) - ((u8*)ctx->current_header - ctx->packet_data) + - spp_net_to_host_byte_order_16(&ipv4->total_len_bytes); - PLATFORM_CNAT_SET_TX_VRF(ctx,rx_uidb_index); - return 1; - } else { - return 0; - } -} - -int icmpv4_generate_with_throttling_v1 (spp_ctx_t *ctx, ipv4_header *ipv4, - u16 rx_uidb_index, u32 type, u32 code) -{ - if (icmp_msg_gen_allowed()) { - /* ICMP error would be small, so one buffer is enough. Clear the other */ - free_all_but_first_chained_buffers(ctx); - - icmp_error_generate(ipv4, type, code, rx_uidb_index); - ctx->current_length = (u16) - ((u8*)ctx->current_header - ctx->packet_data) + - spp_net_to_host_byte_order_16(&ipv4->total_len_bytes); - PLATFORM_CNAT_SET_TX_VRF(ctx,rx_uidb_index); - return 1; - } else { - return 0; - } -} - - -int icmpv6_generate_with_throttling (spp_ctx_t *ctx, ipv6_header_t *ipv6, - u16 rx_uidb_index) -{ - int icmp_type; - int icmp_code; - - if (v6_icmp_msg_gen_allowed()) { - icmp_type = ICMPV6_TIMEEXCEEDED; - icmp_code = ICMPV6_TIMTTL; - icmp_error_generate_v6(ctx, icmp_type, icmp_code, rx_uidb_index); - return 1; - } else { - return 0; - } -} - -int icmpv6_generate_with_throttling_v1 (spp_ctx_t *ctx, ipv6_header_t *ipv6, - u16 rx_uidb_index, u32 type, u32 code) -{ - - if (v6_icmp_msg_gen_allowed()) { - icmp_error_generate_v6(ctx, type, code, rx_uidb_index); - return 1; - } else { - return 0; - } -} -#endif - -void calculate_window_scale(tcp_hdr_type *tcp_header, u8 *scale) { - - u8 check_options = 0; - - *scale = 0; - check_options = ((tcp_header->flags & TCP_FLAG_SYN) && - (((tcp_header->hdr_len>>4) << 2) > sizeof(tcp_hdr_type))); - - if (PREDICT_FALSE(check_options)) { - u8 *options_ptr = tcp_findoption(tcp_header, TCP_OPTION_WINDOW_SCALE); - - /* - * TCP option field: | kind 1B | len 1B | value 2B| - * where kind != [0, 1] - */ - if (PREDICT_TRUE(options_ptr && - (options_ptr[1] == TCP_OPTION_WINDOW_SCALE))) { - u8 *ptr = (u8*)(options_ptr + 2); - *scale = *ptr; - - if(PREDICT_FALSE(*scale >= 14)) { - *scale = 14; - } - - return; - } - } -} - -#if 0 -ALWAYS_INLINE( -void cnat_log_nat44_tcp_seq_mismatch( - cnat_main_db_entry_t *db, - cnat_vrfmap_t *vrfmap)) -{ - /* As of now, Netflow does not require this to be logged - * So only syslog - */ - if(PREDICT_TRUE(db->flags & CNAT_TAC_SEQ_MISMATCH)) { - /* Already logged ..*/ - return; - } - /* else, set the flag and call the log API */ - - db->flags = db->flags | CNAT_TAC_SEQ_MISMATCH; - - cnat_syslog_nat44_tcp_seq_mismatch(db, vrfmap); -} - - -static int cnat_util_init (void *notused) -{ - /* run SPP_API_CNAT_PORTMAP_CREATE first*/ - spp_msg_api_set_handler(SPP_API_CNAT_PORT_ALLOCATE, - spp_api_cnat_port_allocate_t_handler); - - - spp_msg_api_set_handler(SPP_API_CNAT_PORT_CLEAR, - spp_api_cnat_port_clear_t_handler); - - /* run vrfmap config first */ - spp_msg_api_set_handler(SPP_API_CNAT_PORT_CREATE, - spp_api_cnat_port_create_t_handler); - - spp_msg_api_set_handler(SPP_API_CNAT_PORT_DELETE, - spp_api_cnat_port_delete_t_handler); - return 0; -} - -void -print_ipv6_pkt (ipv6_header_t *ip) -{ - u32 i, total_len, l4_len=0; - - u8 *pkt = (u8 *) ip; - - total_len = spp_net_to_host_byte_order_16(&ip->payload_length); - - /* we rarely need to debug > 200 bytes of packet */ - if(total_len > 200) { - total_len = 200; - } - - printf("\n======== PRINTING PKT START======\n"); - printf("======== IPv6 PAYLOAD LEN %d ===========\n", total_len); - for (i=0; i < 40; i++) { - printf(" %02X ", *(pkt + i)); - if(i%16==15) - printf("\n"); - } - - if (ip->next_header == IPV6_PROTO_TCP) { - printf("\n======== TCP HEADER =================\n"); - l4_len = 20; - } - else if (ip->next_header == IPV6_PROTO_UDP) { - printf("\n======== UDP HEADER =================\n"); - l4_len = 8; - } - else if (ip->next_header == IPV6_PROTO_ICMPV6) { - printf("\n======== ICMP HEADER =================\n"); - l4_len = 8; - } - - for (i=40; i < (l4_len + 40); i++) { - printf(" %02X ", *(pkt + i)); - } - - printf("\n======== LAYER4 PAYLOAD ===================\n"); - for (i=(l4_len + 40); i < total_len; i++) { - printf(" %02X ", *(pkt + i)); - if(i%16==15) - printf("\n"); - } - - printf("\n======== PRINTING PKT END =======\n"); -} - - - -PLATFORM_SPP_INIT_FUNCTION(cnat_util_init); -#endif diff --git a/plugins/plugins/vcgn/cnat_v4_ftp_alg.h b/plugins/plugins/vcgn/cnat_v4_ftp_alg.h deleted file mode 100644 index df3dfcb0..00000000 --- a/plugins/plugins/vcgn/cnat_v4_ftp_alg.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - *------------------------------------------------------------------ - * cnat_v4_ftp_alg.h - * - * Copyright (c) 2012-2013 Cisco and/or its affiliates. - * 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 __CNAT_V4_FTP_ALG_H__ -#define __CNAT_V4_FTP_ALG_H__ - - -#include -#include - -#include "tcp_header_definitions.h" -#include "dslite_defs.h" -#include "dslite_db.h" - -/* shorter form of byte order functions */ - -#define net2host16(x) clib_net_to_host_u16( x) -#define net2host32(x) clib_net_to_host_u32( x) -#define net2host64(x) clib_net_to_host_u64( x) -#define host2net16(x) clib_host_to_net_u16(x) -#define host2net32(x) clib_host_to_net_u32(x) -#define host2net64(x) clib_host_to_net_u64(x) - -//#define BIGENDIAN - -typedef struct iphdrtype_ { - u8 v_ihl; /* version and IP header length */ - u8 tos; /* type of service */ - u16 tl; /* total length */ - u16 id; /* identifier */ - u16 ipreserved: 1; - u16 dontfragment: 1; - u16 morefragments: 1; - u16 fo: 13; /* fragment offset */ - u8 ttl; /* time to live */ - u8 prot; /* protocol type */ - u16 checksum; /* checksum */ - u32 srcadr; /* IP source address */ - u32 dstadr; /* IP destination address */ -} iphdrtype; - - -typedef struct tcptype_ { - u16 sourceport; - u16 destinationport; - u32 sequencenumber; - u32 acknowledgementnumber; - u8 dataoffset; - u8 flags; -#if 0 -/* bypass the ENDIAN part */ -#ifdef BIGENDIAN - u8 reserved: 2; - u8 urg: 1; - u8 ack: 1; - u8 psh: 1; - u8 rst: 1; - u8 syn: 1; - u8 fin: 1; -#else - u8 fin: 1; - u8 syn: 1; - u8 rst: 1; - u8 psh: 1; - u8 ack: 1; - u8 urg: 1; - u8 reserved2: 2; -#endif -#endif - - u16 window; - u16 checksum; - u16 urgentpointer; - u8 data[0]; -} tcptype ; - - -int watch_ftp_port_cmd (iphdrtype *ip, - tcptype *tcp, - u32 * ip_addr, - u16 * port); - - -u8 * ftp_test_pkt_gen (u32 ip_addr, u16 port); - -int update_ftp_port(u8 * pkt, u32 new_ip, u16 new_port, i8 * delta, - cnat_main_db_entry_t *db_tcp_control, - dslite_table_entry_t *dslite_entry_ptr, - ipv6_header_t *ipv6_hdr); -/* - * caller needs to check if it's a ftp packet - * this function returns 1 - * if packet being updated for PORT - * otherwise return 0. - * Assume IP header DOES NOT have option fields - */ - -int cnat_ftp_alg ( u8* pkt, i8 * delta, cnat_main_db_entry_t *db, - dslite_table_entry_t *dslite_entry_ptr, - ipv6_header_t *ipv6_hdr); - -#define FTP_ALG_DEBUG_PRINTF_ENABLED 1 - -#ifdef FTP_ALG_DEBUG_PRINTF_ENABLED - -#define FTP_ALG_DEBUG_PRINTF(...) { \ - if (global_debug_flag & CNAT_DEBUG_FTP_ALG) { \ - printf(__VA_ARGS__); \ - } } - -#else - -#define FTP_ALG_DEBUG_PRINTF(...) - -#endif - -#endif /* __CNAT_V4_FTP_ALG_H__ */ diff --git a/plugins/plugins/vcgn/cnat_v4_functions.c b/plugins/plugins/vcgn/cnat_v4_functions.c deleted file mode 100644 index d3051fba..00000000 --- a/plugins/plugins/vcgn/cnat_v4_functions.c +++ /dev/null @@ -1,364 +0,0 @@ -/* - *--------------------------------------------------------------------------- - * cnat_v4_funtions.c - * - * Copyright (c) 2008-2013 Cisco and/or its affiliates. - * 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 -#include -#include -#include - - -#include "tcp_header_definitions.h" -#include "cnat_db.h" -#include "cnat_config.h" -#include "cnat_v4_functions.h" -#include "dslite_defs.h" -#include "dslite_db.h" - -static u32 tcp_logging_count; -static u32 tcp_logging_overflow; - -static tcp_logging_struct_t tcp_logging_array[MAX_TCP_LOGGING_COUNT]; - -/* - * Function to log TCP pkts checksum changes.. - */ -void -tcp_debug_logging ( - u32 seq_num, - u32 ack_num, - u32 old_ip, - u32 new_ip, - u16 old_port, - u16 new_port, - u16 old_ip_crc, - u16 new_ip_crc, - u16 old_tcp_crc, - u16 new_tcp_crc) -{ - tcp_logging_array[tcp_logging_count].seq_num = seq_num; - tcp_logging_array[tcp_logging_count].ack_num = ack_num; - tcp_logging_array[tcp_logging_count].old_ip = old_ip; - tcp_logging_array[tcp_logging_count].new_ip = new_ip; - tcp_logging_array[tcp_logging_count].old_port = old_port; - tcp_logging_array[tcp_logging_count].new_port = new_port; - tcp_logging_array[tcp_logging_count].old_ip_crc = old_ip_crc; - tcp_logging_array[tcp_logging_count].new_ip_crc = new_ip_crc; - tcp_logging_array[tcp_logging_count].old_tcp_crc = old_tcp_crc; - tcp_logging_array[tcp_logging_count].new_tcp_crc = new_tcp_crc; - - tcp_logging_count++; - - if (tcp_logging_count >= MAX_TCP_LOGGING_COUNT) { - tcp_logging_overflow = 1; - tcp_logging_count = 0; - } -} - -/* - * Function to dmp TCP pkts logged.. - */ -void -tcp_debug_logging_dump (void) -{ - u32 i, total_count, start_entry; - - if (tcp_logging_overflow) { - total_count = MAX_TCP_LOGGING_COUNT; - start_entry = tcp_logging_count; - printf("Logging Entries Wrapped Around, displaying %d entries\n", - total_count); - } else { - total_count = tcp_logging_count; - start_entry = 0; - printf("Displaying %d entries\n", total_count); - } - - printf("SEQ ACK IP_O IP_N PORT_O PORT_N L3_CRC_O L3_CRC_N L4_CRC_O L4_CRC_N\n"); - - for (i = 0; i < total_count; i++) { - u32 entry = (i + start_entry) % MAX_TCP_LOGGING_COUNT; - - printf("%04d: 0x%08x 0x%08x 0x%08x 0x%08x 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x\n", - entry, - tcp_logging_array[entry].seq_num, - tcp_logging_array[entry].ack_num, - tcp_logging_array[entry].old_ip, - tcp_logging_array[entry].new_ip, - tcp_logging_array[entry].old_port, - tcp_logging_array[entry].new_port, - tcp_logging_array[entry].old_ip_crc, - tcp_logging_array[entry].new_ip_crc, - tcp_logging_array[entry].old_tcp_crc, - tcp_logging_array[entry].new_tcp_crc); - } -} - -/* - * Function to enable TCP logging - */ -void -tcp_debug_logging_enable_disable (u32 enable_flag) -{ - switch (enable_flag) { - - case TCP_LOGGING_DISABLE: - if (tcp_logging_enable_flag == TCP_LOGGING_DISABLE) { - printf("\nTCP Logging ALREADY DISABLED\n"); - } else { - printf("\nTCP Logging DISABLED\n"); - } - tcp_logging_enable_flag = 0; - break; - - case TCP_LOGGING_ENABLE: - if (tcp_logging_enable_flag == TCP_LOGGING_ENABLE) { - printf("\nTCP Logging ALREADY ENABLED\n"); - } else { - tcp_logging_enable_flag = 1; - tcp_logging_count = 0; - tcp_logging_overflow = 0; - - printf("\nTCP Logging ENABLED\n"); - } - break; - - case TCP_LOGGING_PACKET_DUMP: - tcp_debug_logging_dump(); - break; - - case TCP_LOGGING_SUMMARY_DUMP: - default: - printf("\ntcp_logging_enable_flag %d, tcp_log_count %d\n", - tcp_logging_enable_flag, tcp_logging_count); - printf("To Enable TCP LOGGING provide a flag value of %d\n", - TCP_LOGGING_ENABLE); - break; - } -} - -void hex_dump (u8 * p, int len) { - int i; - for (i=0;itotal_len_bytes); - - printf("\n======== PRINTING PKT START======\n"); - printf("======== IP PACKET LEN %d ===========\n", total_len); - for (i=0; i < 20; i++) { - printf(" %02X ", *(pkt + i)); - } - - printf("\n======== ICMP HEADER =================\n"); - for (i=20; i < 28; i++) { - printf(" %02X ", *(pkt + i)); - } - - printf("\n======== ICMP BODY ===================\n"); - for (i=28; i < total_len; i++) { - printf(" %02X ", *(pkt + i)); - } - - printf("\n======== PRINTING PKT END =======\n"); -} - -void -print_udp_pkt (ipv4_header *ip) -{ - u32 i, total_len, udp_len; - - u8 *pkt = (u8 *) ip; - - total_len = clib_net_to_host_u16(ip->total_len_bytes); - udp_len = total_len - 20; - - printf("\n======== PRINTING PKT START======\n"); - printf("======== IP PACKET LEN %d ===========\n", total_len); - for (i=0; i < 20; i++) { - printf(" %02X ", *(pkt + i)); - } - printf("\n======== UDP PSEUDO HEADER ==========\n"); - for (i=12; i < 20; i++) { - printf(" %02X ", *(pkt + i)); - } - printf(" 00 11 %02X %02X ", udp_len >> 8, udp_len & 0xff); - - printf("\n======== UDP HEADER =================\n"); - for (i=20; i < 28; i++) { - printf(" %02X ", *(pkt + i)); - } - printf("\n======== UDP BODY ===================\n"); - for (i=28; i < total_len; i++) { - printf(" %02X ", *(pkt + i)); - } - - printf("\n======== PRINTING PKT END =======\n"); -} - -void -print_tcp_pkt (ipv4_header *ip) -{ - u32 i, total_len, tcp_len; - - u8 *pkt = (u8 *) ip; - - total_len = clib_net_to_host_u16(ip->total_len_bytes); - tcp_len = total_len - 20; - - printf("\n======== PRINTING PKT START======\n"); - printf("======== IP PACKET LEN %d ===========\n", total_len); - for (i=0; i < 20; i++) { - printf(" %02X ", *(pkt + i)); - } - printf("\n======== TCP PSEUDO HEADER ==========\n"); - for (i=12; i < 20; i++) { - printf(" %02X ", *(pkt + i)); - } - printf(" 00 06 %02X %02X ", tcp_len >> 8, tcp_len & 0xff); - - printf("\n======== TCP HEADER =================\n"); - for (i=20; i < 40; i++) { - printf(" %02X ", *(pkt + i)); - } - printf("\n======== TCP BODY ===================\n"); - for (i=40; i < total_len; i++) { - printf(" %02X ", *(pkt + i)); - } - - printf("\n======== PRINTING PKT END =======\n"); -} - -/* IN: ipv4 and tcp header pointer, - * new ipv4 addr and port value - * main db index for accessing per vrf mss value - * DO: - * NAT - * mss adjust if needed - * ip & tcp checksum update (incremental) - */ - -inline void tcp_in2out_nat_mss_n_checksum (ipv4_header * ip, - tcp_hdr_type * tcp, - u32 ipv4_addr, - u16 port, - cnat_main_db_entry_t * db) -{ - u8 *mss_ptr; - u8 check_mss = 0; - u16 mss_old, mss_new; - cnat_vrfmap_t * vrf_map_p; - - cnat_v4_recalculate_tcp_checksum(ip, - tcp, - &(ip->src_addr), - &(tcp->src_port), - ipv4_addr, - port); - u16 frag_offset = - clib_net_to_host_u16(ip->frag_flags_offset); - - if(PREDICT_FALSE(frag_offset & IP_FRAG_OFFSET_MASK)) { - return; /* No TCP Header at all */ - } - - /* - * check SYN bit and if options field is present - * If yes, proceed to extract the options and get TCP MSS value - */ - check_mss = ((tcp->flags & TCP_FLAG_SYN) && - (((tcp->hdr_len>>4) << 2) > sizeof(tcp_hdr_type))); - - if (PREDICT_FALSE(check_mss)) { - - /* get per VRF mss config */ - if(PREDICT_FALSE(db->flags & (CNAT_DB_DSLITE_FLAG))) { - mss_new = dslite_table_db_ptr[db->dslite_nat44_inst_id].tcp_mss; - } else { - vrf_map_p = cnat_map_by_vrf + db->vrfmap_index; - mss_new = vrf_map_p->tcp_mss; - } - DSLITE_PRINTF(1, "Check MSS true..%u\n", mss_new); - /* - * If TCP MSS is not configured, skip the MSS checks - */ - if (PREDICT_FALSE(mss_new != V4_TCP_MSS_NOT_CONFIGURED_VALUE)) { - - /* if mss_ptr != NULL, then it points to MSS option */ - mss_ptr = tcp_findoption(tcp, TCP_OPTION_MSS); - - /* - * TCP option field: | kind 1B | len 1B | value 2B| - * where kind != [0,1] - */ - if (PREDICT_TRUE(mss_ptr && (mss_ptr[1] == 4))) { - - u16 *ptr = (u16*)(mss_ptr + 2); - - mss_old = clib_net_to_host_u16(*ptr); - - if (PREDICT_FALSE(mss_old > mss_new)) { - u32 sum32; - u16 mss_old_r, old_tcp_checksum_r; - - *ptr = clib_host_to_net_u16(mss_new); - - mss_old_r = ~mss_old; - - old_tcp_checksum_r = - ~clib_net_to_host_u16(tcp->tcp_checksum); - - /* - * Revise the TCP checksum - */ - sum32 = old_tcp_checksum_r + mss_old_r + mss_new; - FILL_CHECKSUM(tcp->tcp_checksum, sum32) - - if (PREDICT_FALSE(tcp_logging_enable_flag)) { - tcp_debug_logging( - clib_net_to_host_u32(tcp->seq_num), - clib_net_to_host_u32(tcp->ack_num), - 0, - 0, - mss_old, - mss_new, - 0, - 0, - ~old_tcp_checksum_r, - clib_net_to_host_u16(tcp->tcp_checksum)); - } - } - } - } - } -} - -u32 get_my_svi_intf_ip_addr() { - return 0x01010101; -} diff --git a/plugins/plugins/vcgn/cnat_v4_functions.h b/plugins/plugins/vcgn/cnat_v4_functions.h deleted file mode 100644 index 2429e5e1..00000000 --- a/plugins/plugins/vcgn/cnat_v4_functions.h +++ /dev/null @@ -1,342 +0,0 @@ -/* - *------------------------------------------------------------------ - * cnat_v4_functions.h - * - * Copyright (c) 2007-2013 Cisco and/or its affiliates. - * 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 __CNAT_V4_FUNCTOINS__ -#define __CNAT_V4_FUNCTOINS__ - -#include "tcp_header_definitions.h" -#include "cnat_db.h" -#include "spp_ctx.h" - -#include "platform_common.h" - -/* - * Defines and structures to enable TCP packet logging - */ -#define TCP_LOGGING_DISABLE 0 -#define TCP_LOGGING_ENABLE 1 -#define TCP_LOGGING_PACKET_DUMP 2 -#define TCP_LOGGING_SUMMARY_DUMP 3 - -#define MAX_TCP_LOGGING_COUNT 1024 - -typedef struct tcp_logging_struct { - u32 seq_num; - u32 ack_num; - u32 old_ip; - u32 new_ip; - u16 old_port; - u16 new_port; - u16 old_ip_crc; - u16 new_ip_crc; - u16 old_tcp_crc; - u16 new_tcp_crc; -} tcp_logging_struct_t; - -void tcp_debug_logging_dump (void); -void tcp_debug_logging_enable_disable (u32 enable_flag); - -void -tcp_debug_logging ( - u32 seq_num, - u32 ack_num, - u32 old_ip, - u32 new_ip, - u16 old_port, - u16 new_port, - u16 old_ip_crc, - u16 new_ip_crc, - u16 old_tcp_crc, - u16 new_tcp_crc); - -#define JLI printf("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__); fflush(stdout); - -#define CNAT_ICMP_DEST_UNREACHABLE 100 -#define INCREMENT_NODE_COUNTER(c) \ - em->counters[node_counter_base_index + c] += 1; - -#define V4_TCP_UPDATE_SESSION_FLAG(db, tcp) \ -if ((tcp->flags & TCP_FLAG_ACK) && (tcp->flags & TCP_FLAG_SYN)) { \ - db->flags |= CNAT_DB_FLAG_TCP_ACTIVE; \ -} \ -if ((tcp->flags & TCP_FLAG_RST) || (tcp->flags & TCP_FLAG_FIN)) { \ - db->flags &= ~CNAT_DB_FLAG_TCP_ACTIVE; \ - db->flags |= CNAT_DB_FLAG_TCP_CLOSING; \ -} - -#define V4_TCP_UPDATE_SESSION_DB_FLAG(sdb, tcp) \ -if ((tcp->flags & TCP_FLAG_ACK) && (tcp->flags & TCP_FLAG_SYN)) { \ - sdb->flags |= CNAT_DB_FLAG_TCP_ACTIVE; \ -} \ -if ((tcp->flags & TCP_FLAG_RST) || (tcp->flags & TCP_FLAG_FIN)) { \ - sdb->flags &= ~CNAT_DB_FLAG_TCP_ACTIVE; \ - sdb->flags |= CNAT_DB_FLAG_TCP_CLOSING; \ -} - -/* - * Code to recalculate checksum after ACK/SEQ number changes - * This macro assumes, we have pointer to tcp structure - * referenced by the name "tcp" - */ -#define CNAT_UPDATE_TCP_SEQ_ACK_CHECKSUM(old_val32, new_val32) \ -{ \ - u16 old_val_lower, old_val_upper, old_tcp_cr; \ - u16 new_val_lower, new_val_upper, new_tcp_cr; \ - u32 sum32; \ - \ - old_val_lower = ~((u16) old_val32); \ - old_val_upper = ~((u16) (old_val32 >> 16)); \ - old_tcp_cr = ~net2host16(&tcp->tcp_checksum); \ - new_val_lower = (u16) new_val32; \ - new_val_upper = (u16) (new_val32 >> 16); \ - \ - sum32 = old_val_lower + old_val_upper + old_tcp_cr + \ - new_val_lower + new_val_upper; \ - \ - sum32 = (sum32 & 0xffff) + ((sum32 >> 16) & 0xffff); \ - sum32 = (sum32 & 0xffff) + ((sum32 >> 16) & 0xffff); \ - new_tcp_cr = ~((u16)sum32); \ - \ - tcp->tcp_checksum = host2net16(new_tcp_cr); \ -} - -/* - * newchecksum = ~(~oldchecksum + ~old + new) - * old/new for l3 checksum: ip address - */ -#define CNAT_UPDATE_L3_CHECKSUM_DECLARE \ -u16 old_l3_1r, old_l3_2r; \ -u16 old_l3_cr, new_l3_c; \ -u32 new32; - -#define CNAT_UPDATE_L3_CHECKSUM(old_l3_1, old_l3_2, old_l3_c, \ - new_l3_1, new_l3_2) \ -old_l3_1r = ~(old_l3_1); \ -old_l3_2r = ~(old_l3_2); \ -old_l3_cr = ~(old_l3_c); \ -new32 = old_l3_cr + old_l3_1r + old_l3_2r + new_l3_1 + new_l3_2; \ -new32 = (new32 & 0xffff) + ((new32 >> 16) & 0xffff); \ -new32 = (new32 & 0xffff) + ((new32 >> 16) & 0xffff); \ -new_l3_c = ~((u16)new32); - - -/* - * newchecksum = ~(~oldchecksum + ~old + new) - * old/new for l3 checksum: ip address - * old/new for l4 checksum: ip address and port - */ -#define CNAT_UPDATE_L3_L4_CHECKSUM_DECLARE \ -u16 old_l3_1r, old_l3_2r, old_l4r; \ -u16 old_l3_cr, old_l4_cr; \ -u16 new_l3_c, new_l4_c; \ -u32 sum32, new32; - -#define CNAT_UPDATE_L3_L4_CHECKSUM(old_l3_1, old_l3_2, old_l4, \ - old_l3_c, old_l4_c, \ - new_l3_1, new_l3_2, new_l4) \ -old_l3_1r = ~(old_l3_1); \ -old_l3_2r = ~(old_l3_2); \ -old_l3_cr = ~(old_l3_c); \ -sum32 = old_l3_1r + old_l3_2r + new_l3_1 + new_l3_2; \ -new32 = old_l3_cr + sum32; \ -new32 = (new32 & 0xffff) + ((new32 >> 16) & 0xffff); \ -new32 = (new32 & 0xffff) + ((new32 >> 16) & 0xffff); \ -new_l3_c = ~((u16)new32); \ -old_l4r = ~(old_l4); \ -old_l4_cr = ~(old_l4_c); \ -sum32 += old_l4r + new_l4; \ -new32 = old_l4_cr + sum32; \ -new32 = (new32 & 0xffff) + ((new32 >> 16) & 0xffff); \ -new32 = (new32 & 0xffff) + ((new32 >> 16) & 0xffff); \ -new_l4_c = ~((u16)new32); - -/* - * For ICMP checksums, we don't use the top IP header for checksum calculation - */ -#define CNAT_UPDATE_L3_ICMP_CHECKSUM(old_l3_1, old_l3_2, old_l4, \ - old_l3_c, old_l4_c, \ - new_l3_1, new_l3_2, new_l4) \ -old_l3_1r = ~(old_l3_1); \ -old_l3_2r = ~(old_l3_2); \ -old_l3_cr = ~(old_l3_c); \ -sum32 = old_l3_1r + old_l3_2r + new_l3_1 + new_l3_2; \ -new32 = old_l3_cr + sum32; \ -new32 = (new32 & 0xffff) + ((new32 >> 16) & 0xffff); \ -new32 = (new32 & 0xffff) + ((new32 >> 16) & 0xffff); \ -new_l3_c = ~((u16)new32); \ -old_l4r = ~(old_l4); \ -old_l4_cr = ~(old_l4_c); \ -sum32 = old_l4r + new_l4; \ -new32 = old_l4_cr + sum32; \ -new32 = (new32 & 0xffff) + ((new32 >> 16) & 0xffff); \ -new32 = (new32 & 0xffff) + ((new32 >> 16) & 0xffff); \ -new_l4_c = ~((u16)new32); - - -/* - * icmp error type message: - * newchecksum = ~(~oldchecksum + ~old + new) - * old/new for outlayer ip checksum: ip address - * old/new for outlayer icmp checksum: - * out-layer: ip address - * inner-layer: ip addr, port, l3 checksum, l4 checksum - */ -#define CNAT_UPDATE_ICMP_ERR_CHECKSUM_DECLARE \ -u16 old_ip_1r, old_ip_2r, old_ip_port_r, old_ip_cr, old_icmp_cr; \ -u16 new_icmp_c; \ -u32 sum32; - - -#define CNAT_UPDATE_ICMP_ERR_CHECKSUM(old_ip_1, old_ip_2, old_ip_port, old_ip_c, old_icmp_c, \ - new_ip_1, new_ip_2, new_ip_port, new_ip_c) \ -old_ip_1r = ~(old_ip_1); \ -old_ip_2r = ~(old_ip_2); \ -old_ip_port_r = ~(old_ip_port); \ -old_ip_cr = ~(old_ip_c); \ -old_icmp_cr = ~(old_icmp_c); \ -sum32 = old_ip_1r + old_ip_2r + new_ip_1 + new_ip_2 + \ - old_ip_port_r + new_ip_port + old_ip_cr + new_ip_c; \ -new32 = old_icmp_cr + sum32; \ -new32 = (new32 & 0xffff) + ((new32 >> 16) & 0xffff); \ -new32 = (new32 & 0xffff) + ((new32 >> 16) & 0xffff); \ -new_icmp_c = ~((u16)new32); \ - -/* - * Add the two 16 bit parts of the 32 bit field - * Repeat it one more time to take care of any overflow - * Complement the u16 value and store it in network format - */ -#define FILL_CHECKSUM(checksum_field, sum32) { \ - sum32 = (sum32 & 0xffff) + ((sum32>>16) & 0xffff); \ - sum32 = (sum32 & 0xffff) + ((sum32>>16) & 0xffff); \ - checksum_field = clib_host_to_net_u16(~((u16) sum32)); \ -} - -static inline void -cnat_v4_recalculate_tcp_checksum (ipv4_header *ip, - tcp_hdr_type *tcp, - u32 *ip_addr_ptr, - u16 *tcp_port_addr_ptr, - u32 new_ip, - u16 new_port) -{ - u32 old_ip_addr, old_ip32_r, new_ip32, sum32; - u16 old_port_r, old_ip_checksum_r, old_tcp_checksum_r; - - u16 *p16; - - p16 = (u16*) ip_addr_ptr; - - old_ip_addr = *ip_addr_ptr; - old_ip32_r = (((u16) ~clib_net_to_host_u16(*p16)) + - ((u16) ~clib_net_to_host_u16(*(p16+1)))); - - old_port_r = ~clib_net_to_host_u16(*tcp_port_addr_ptr); - - *ip_addr_ptr = clib_host_to_net_u32(new_ip); - - new_ip32 = (new_ip & 0xffff) + ((new_ip >> 16) & 0xffff); - - old_ip_checksum_r = ~clib_net_to_host_u16(ip->checksum); - - /* - * Recalculate the new IP checksum - */ - sum32 = old_ip32_r + new_ip32 + old_ip_checksum_r; - - FILL_CHECKSUM(ip->checksum, sum32); - - u16 frag_offset = - clib_net_to_host_u16((ip->frag_flags_offset)); - - if(PREDICT_FALSE(frag_offset & IP_FRAG_OFFSET_MASK)) { - return; /* No need to update TCP fields */ - } - - *tcp_port_addr_ptr = clib_host_to_net_u16(new_port); - old_tcp_checksum_r = ~clib_net_to_host_u16(tcp->tcp_checksum); - - /* - * Recalculate the new TCP checksum - */ - sum32 = old_ip32_r + new_ip32 + - old_port_r + new_port + old_tcp_checksum_r; - - FILL_CHECKSUM(tcp->tcp_checksum, sum32); - - if (PREDICT_FALSE(tcp_logging_enable_flag)) { - tcp_debug_logging( - clib_net_to_host_u32(tcp->seq_num), - clib_net_to_host_u32(tcp->ack_num), - clib_net_to_host_u32(old_ip_addr), - clib_net_to_host_u32(*ip_addr_ptr), - ~old_port_r, - clib_net_to_host_u16(*tcp_port_addr_ptr), - ~old_ip_checksum_r, - clib_net_to_host_u16(ip->checksum), - ~old_tcp_checksum_r, - clib_net_to_host_u16(tcp->tcp_checksum)); - } -} - - -extern void tcp_in2out_nat_mss_n_checksum (ipv4_header *ip, - tcp_hdr_type *tcp, - u32 ipv4_addr, - u16 port, - cnat_main_db_entry_t * db); - -void hex_dump(u8 * p, int len); - -u32 get_my_svi_intf_ip_addr(); - -/* - * in cnat_v4_icmp_gen.c, - * return 1 if icmp msg allow to generate - * for this user - */ - -u32 icmp_msg_gen_allowed (); - -cnat_icmp_msg_t v6_icmp_msg_gen_allowed(); - -int v4_crc_zero_udp_allowed(); -void ipv4_decr_ttl_n_calc_csum(ipv4_header *ipv4); -int icmpv4_generate_with_throttling (spp_ctx_t *ctx, ipv4_header *ipv4, - u16 rx_uidb_index); - -int icmpv6_generate_with_throttling (spp_ctx_t *ctx, ipv6_header_t *ipv4, - u16 rx_uidb_index); - -void icmp_error_generate_v6(spp_ctx_t *ctx, u8 icmp_type, - u8 icmp_code, u16 uidb_index); - -void calculate_window_scale(tcp_hdr_type *tcp_header, u8 *scale); - -void cnat_log_nat44_tcp_seq_mismatch( - cnat_main_db_entry_t *db, - cnat_vrfmap_t *vrfmap); -void print_icmp_pkt (ipv4_header *ip); -void print_udp_pkt (ipv4_header *ip); -void print_tcp_pkt (ipv4_header *ip); -void print_ipv6_pkt (ipv6_header_t *ip); - - -#endif - diff --git a/plugins/plugins/vcgn/cnat_v4_pptp_alg.h b/plugins/plugins/vcgn/cnat_v4_pptp_alg.h deleted file mode 100644 index 5a6d4243..00000000 --- a/plugins/plugins/vcgn/cnat_v4_pptp_alg.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - *------------------------------------------------------------------ - * cnat_v4_pptp_alg.h - * - * Copyright (c) 2009-2013 Cisco and/or its affiliates. - * 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 __CNAT_V4_PPTP_ALG_H__ -#define __CNAT_V4_PPTP_ALG_H__ - -/* Debug utils of PPTP */ -#define PPTP_DBG(debug, ...) \ - if(PREDICT_FALSE(cnat_pptp_debug_flag >= debug)) { \ - PLATFORM_DEBUG_PRINT("%s:%s:%d - ", \ - __FILE__, __FUNCTION__, __LINE__);\ - PLATFORM_DEBUG_PRINT(__VA_ARGS__);\ - PLATFORM_DEBUG_PRINT("\n"); \ - } - -#define PPTP_DUMP_PACKET(ip, len) pptp_hex_dump(ip, len) - - -#define PPTP_DISABLED 0 -#define PPTP_ENABLED 1 - -#define PPTP_GRE_TIMEOUT 60 /*sec */ - -#define TCP_PPTP_PORT 1723 - -#define PPTP_PAC 0 -#define PPTP_PNS 1 - -/* PPTP MSG TYPE */ - -#define PPTP_MSG_TYPE_CONTROL 1 -#define PPTP_MSG_TYPE_MGMT 2 - -/* PPTP control messages */ - -/* control connection mgmt */ -#define PPTP_START_CC_RQ 1 -#define PPTP_START_CC_RP 2 -#define PPTP_STOP_CC_RQ 3 -#define PPTP_STOP_CC_RP 4 -#define PPTP_ECHO_RQ 5 -#define PPTP_ECHO_RP 6 - -/* call mgmt */ -#define PPTP_OBOUND_CALL_RQ 7 -#define PPTP_OBOUND_CALL_RP 8 -#define PPTP_IBOUND_CALL_RQ 9 -#define PPTP_IBOUND_CALL_RP 10 -#define PPTP_IBOUND_CALL_CN 11 -#define PPTP_CALL_CLEAR_RQ 12 -#define PPTP_CALL_DISCON_NT 13 - -/* other */ - -#define PPTP_WAN_ERR_NT 14 -#define PPTP_SET_LINK_INF 15 - -#define PPTP_MIN_HDR_LEN 8 - -/* Byte offsets from start of TCP Data(PPTP header) */ - -#define PPTP_CTRL_MGMT_TYPE_OFFSET 0x02 -#define PPTP_CC_TYPE_OFFSET 0x08 -#define PPTP_HDR_CALL_ID_OFFSET 0x0c -#define PPTP_HDR_PEER_CALL_ID_OFFSET 0x0e - -#define PPTP_HDR_RESULT_CODE_OFFSET_STCCRP 0x0e -#define PPTP_HDR_RESULT_CODE_OFFSET 0x10 - - -/* Offset of control/mgmt msg types - from start of TCP header */ - -#define TCP_HEADER_SIZE(tcp) \ - ((tcp->hdr_len>>4) << 2) - - -#define PPTP_MSG_START_OFFSET(tcp) \ - ((u8*)tcp + TCP_HEADER_SIZE(tcp)) - - -#define PPTP_CC_MSG_TYPE_OFFSET(tcp) \ - (PPTP_MSG_START_OFFSET(tcp) + \ - PPTP_CC_TYPE_OFFSET ) - -#define PPTP_MGMT_MSG_TYPE_OFFSET(tcp) \ - ( PPTP_MSG_START_OFFSET(tcp) + \ - PPTP_CTRL_MGMT_TYPE_OFFSET ) - -#define PPTP_CALL_ID_OFFSET(tcp) \ - ( PPTP_MSG_START_OFFSET(tcp) + \ - PPTP_HDR_CALL_ID_OFFSET ) - -#define PPTP_PEER_CALL_ID_OFFSET(tcp) \ - ( PPTP_MSG_START_OFFSET(tcp) + \ - PPTP_HDR_PEER_CALL_ID_OFFSET ) - -#define PPTP_RESULT_CODE_OFFSET(tcp) \ - ( PPTP_MSG_START_OFFSET(tcp) + \ - PPTP_HDR_RESULT_CODE_OFFSET ) - -#define PPTP_RESULT_CODE_OFFSET_STCCRP(tcp) \ - ( PPTP_MSG_START_OFFSET(tcp) + \ - PPTP_HDR_RESULT_CODE_OFFSET_STCCRP) - -/* values */ -#define PPTP_CC_MSG_TYPE(tcp) \ - (u16*)PPTP_CC_MSG_TYPE_OFFSET(tcp) - -#define PPTP_MGMT_MSG_TYPE(tcp) \ - (u16*)PPTP_MGMT_MSG_TYPE_OFFSET(tcp) - -#define PPTP_CALL_ID(tcp) \ - (u16*)PPTP_CALL_ID_OFFSET(tcp) - -#define PPTP_PEER_CALL_ID(tcp) \ - (u16*)PPTP_PEER_CALL_ID_OFFSET(tcp) - -#define PPTP_RESULT_CODE(tcp) \ - *(u8*)PPTP_RESULT_CODE_OFFSET(tcp); - -#define PPTP_RESULT_CODE_STCCRP(tcp) \ - *(u8*)PPTP_RESULT_CODE_OFFSET_STCCRP(tcp); - - -/* other code */ -#define PPTP_CHAN_SUCCESS 1 - - -/* Data structures */ - -extern u32 cnat_pptp_debug_flag; - -#endif /* __CNAT_V4_PPTP_ALG_H__ */ diff --git a/plugins/plugins/vcgn/cnat_v4_tcp_in2out_stages.c b/plugins/plugins/vcgn/cnat_v4_tcp_in2out_stages.c deleted file mode 100644 index 220ced46..00000000 --- a/plugins/plugins/vcgn/cnat_v4_tcp_in2out_stages.c +++ /dev/null @@ -1,679 +0,0 @@ -/* - *--------------------------------------------------------------------------- - * cnat_v4_tcp_in2out_stages.c - cnat_v4_tcp_in2out node pipeline stage functions - * - * - * Copyright (c) 2008-2014 Cisco and/or its affiliates. - * 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 -#include -#include -#include - -#include "cnat_db.h" -/* #include */ -#include "ipv4_packet.h" -#include "tcp_header_definitions.h" -#include "cnat_config.h" -#include "cnat_global.h" -#include "cnat_v4_functions.h" -#include "cnat_v4_ftp_alg.h" -#include "cnat_v4_pptp_alg.h" - -#define foreach_cnat_ipv4_tcp_inside_input_error \ -_(TCP_NAT_IN, "packets received") \ -_(TCP_NAT, "packets NATed") \ -_(TCP_EXCEPTION, "packets to exception") \ -_(TCP_TTL_GEN, "Generated TTL Expiry ICMP packet") \ -_(TCP_TTL_DROP, "Could not generate TTL Expiry ICMP packet") \ -_(TCP_SESSION_DROP, "Could not generate session") \ -_(TCP_FRAG_DROP, "Non-first Fragment received") - -typedef enum { -#define _(sym,str) sym, - foreach_cnat_ipv4_tcp_inside_input_error -#undef _ - CNAT_IPV4_TCP_INSIDE_INPUT_N_ERROR, -} cnat_ipv4_tcp_inside_input_t; - -static char * cnat_ipv4_tcp_inside_input_error_strings[] = { -#define _(sym,string) string, - foreach_cnat_ipv4_tcp_inside_input_error -#undef _ - - - -typedef struct cnat_v4_tcp_in2out_pipeline_data_ { - spp_node_main_vector_t *nmv; - /* Add additional pipeline stage data here... */ - u32 bucket; - u16 src_port; /* Added for handling fragments */ - u16 dst_port; /* Added for handling fragments */ -} cnat_v4_tcp_in2out_pipeline_data_t; - -static cnat_v4_tcp_in2out_pipeline_data_t pctx_data[SPP_MAXDISPATCH]; - -#define EXTRA_PIPELINE_ARGS_PROTO , cnat_v4_tcp_in2out_pipeline_data_t *pctx -#define EXTRA_PIPELINE_ARGS , pctx - -ALWAYS_INLINE( -static inline void -stage0(spp_ctx_t **ctxs, int index, spp_node_t *np, - u8 *disp_used EXTRA_PIPELINE_ARGS_PROTO)) -{ - spp_ctx_t *ctx = ctxs[index]; - /* - * Prefetch the context header. This is almost always - * the right thing to do - */ - SPP_PREFETCH_CTX(ctx); -} - -ALWAYS_INLINE( -static inline void -stage1(spp_ctx_t **ctxs, int index, spp_node_t *np, - u8 *disp_used EXTRA_PIPELINE_ARGS_PROTO)) -{ - spp_ctx_t *ctx = ctxs[index]; - /* got ctx, prefetch packet data separately */ - SPP_PREFETCH_CTX_DATA(ctx, 1*CACHE_DATA_QUANTUM); -} - -ALWAYS_INLINE( -static inline void -stage2(spp_ctx_t **ctxs, int index, spp_node_t *np, - u8 *disp_used EXTRA_PIPELINE_ARGS_PROTO)) -{ - spp_ctx_t *ctx = ctxs[index]; - u64 a, b, c; - u32 bucket; - cnat_feature_data_t *fd = (cnat_feature_data_t *)ctx->feature_data; - ipv4_header *ip; - tcp_hdr_type * tcp; - u8 *prefetch_target; - - INCREMENT_NODE_COUNTER(np, TCP_NAT_IN); - - /* extract the key from ctx and save it to feature_data */ - - ip = (ipv4_header *)(ctx->current_header); - ctx->application_start = (ip->version_hdr_len_words & 0xf) << 2; - tcp = (tcp_hdr_type*) ((u8 *)ip + ctx->application_start); - - PLATFORM_CNAT_SET_RX_VRF(ctx,fd->dbl.k.k.vrf, CNAT_TCP, 1); - fd->dbl.k.k.ipv4 = spp_net_to_host_byte_order_32(&ip->src_addr); - - if(PREDICT_FALSE(ctx->ru.rx.frag)) { - /* Must have routed through cnat_v4_frag_in2out node - * Since feature data of the ctx is being used for other - * purposes here, copy them to extra stage argument - */ - u16 *feature_data_ports = (u16 *)&ctx->feature_data[2]; - pctx[index].src_port = fd->dbl.k.k.port = *feature_data_ports; - feature_data_ports++; - pctx[index].dst_port = *feature_data_ports; - } else { - fd->dbl.k.k.port = spp_net_to_host_byte_order_16(&tcp->src_port); - pctx[index].dst_port = - spp_net_to_host_byte_order_16(&tcp->dest_port); - } - -#if 0 - /* extra info for evil mode, or default value for dst_ipv4 field in good mode */ - fd->dbl.dst_ipv4 = address_dependent_filtering ? - spp_net_to_host_byte_order_32(&ip->dest_addr) : 0; -#endif - - CNAT_V4_GET_HASH(fd->dbl.k.key64, - bucket, CNAT_MAIN_HASH_MASK) - - prefetch_target = (u8 *)(&cnat_in2out_hash[bucket]); - pctx[index].bucket = bucket; - - /* Prefetch the hash bucket */ - SPP_PREFETCH(prefetch_target, 0, LOAD); - -} - -ALWAYS_INLINE( -static inline void -stage3(spp_ctx_t **ctxs, int index, spp_node_t *np, - u8 *disp_used EXTRA_PIPELINE_ARGS_PROTO)) -{ - u32 db_index; - u32 bucket; - uword prefetch_target0, prefetch_target1; - - bucket = pctx[index].bucket; - - /* read the hash bucket */ - db_index = pctx[index].bucket = cnat_in2out_hash[bucket].next; - if (PREDICT_TRUE(db_index != EMPTY)) { - - /* - * Prefetch database keys. We save space by not cache-line - * aligning the DB entries. We don't want to waste LSU - * bandwidth prefetching stuff we won't need. - */ - - prefetch_target0 = (uword)(cnat_main_db + db_index); - - SPP_PREFETCH(prefetch_target0, 0, LOAD); - - /* Just beyond DB key #2 */ - - prefetch_target1 = prefetch_target0 + - STRUCT_OFFSET_OF(cnat_main_db_entry_t, user_ports); - - /* If the targets are in different lines, do the second prefetch */ - - if (PREDICT_FALSE((prefetch_target0 & ~(SPP_CACHE_LINE_BYTES-1)) != - (prefetch_target1 & ~(SPP_CACHE_LINE_BYTES-1)))) { - - SPP_PREFETCH(prefetch_target1, 0, LOAD); - - } - } -} - -static inline void -stage4(spp_ctx_t **ctxs, int index, spp_node_t *np, - u8 *disp_used EXTRA_PIPELINE_ARGS_PROTO) -{ - spp_ctx_t *ctx = ctxs[index]; - u32 db_index = pctx[index].bucket; - cnat_main_db_entry_t *db; - cnat_feature_data_t *fd; - - /* - * Note: if the search already failed (empty bucket), - * the answer is already in the pipeline context structure - */ - if (PREDICT_FALSE(db_index == EMPTY)) { - return; - } - - fd = (cnat_feature_data_t *)ctx->feature_data; - - /* - * Note: hash collisions suck. We can't easily prefetch around them. - * The first trip around the track will be fast. After that, maybe - * not so much... - */ - do { - - db = cnat_main_db + db_index; - if (PREDICT_TRUE(db->in2out_key.key64 == fd->dbl.k.key64)) - break; - db_index = db->in2out_hash.next; - - } while (db_index != EMPTY); - - /* even in evil mode, for in2out, we nat all packets regardless mode and dst_ip */ - - /* Stick the answer back into the pipeline context structure */ - pctx[index].bucket = db_index; -} - -ALWAYS_INLINE( -static inline void -stage5(spp_ctx_t **ctxs, int index, spp_node_t *np, - u8 *disp_used EXTRA_PIPELINE_ARGS_PROTO)) -{ - spp_ctx_t *ctx = ctxs[index]; - u32 db_index = pctx[index].bucket; - cnat_feature_data_t *fd = (cnat_feature_data_t *)ctx->feature_data; - int disposition; - cnat_main_db_entry_t *db; - /* Below two pointers are just to keep the cnat_ftp_alg call happy*/ - dslite_table_entry_t *dslite_entry_ptr = NULL; - ipv6_header_t *ipv6_hdr = NULL; - tcp_hdr_type *tcp; - ipv4_header *ip; - i8 delta; - u32 seq, seq1; - u32 window; - u8 scale; - int rc; - - ip = (ipv4_header *) ctx->current_header; - - if (PLATFORM_HANDLE_TTL_DECREMENT) { - if (PREDICT_FALSE(ip->ttl <= 1)) { - /* Try to generate ICMP error msg, as TTL is <= 1 */ - - if (icmpv4_generate_with_throttling - (ctx, ip, ctx->ru.rx.uidb_index)) { - /* Generated ICMP */ - disposition = CNAT_REWRITE_OUTPUT; - INCREMENT_NODE_COUNTER(np, TCP_TTL_GEN); - } else { - /* Could not generated ICMP - drop the packet */ - disposition = CNAT_DROP; - INCREMENT_NODE_COUNTER(np, TCP_TTL_DROP); - } - goto drop_pkt; - } - } - - if (PREDICT_FALSE(db_index == EMPTY)) { - if(PREDICT_FALSE(ctx->ru.rx.frag)) { - /* Must have routed through cnat_v4_frag_in2out node */ - u16 frag_offset = - spp_net_to_host_byte_order_16(&(ip->frag_flags_offset)); - if(PREDICT_FALSE(frag_offset & IP_FRAG_OFFSET_MASK)) { - INCREMENT_NODE_COUNTER(np, TCP_FRAG_DROP); - disposition = CNAT_DROP; - goto drop_pkt; - } else { - INCREMENT_NODE_COUNTER(np, TCP_EXCEPTION); - disposition = CNAT_V4_TCP_IE; - } - } else { - INCREMENT_NODE_COUNTER(np, TCP_EXCEPTION); - disposition = CNAT_V4_TCP_IE; - } - } else { - cnat_key_t dest_info; - cnat_session_entry_t *session_db = NULL; - db = cnat_main_db + db_index; - /* Handle destination sessions */ - tcp = (tcp_hdr_type*) ((u8*)ip + ctx->application_start); - dest_info.k.port = pctx[index].dst_port; - dest_info.k.ipv4 = spp_net_to_host_byte_order_32(&(ip->dest_addr)); - - if(PREDICT_TRUE(!PLATFORM_DBL_SUPPORT)) { - - /* No DBL support, so just update the destn and proceed */ - db->dst_ipv4 = dest_info.k.ipv4; - db->dst_port = dest_info.k.port; - goto update_pkt; - } - - if(PREDICT_FALSE(db->dst_ipv4 != dest_info.k.ipv4 || - db->dst_port != dest_info.k.port)) { - if(PREDICT_TRUE(db->nsessions == 0)) { - /* Should be a static entry - * Note this session as the first session and log - */ - cnat_add_dest_n_log(db, &dest_info); - } else if(PREDICT_FALSE(db->nsessions == 1)) { - /* Destn is not same as in main db. Multiple session - * scenario - */ - dest_info.k.vrf = db->in2out_key.k.vrf; - session_db = cnat_handle_1to2_session(db, &dest_info); - if(PREDICT_FALSE(session_db == NULL)) { - disposition = CNAT_DROP; - INCREMENT_NODE_COUNTER(np, TCP_SESSION_DROP); - goto drop_pkt; - } - } else { /* There are already multiple destinations */ - dest_info.k.vrf = db->in2out_key.k.vrf; - /* If session already exists, - * cnat_create_session_db_entry will return the existing db - * else create a new db - * If could not create, return NULL - */ - session_db = cnat_create_session_db_entry(&dest_info, - db, TRUE); - if(PREDICT_FALSE(session_db == NULL)) { - disposition = CNAT_DROP; - INCREMENT_NODE_COUNTER(np, TCP_SESSION_DROP); - goto drop_pkt; - } - } - if(PREDICT_TRUE(session_db)) { - /* Have to repeat the window size check for new destinations */ - window = (u32)spp_net_to_host_byte_order_16( - &tcp->window_size); - window = window << session_db->scale; - if(PREDICT_TRUE(!session_db->window)) { - calculate_window_scale(tcp, &scale); - session_db->scale = scale; - session_db->window = window; - } else if (PREDICT_FALSE(session_db->window < - window)) { - /* Update the db entry with window option from packet */ - session_db->window = window; - } else { - /* Do nothing */ - } - session_db->tcp_seq_num = spp_net_to_host_byte_order_32( - &tcp->seq_num); - session_db->ack_no = spp_net_to_host_byte_order_32( - &tcp->ack_num); - if (PREDICT_FALSE(global_debug_flag && CNAT_DEBUG_GLOBAL_ALL)) { - PLATFORM_DEBUG_PRINT("\n In2out SDB stages seq no = %u," - " ack no = %u, window = %u\n", - session_db->tcp_seq_num, - session_db->ack_no, - session_db->window); - } - } - } else { - //Update the seq no and ack no for subsequent communication - //after connection establishment - //No need to update window here. Window is already updated - //during connection establishment - window = (u32)spp_net_to_host_byte_order_16( - &tcp->window_size); - window = window << db->scale; - if(PREDICT_FALSE(!ALG_ENABLED_DB(db))) { - //This check is done since proto_data is part of union in main - //db entry - db->proto_data.tcp_seq_chk.seq_no = - spp_net_to_host_byte_order_32( - &tcp->seq_num); - db->proto_data.tcp_seq_chk.ack_no = - spp_net_to_host_byte_order_32( - &tcp->ack_num); - } - if (PREDICT_FALSE(db->diff_window < window)) { - /* Update the db entry with window option from packet */ - db->diff_window = window; - } - if (PREDICT_FALSE(global_debug_flag && CNAT_DEBUG_GLOBAL_ALL)) { - PLATFORM_DEBUG_PRINT("\n In2out MainDB seq no = %u," - "\n ack no = %u\n", - db->proto_data.tcp_seq_chk.seq_no, - db->proto_data.tcp_seq_chk.ack_no); - PLATFORM_DEBUG_PRINT("\n In2out MAINDB window = %u\n", - db->diff_window); - } - } -update_pkt: - - INCREMENT_NODE_COUNTER(np, TCP_NAT); - - disposition = CNAT_REWRITE_OUTPUT; - - /* NAT the packet and update checksum (increamental) */ - - /* If it is a non-first fragment, we need not worry about - * ALGs as the packet does not have TCP header.. - * However, under a very race scenario when this non-first - * fragment is containing an FTP PORT command OR RTSP command - * we cannot handle that case.. in that case the ALG will fail - * Do not want to add a lot of complexity to handle one in million - * of such ALG case - */ - u16 frag_offset = - spp_net_to_host_byte_order_16(&(ip->frag_flags_offset)); - - if(PREDICT_FALSE(frag_offset & IP_FRAG_OFFSET_MASK)) { - /* Non first fragment.. no TCP header */ - FTP_ALG_DEBUG_PRINTF("Non first frag.. cannot handle ALG"); - goto handle_ttl_n_checksum; - } - - FTP_ALG_DEBUG_PRINTF("src port 0x%x, dst_port 0x%x", - spp_net_to_host_byte_order_16(&tcp->src_port), - spp_net_to_host_byte_order_16(&tcp->dest_port)) - - /* handle FTP ALG */ - if (PREDICT_FALSE(ftp_alg_enabled && - (spp_net_to_host_byte_order_16(&tcp->src_port) == 21 || - spp_net_to_host_byte_order_16(&tcp->dest_port) == 21))) { - - if(PREDICT_FALSE((db->flags & CNAT_DB_FLAG_PPTP_TUNNEL_ACTIVE) || - (db->flags & CNAT_DB_FLAG_PPTP_TUNNEL_INIT))) - { - /* FTP on a PPTP Control session? Ignore FTP */ - goto handle_ttl_n_checksum; - } - - if (PREDICT_FALSE(tcp->flags & (TCP_FLAG_SYN | TCP_FLAG_RST | - TCP_FLAG_FIN))) { - - FTP_ALG_DEBUG_PRINTF("SYN Case setting delta = 0") - - /* reset the delta */ - if(PREDICT_FALSE(session_db != NULL)) { - session_db->alg.delta = 0; - } else { - db->alg.delta = 0; - } - - } else { - - /* need to adjust seq # for in2out pkt if delta is not 0 */ - if (PREDICT_TRUE((session_db && (session_db->alg.delta != 0)) - || ((!session_db) && (db->alg.delta != 0)))) { - seq = net2host32(&tcp->seq_num); - - FTP_ALG_DEBUG_PRINTF("Orig Seq Num 0x%x", seq) - /* - * for ftp packets, due to PORT command translation, - * we may have cases that a packet/payload len gets - * changed for tcp, we need to adjust the packet's - * sequence numbers to match the changes. The delta - * of orig pkt len and new len is in alg_dlt[1] together - * with the sequence number that cuased the delta. When - * there are multiple len changes, we keep theprevious - * delta in alg_dlt[0] for case like pkt retransmission. - * So depends on packet seq number, we decide to use - * either latest delta or previous delta ([0]) - * We won't be here if both delta values are 0 - */ - if(PREDICT_FALSE(session_db != NULL)) { - seq1 = seq > session_db->tcp_seq_num ? - (seq + session_db->alg.alg_dlt[1]): - (seq + session_db->alg.alg_dlt[0]); - } else { - seq1 = seq > db->proto_data.seq_pcp.tcp_seq_num ? - (seq + db->alg.alg_dlt[1]): - (seq + db->alg.alg_dlt[0]); - } - - FTP_ALG_DEBUG_PRINTF("Old_seq_num 0x%x New Seq Num 0x%x", - seq, seq1) - - if (PREDICT_TRUE(seq1 != seq)) { - - tcp->seq_num = host2net32(seq1); - - FTP_ALG_DEBUG_PRINTF("Old TCP Checksum 0x%x", - net2host16(&tcp->tcp_checksum)) - - /* - * fix checksum incremental for seq # changes - * newchecksum = ~(~oldchecksum + ~old + new) - */ - CNAT_UPDATE_TCP_SEQ_ACK_CHECKSUM(seq, seq1) - } /* There is a diff in seq */ - - } /* ALG Delta is non zero */ - - rc = cnat_ftp_alg((u8*) ip, &delta, db, dslite_entry_ptr, ipv6_hdr); - - FTP_ALG_DEBUG_PRINTF("cnat_ftp_alg rc 0x%x", rc) - - /*if located PORT cmd, packet being updated, take the delta and seq # */ - if (PREDICT_FALSE(rc)) { - - /* set alg flag for this ftp control connection */ - if(PREDICT_FALSE(session_db != NULL)) { - session_db->flags |= CNAT_DB_FLAG_ALG_CTRL_FLOW; - } else { - db->flags |= CNAT_DB_FLAG_ALG_CTRL_FLOW; - } - - /* - * rc != 0 indicates this packet has triggered a new pkt len delta - * we need to update db entry's seq# with seq# of this packet. - * - * Move alg_dlt[1] to [0], (current delta -> previous delta) - * then apply latest delta to alg_dlt[1] (keep [1] as latest delta) - */ - if(PREDICT_FALSE(session_db != NULL)) { - session_db->tcp_seq_num = net2host32(&tcp->seq_num); - session_db->alg.alg_dlt[0] = session_db->alg.alg_dlt[1]; - - /* accumulate the delta ! */ - session_db->alg.alg_dlt[1] += delta; - FTP_ALG_DEBUG_PRINTF( - "cnat_ftp_alg seq_num 0x%x, dlt0 0x%x, dlt1 0x%x", - session_db->tcp_seq_num, - session_db->alg.alg_dlt[0], - session_db->alg.alg_dlt[1]) - - } else { - db->proto_data.seq_pcp.tcp_seq_num = net2host32(&tcp->seq_num); - db->alg.alg_dlt[0] = db->alg.alg_dlt[1]; - - /* accumulate the delta ! */ - db->alg.alg_dlt[1] += delta; - - FTP_ALG_DEBUG_PRINTF( - "cnat_ftp_alg seq_num 0x%x, dlt0 0x%x, dlt1 0x%x", - db->proto_data.seq_pcp.tcp_seq_num, - db->alg.alg_dlt[0], - db->alg.alg_dlt[1]) - } - ctx->current_length += delta; - }/* cnat_ftp_alg returned non zero */ - } /* It is not a SYN, RST or FIN */ - } else if (PREDICT_FALSE(rtsp_alg_port_num && - ((spp_net_to_host_byte_order_16(&tcp->dest_port) == rtsp_alg_port_num) || - (spp_net_to_host_byte_order_16(&tcp->src_port) == rtsp_alg_port_num))) ) { - - if (PREDICT_FALSE(tcp->flags & (TCP_FLAG_SYN | TCP_FLAG_RST | - TCP_FLAG_FIN))) { - - FTP_ALG_DEBUG_PRINTF("SYN Case setting delta = 0") - - /* reset the delta */ - if(PREDICT_FALSE(session_db != NULL)) { - session_db->alg.delta = 0; - } else { - db->alg.delta = 0; - } - - } else { -#define RTSP_ALG_DELTA_MASK 0xFF - /* need to adjust seq # for in2out pkt if delta is not 0 */ - if (PREDICT_FALSE((session_db && - (session_db->alg.delta & RTSP_ALG_DELTA_MASK) != 0) || - ((!session_db) && - (db->alg.delta & RTSP_ALG_DELTA_MASK) != 0))) { - seq = net2host32(&tcp->seq_num); - - if(PREDICT_FALSE(session_db != NULL)) { - seq1 = seq > session_db->tcp_seq_num ? - (seq + db->alg.alg_dlt[1]): - (seq + db->alg.alg_dlt[0]); - } else { - seq1 = seq > db->proto_data.seq_pcp.tcp_seq_num ? - (seq + db->alg.alg_dlt[1]): - (seq + db->alg.alg_dlt[0]); - } - - FTP_ALG_DEBUG_PRINTF("Old_seq_num 0x%x New Seq Num 0x%x", - seq, seq1) - - if (PREDICT_TRUE(seq1 != seq)) { - - tcp->seq_num = host2net32(seq1); - - FTP_ALG_DEBUG_PRINTF("Old TCP Checksum 0x%x", - net2host16(&tcp->tcp_checksum)) - - /* - * fix checksum incremental for seq # changes - * newchecksum = ~(~oldchecksum + ~old + new) - */ - CNAT_UPDATE_TCP_SEQ_ACK_CHECKSUM(seq, seq1) - } - - } - } - if ((session_db && (!session_db->alg.il)) || - ((!session_db) && (!db->alg.il))) { - cnat_rtsp_alg((u8*) ip, - &delta, - db, - ctx->current_length, - NULL, - NULL); - } - } -handle_ttl_n_checksum: - if (PLATFORM_HANDLE_TTL_DECREMENT) { - /* - * Decrement TTL and update IPv4 checksum - */ - ipv4_decr_ttl_n_calc_csum(ip); - } - - tcp_in2out_nat_mss_n_checksum(ip, - tcp, - db->out2in_key.k.ipv4, - db->out2in_key.k.port, - db); -/* CNAT_PPTP_ALG_SUPPORT */ - /* code to handle pptp control msgs */ - if(PREDICT_FALSE( - (spp_net_to_host_byte_order_16(&tcp->dest_port) == - TCP_PPTP_PORT))) { - - u32 ret; - - PPTP_DBG(3, "PPTP mgmt/ctrl msg recieved"); - - ret = cnat_handle_pptp_msg(ctx, db , tcp, PPTP_PNS ); - - if( PREDICT_FALSE( ret != CNAT_SUCCESS) ) { - PPTP_DBG(3, "PPTP mgmt/ctrl msg drop"); - disposition = CNAT_DROP; - PPTP_INCR(ctrl_msg_drops); - goto drop_pkt; - } - } - -/* CNAT_PPTP_ALG_SUPPORT */ - - /* update transaltion counters */ - db->in2out_pkts++; - - in2out_forwarding_count++; - - PLATFORM_CNAT_SET_TX_VRF(ctx,db->out2in_key.k.vrf); - - /* update the timer for good mode, or evil mode dst_ip match */ - -// if (!address_dependent_filtering || fd->dbl.dst_ipv4 == db->dst_ipv4) { - if(PREDICT_FALSE(session_db != NULL)) { - V4_TCP_UPDATE_SESSION_DB_FLAG(session_db, tcp); - CNAT_DB_TIMEOUT_RST(session_db); - } else { - V4_TCP_UPDATE_SESSION_FLAG(db, tcp); - CNAT_DB_TIMEOUT_RST(db); - } - -// } - - } - - /* Pick up the answer and put it into the context */ - fd->dbl.db_index = db_index; - -drop_pkt: - - DISP_PUSH_CTX(np, ctx, disposition, disp_used, last_disposition, last_contexts_ptr, last_nused_ptr); - -} - diff --git a/plugins/plugins/vcgn/cnat_va_db.c b/plugins/plugins/vcgn/cnat_va_db.c deleted file mode 100644 index 7423bdf2..00000000 --- a/plugins/plugins/vcgn/cnat_va_db.c +++ /dev/null @@ -1,286 +0,0 @@ -/* - *------------------------------------------------------------------ - * cnat_va_db.c - virtual assembly database - * - * Copyright (c) 2009, 2013 Cisco and/or its affiliates. - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -va_bucket_t va_bucket[VA_BUCKETS]; - -void va_bucket_init () { - - u32 i; - - /* - * set the pointer in each bucket - * points to nowhere - */ - for (i=0; i [%d, %d]\n", - bucket_index, entry_p->src_port, - entry_p->dst_port, key->e.src_port, key->e.dst_port) - - /* found match entry, update it */ - entry_p->src_port = key->e.src_port; - entry_p->dst_port = key->e.dst_port; - - FRAG_DEBUG_PRINTF3("VA_ADD_NEW: Existing bucket %d, counter %d\n", - bucket_index, - va_bucket[bucket_index].new_entry_counter) - - } else { - - /* no match, add a new one */ - head = va_bucket[bucket_index].head_entry; - next = va_bucket[bucket_index].next_available_entry; - - FRAG_DEBUG_PRINTF5( - "\nVA_ADD_NEW: Filling bucket %d, index %d with key 0x%llx %x\n", - bucket_index, next, key->k.key64, key->k.key32) - - va_bucket[bucket_index].va_entry[next] = key->e; - - /* increase next pointer */ - va_bucket[bucket_index].next_available_entry = (next+1) & VA_BUCKET_MASK; - - if (PREDICT_FALSE(head == va_bucket[bucket_index].next_available_entry)) { - /* adjust head circular pointer */ - va_bucket[bucket_index].head_entry = (head+1) & VA_BUCKET_MASK; - } - - va_bucket[bucket_index].new_entry_counter++; - - FRAG_DEBUG_PRINTF4( - "VA_ADD_NEW: NEW bucket %d, entry %d counter %d\n", - bucket_index, next, va_bucket[bucket_index].new_entry_counter) - } -} - - -/* - * use the key, - * return pointer to the entry if found, - * NULL if not - */ - -inline -va_entry_t * va_db_lookup (u32 bucket_index, va_lookup_key * key) -{ - - u32 index, next; - va_entry_t * entry_p; - va_bucket_t * bucket; - - bucket = &va_bucket[bucket_index]; - index = bucket->head_entry; - next = bucket->next_available_entry; - entry_p = NULL; - - FRAG_DEBUG_PRINTF4( - "\nVA_DB_LOOKUP: bucket index %d head %d next %d\n", - bucket_index, index, next) - - /* loop through the entries in the bucket */ - while( index != next) { - - if(PREDICT_TRUE(memcmp(&bucket->va_entry[index], key, VA_KEY_SIZE)==0)) { - - entry_p = &bucket->va_entry[index]; - /*In add frag entry function we are again assigning key's src - port to entry_p's src port. So when a main DB entry is deleted/ - timed out, and again another entry is created for the same - src ip and src port pair, the frag's entry_p will have the - previous port info stored and not updated. Hence the below - line is not required*/ - - /* *(u32*)&key->e.src_port = *(u32*)&entry_p->src_port; */ - /* do two ports as u32 :) */ - - break; - } - - index = (index +1) & VA_BUCKET_MASK; - - } - -#ifdef FRAG_DEBUG - if (PREDICT_TRUE(entry_p)) { - FRAG_DEBUG_PRINTF3("VA_DB_LOOKUP: bucket index %d entry index %d\n", - bucket_index, index) - FRAG_DEBUG_PRINTF5("VA_DB_LOOKUP: SRC-->DST [0x%x, %d] [0x%x, %d]\n", - entry_p->src_ip, entry_p->src_port, - entry_p->dst_ip, entry_p->dst_port) - FRAG_DEBUG_PRINTF3("[vrf 0x%x, id 0x%x]\n", - entry_p->vrf, entry_p->ip_id) - } else { - FRAG_DEBUG_PRINTF1("\nNULL ENTRY\n") - } -#endif - - return entry_p; - -} - -inline -int va_db_delete_entry (u32 bucket_index, va_lookup_key * key) -{ - - u32 index, next; - int entry_found = 0; - va_bucket_t * bucket; - - bucket = &va_bucket[bucket_index]; - index = bucket->head_entry; - next = bucket->next_available_entry; - - FRAG_DEBUG_PRINTF4( - "\nVA_DB_DELETE_ENTRY: bucket index %d head %d next %d\n", - bucket_index, index, next); - - /* loop through the entries in the bucket */ - while( index != next) { - if(PREDICT_TRUE(memcmp(&bucket->va_entry[index], key, - VA_KEY_SIZE)==0)) { - /* Clear the entry */ - FRAG_DEBUG_PRINTF1("Entry found in delete API"); - memset(&bucket->va_entry[index], 0, sizeof(va_entry_t)); - entry_found = 1; - break; - } - index = (index +1) & VA_BUCKET_MASK; - } - return entry_found; -} - - - -void cnat_va_bucket_used (int argc, unsigned long * argv) -{ - - u32 i, sum = 0;; - - for(i=0;i 0)) sum ++; - } - - PLATFORM_DEBUG_PRINT("buckets in use: %d\n", sum); - - sum = 0; - for(i=0; i= VA_BUCKETS)) { - PLATFORM_DEBUG_PRINT("invalid bucket index %d\n", index); - return; - } - - PLATFORM_DEBUG_PRINT("\n====== Bucket %d ======\n", index); - - PLATFORM_DEBUG_PRINT("bucket head index %d\n", va_bucket[index].head_entry); - - PLATFORM_DEBUG_PRINT("bucket next index %d\n", va_bucket[index].next_available_entry); - - PLATFORM_DEBUG_PRINT(" source IP dest IP VRF ip-id srcP dstP\n"); - - for(i=0;i - -#define FRAG_DEBUG 1 - -/* virtual assemble hash database size ~ 16B x 64K = 1MB */ - -#define VA_TOTAL_ENTRIES (64*1024) -#define VA_ENTRY_PER_BUCKET (8) /* make sure size is power of 2 for circular FIFO */ -#define VA_BUCKET_MASK (VA_ENTRY_PER_BUCKET -1) -#define VA_BUCKETS (VA_TOTAL_ENTRIES / VA_ENTRY_PER_BUCKET) -#define VA_KEY_SIZE 12 - -typedef struct _va_entry { - /* key: top 12 bytes */ - u32 src_ip; - u32 dst_ip; - u16 vrf; /* overloaded with protocol info with top two bits */ - u16 ip_id; - - /* values */ - u16 src_port; - u16 dst_port; -} va_entry_t; - -typedef struct _va_keys { - u64 key64; /* src & dst IP */ - u32 key32; /* vrf, protocol and ip_id */ -} va_keys; - -typedef union { - va_entry_t e; - va_keys k; -} va_lookup_key; - -typedef struct _va_bucket_t { - u32 head_entry; - u32 next_available_entry; /* ~0 for empty bucket */ - u32 new_entry_counter; /* for debug purpose */ - va_entry_t va_entry[VA_ENTRY_PER_BUCKET]; -} va_bucket_t; - -extern va_bucket_t va_bucket[]; /* hash table in cnat_va_db.c */ - -void va_bucket_init (); - -inline void va_db_add_new_entry (u32 bucket_index, va_lookup_key * ); -inline int va_db_delete_entry (u32 bucket_index, va_lookup_key * ); -inline va_entry_t * va_db_lookup (u32 bucket_index, va_lookup_key * key); - -#ifdef FRAG_DEBUG - -#define FRAG_DEBUG_PRINTF1(a) \ - if (frag_debug_flag) { \ - PLATFORM_DEBUG_PRINT(a); \ - } - -#define FRAG_DEBUG_PRINTF2(a, b) \ - if (frag_debug_flag) { \ - PLATFORM_DEBUG_PRINT(a, b); \ - } - -#define FRAG_DEBUG_PRINTF3(a, b, c) \ - if (frag_debug_flag) { \ - PLATFORM_DEBUG_PRINT(a, b, c); \ - } - -#define FRAG_DEBUG_PRINTF4(a, b, c, d) \ - if (frag_debug_flag) { \ - PLATFORM_DEBUG_PRINT(a, b, c, d); \ - } - -#define FRAG_DEBUG_PRINTF5(a, b, c, d, e) \ - if (frag_debug_flag) { \ - PLATFORM_DEBUG_PRINT(a, b, c, d, e); \ - } - -#define FRAG_DEBUG_PRINTF6(a, b, c, d, e, f) \ - if (frag_debug_flag) { \ - PLATFORM_DEBUG_PRINT(a, b, c, d, e, f); \ - } -#else - -#define FRAG_DEBUG_PRINTF1(a) - -#define FRAG_DEBUG_PRINTF2(a, b) - -#define FRAG_DEBUG_PRINTF3(a, b, c) - -#define FRAG_DEBUG_PRINTF4(a, b, c, d) - -#define FRAG_DEBUG_PRINTF5(a, b, c, d, e) - -#define FRAG_DEBUG_PRINTF6(a, b, c, d, e, f) - -#endif - -#endif /* __CNAT_VA_DB_H__ */ - - diff --git a/plugins/plugins/vcgn/dslite_db.h b/plugins/plugins/vcgn/dslite_db.h deleted file mode 100644 index 2269b98c..00000000 --- a/plugins/plugins/vcgn/dslite_db.h +++ /dev/null @@ -1,170 +0,0 @@ -/* - *------------------------------------------------------------------ - * dslite_db.h - Stateful DSLITE translation database definitions - * - * Copyright (c) 2010-2013 Cisco and/or its affiliates. - * 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 __DSLITE_DB_H__ -#define __DSLITE_DB_H__ - -#include "cnat_cli.h" -#include "index_list.h" -#include "cnat_ports.h" -#include "cnat_db.h" -#include "dslite_defs.h" - -#define DSLITE_PRINTF(level, ...) \ - if (dslite_debug_level > level) PLATFORM_DEBUG_PRINT(__VA_ARGS__); -/* -#define DSLITE_PRINTF(lvl, ...) \ -{ \ - avsm_dispatlib_debug (__VA_ARGS__); \ -} -*/ - -#define HASH_ENHANCE 4 -//#define DSLITE_DEF -#define DSLITE_MAIN_DB_SIZE (20000000 / PLATFORM_CNAT_INSTS) -#define DSLITE_MAIN_HASH_SIZE \ - (HASH_ENHANCE * PLATFORM_CNAT_MAIN_PRELIM_HASH_SIZE) - -#define DSLITE_MAIN_HASH_MASK (DSLITE_MAIN_HASH_SIZE-1) - - -/* nb: 200000 users / 64 CNAT = 3125, 76% occupancy */ -#define DSLITE_USER_HASH_SIZE CNAT_USER_HASH_SIZE -#define DSLITE_USER_HASH_MASK (DSLITE_USER_HASH_SIZE-1) - -/* No. of per ip/port config will be limited to 1000 */ -#define DSLITE_TIMEOUT_HASH_SIZE 1000 -#define DSLITE_TIMEOUT_HASH_MASK (DSLITE_TIMEOUT_HASH_SIZE - 1) -#define DSLITE_TIMEOUT_FULL_MASK 0xFFFFFFFFFFFFFFFF - -#define CNAT_MAX_SESSIONS_PER_BIB 0xFFFF - -#define FORCE_DEL 1 /* Delete static BIB entries as well */ - -/* default timeout values */ -#define DSLITE_UDP_DEFAULT 300 /* 5 min */ -#define DSLITE_UDP_MIN 120 /* 2 min */ -#define DSLITE_TCP_TRANS 240 /* 4 min */ -#define DSLITE_TCP_EST 7200 /* 2 hrs */ -#define DSLITE_TCP_V4_SYN 6 /* 6 sec */ -#define DSLITE_FRAG_MIN 2 /* 2 sec */ -#define DSLITE_ICMP_DEFAULT 60 /* 1 min */ - -extern u32 dslite_translation_create_count; -extern u32 dslite_translation_delete_count; -extern u32 dslite_translation_create_rate; -extern u32 dslite_translation_delete_rate; -extern u32 dslite_in2out_forwarding_count; -extern u32 dslite_in2out_forwarding_rate; -extern u32 dslite_out2in_forwarding_count; -extern u32 dslite_out2in_forwarding_rate; - -#define DSLITE_V6_GET_HASH(in_key, hash, mask) \ - a = in_key->ipv6[0] ^ in_key->ipv6[1] ^ in_key->ipv6[2] ^ in_key->ipv6[3] \ - ^ in_key->ipv4_key.k.ipv4 ^ ((in_key->ipv4_key.k.port << 16) | in_key->ipv4_key.k.vrf); \ - DSLITE_PRINTF(1, "%x:%x:%x:%x:%x:%x:%x\n", in_key->ipv6[0], in_key->ipv6[1], in_key->ipv6[2], in_key->ipv6[3], \ - in_key->ipv4_key.k.ipv4, in_key->ipv4_key.k.port, in_key->ipv4_key.k.vrf); \ - b = c = 0x9e3779b9;\ - /* Jenkins hash, arbitrarily use c as the "answer" */ \ - hash_mix32(a, b, c); \ - hash = c & mask; \ - - -#define DSLITE_V6_GET_USER_HASH(ipv6, hash, mask) \ - a = ipv6[0] ^ ipv6[1] ^ ipv6[2] ^ ipv6[3]; \ - b = c = 0x9e3779b9;\ - /* Jenkins hash, arbitrarily use c as the "answer" */ \ - hash_mix32(a, b, c); \ - hash = c & mask; \ - -#define DSLITE_V4_GET_HASH(in_key, hash, mask) \ - a = in_key.ipv4 ^ ((in_key.port << 16) | in_key.vrf); \ - b = c = 0x9e3779b9; \ - /* Jenkins hash, arbitrarily use c as the "answer" */ \ - hash_mix32(a, b, c); \ - hash = c & mask; - -#define PRIVATE_V4_ADDR_CHECK(addr, invalid) \ - invalid = 0; \ - int range1 = ((addr & 0xFF000000) >> 24); \ - int range2 = ((addr & 0xFFF00000) >> 20); \ - int range3 = ((addr & 0xFFFF0000) >> 16); \ - int range4 = ((addr & 0xFFFFFFF8) >> 3); \ - if(range1 != 0xa && range2 != 0xac1 && range3 != 0xc0a8 && range4 != 0x18000000) \ - invalid = 1; - -#define V4_MAPPED_V6_CHECK(v6_addr, invalid) \ - invalid = 0; \ - int word1 = v6_addr[0]; \ - int word2 = v6_addr[1]; \ - int word3 = v6_addr[2]; \ - if(!((word1 == 0) && (word2 == 0) && (word3 == 0x0000FFFF))) \ - invalid = 1; - - -extern dslite_table_entry_t dslite_table_array[DSLITE_MAX_DSLITE_ENTRIES]; -extern dslite_table_entry_t *dslite_table_ptr; - -#define DSLITE_CMP_V6_KEY(key1, key2) \ - memcmp(key1, key2, sizeof(dslite_v6_key_t)) - -#define DSLITE_CMP_V4_KEY(key1, key2) \ - memcmp(key1, key2, sizeof(dslite_v4_key_t)) - - -#define DSLITE_CMP_V6_IP(ip1, ip2) \ - memcmp(ip1, ip2, (sizeof(u32) * 4)) - - -#define DSLITE_CMP_V6_KEY1(key1, key2) \ - (key1.ipv6[0] == key2.ipv6[0]) && (key1.ipv6[1] == key2.ipv6[1]) && \ - (key1.ipv6[2] == key2.ipv6[2]) && (key1.ipv6[3] == key2.ipv6[3]) && \ - (key1.port == key2.port) && (key1.vrf == key2.vrf) - - -#define DSLITE_CMP_V6_IP1(ip1, ip2) \ - ((ip1[0] == ip2[0]) && (ip1[1] == ip2[1]) && \ - (ip1[2] == ip2[2]) && (ip1[3] == ip2[3])) - -#define DSLITE_CMP_V4_KEY1(key1, key2) \ - (key1.key64 == key2.key64) - -cnat_main_db_entry_t* -dslite_get_main_db_entry_v2(dslite_db_key_bucket_t *ki, - port_pair_t port_pair_type, - port_type_t port_type, - cnat_gen_icmp_info *info, - dslite_table_entry_t *dslite_entry_ptr, - cnat_key_t *dest_info); - -cnat_main_db_entry_t* -dslite_main_db_lookup_entry(dslite_db_key_bucket_t *ki); - - -cnat_user_db_entry_t* -dslite_user_db_lookup_entry(dslite_db_key_bucket_t *uki); - -cnat_user_db_entry_t* -dslite_user_db_create_entry(dslite_db_key_bucket_t *uki, u32 portmap_index); - -cnat_main_db_entry_t* -dslite_create_main_db_entry_and_hash(dslite_db_key_bucket_t *ki, - cnat_db_key_bucket_t *ko, - cnat_user_db_entry_t *udb); - -#endif diff --git a/plugins/plugins/vcgn/dslite_defs.h b/plugins/plugins/vcgn/dslite_defs.h deleted file mode 100644 index 4860adcb..00000000 --- a/plugins/plugins/vcgn/dslite_defs.h +++ /dev/null @@ -1,336 +0,0 @@ -/* - *------------------------------------------------------------------ - * dslite_defs.h - DSLITE structure definiitions - * - * Copyright (c) 2011-2012 Cisco and/or its affiliates. - * 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 __DSLITE_DEFS_H__ -#define __DSLITE_DEFS_H__ - -#ifdef TOBE_PORTED -#include "spp_platform_common.h" -#include "cgse_defs.h" -#endif -#include "cnat_cli.h" -#include "cnat_config.h" -#include "cnat_ports.h" -#include "cnat_bulk_port_defs.h" - -extern u32 ds_lite_config_debug_level; - -#define SWAP_IPV6_ADDR(ipv6_hdr, dslite_entry_ptr) \ - ipv6_hdr->dst_addr[0] = ipv6_hdr->src_addr[0]; \ - ipv6_hdr->dst_addr[1] = ipv6_hdr->src_addr[1]; \ - ipv6_hdr->dst_addr[2] = ipv6_hdr->src_addr[2]; \ - ipv6_hdr->dst_addr[3] = ipv6_hdr->src_addr[3]; \ - ipv6_hdr->src_addr[0] = spp_host_to_net_byte_order_32(dslite_entry_ptr->AFTR_v6_address[0]); \ - ipv6_hdr->src_addr[1] = spp_host_to_net_byte_order_32(dslite_entry_ptr->AFTR_v6_address[1]); \ - ipv6_hdr->src_addr[2] = spp_host_to_net_byte_order_32(dslite_entry_ptr->AFTR_v6_address[2]); \ - ipv6_hdr->src_addr[3] = spp_host_to_net_byte_order_32(dslite_entry_ptr->AFTR_v6_address[3]); - -#define DSLITE_SET_TX_PKT_TYPE(type) { \ - ctx->ru.tx.packet_type = type; \ -} - -#define DSLITE_INC_STATS_V4(PTR, COUNTER, IPV4_SRC_ADDR) { \ - PTR->COUNTER++; \ -} - -#define DSLITE_INC_STATS_V6(PTR, COUNTER, IPV6_DEST_ADDR) { \ - PTR->COUNTER++; \ -} - - -#define DSLITE_INVALID_UIDX 0xffff /*invalid svi app uidb index */ -#define DSLITE_INVALID_VRFID 0xffffffff /*invalid vrf id */ - -#define DSLITE_VRF_MASK 0x3fff -#define DSLITE_MAX_VRFMAP_ENTRIES (DSLITE_VRF_MASK + 1) - -#define DSLITE_VRFMAP_ENTRY_INVALID 0xffff - -#define DSLITE_V6_PREFIX_MASK_MIN 16 -#define DSLITE_V6_PREFIX_MASK_MAX 96 -#define DSLITE_V6_PREFIX_MASK_MULTIPLE 8 - -#define DSLITE_TUNNEL_MTU_MIN 1280 -#define DSLITE_TUNNEL_MTU_MAX 9216 - -#define DSLITE_TUNNEL_TTL_MIN 0 -#define DSLITE_TUNNEL_TTL_MAX 255 - -#define DSLITE_TUNNEL_TOS_MIN 0 -#define DSLITE_TUNNEL_TOS_MAX 255 - -#define DSLITE_V4_MASK_MAX 32 - -//#define XLAT_MAX_FRAG_ID_COUNTERS (256) -#define DSLITE_AFTR_IPV4_ADDR 0xC0000001 - -#define DSLITE_MAX_TAP_RG_ENTRIES 2 -#define DSLITE_MAX_DSLITE_ENTRIES (256) -#define DSLITE_MAX_DSLITE_ID (DSLITE_MAX_DSLITE_ENTRIES-1) -/* Define the below value as 64 if first 64 entries are for NAT44 */ -#define DSLITE_INDEX_OFFSET 1 - -#define DSLITE_INVALID_DSLITE_ID (0) - -#define DSLITE_TABLE_ENTRY_DELETED 0 -#define DSLITE_TABLE_ENTRY_ACTIVE 1 -#define DSLITE_TABLE_ENTRY_DORMANT 2 -#define DSLITE_TABLE_ENTRY_INVALID_UIDB 3 - -typedef struct { - u16 tcp_initial_setup_timeout; - u16 tcp_active_timeout; - u16 udp_init_session_timeout; - u16 udp_act_session_timeout; - u16 icmp_session_timeout; - u16 temp; -} dslite_timeout_info_t; - - -typedef struct { - - u16 state; /* To use nat44 enums ?? TBD */ - u16 dslite_id; /* DSLITE_ID value for this table entry - for easy access */ - - u16 i_vrf; /* V6 uidb index */ - u16 o_vrf; /* V4 uidb index */ - - u16 cnat_main_db_max_ports_per_user; /* port limit */ - u16 tcp_mss; /*tcp max segment size for this inside vrf */ - - u32 delete_time; - - cnat_portmap_v2_t *portmap_list; - - u32 nfv9_logging_index; - u32 syslog_logging_index; - u32 AFTR_v6_address[4]; - -#define DSLITE_IPV4_TOS_OVERRIDE_FLAG 0x00000001 -#define DSLITE_IPV6_TOS_OVERRIDE_FLAG 0x00000002 -#define DSLITE_IPV4_TTL_OVERRIDE_FLAG 0x00000004 -#define DSLITE_IPV6_TTL_OVERRIDE_FLAG 0x00000008 -#define DSLITE_IPV6_FRAG_REASSEMB_ENG 0x00000010 -#define DSLITE_FTP_ALG_ENABLE 0x00000020 -#define DSLITE_RTSP_ALG_ENABLE 0x00000040 -#define DSLITE_NETFLOW_ENABLE 0x00000080 -#define DSLITE_SYSLOG_ENABLE 0x00000100 - - u16 feature_flags; - u16 tunnel_mtu; - - u8 ipv4_ttl_value; - u8 ipv6_ttl_value; - u8 ipv4_tos_value; - u8 ipv6_tos_value; - - u32 v4_if_num; /* V4 SVI ifnum */ - u32 v6_if_num; /* V6 SVI ifnum */ - u32 i_vrf_id; //inside vrf id - u32 o_vrf_id; //outside vrf id - - dslite_timeout_info_t timeout_info; - u16 cnat_static_port_range; - u16 dyn_start_port; - - u32 AFTR_v4_addr; - bulk_alloc_size_t bulk_size; /* should be equivalent to u16 - 2 bytes */ - u32 pcp_server_addr; - u16 pcp_server_port; - u8 mapping_refresh_both_direction; - u8 pad; - u16 rtsp_port; -#define DSLITE_BIDIR_REFRESH 1 - u8 dslite_enable; /* DS-Lite enable check flag */ - u8 syslog_logging_policy; /* DS-Lite Session Logging check flag */ - u8 nf_logging_policy; - - u8 temp1; - u16 temp2; - u32 temp3; - u32 rseed_ip; -} dslite_table_entry_t; - -typedef struct { - u64 v4_to_v6_invalid_uidb_drop_count; - u64 v6_to_v4_invalid_uidb_drop_count; - u64 v4_to_v6_frag_invalid_uidb_drop_count; -} dslite_global_counters_t; - -typedef struct { - u32 tap_enable; - u32 ipv4_addr; - u32 ipv6_addr[4]; -} dslite_tap_rg_t; - -extern dslite_table_entry_t *dslite_table_db_ptr; - - -#define DSLITE_ADD_UIDB_INDEX_DSLITE_ID_MAPPING(uidb_index, dslite_id) \ - *(cgse_uidb_index_cgse_id_mapping_ptr + uidb_index) = dslite_id; - -extern u8 my_instance_number; - -extern void dslite_clear_counters(u16 dslite_id); -extern void dslite_clear_per_RG_counters(); -extern dslite_global_counters_t dslite_global_counters; -extern u32 dslite_config_debug_level; -extern u32 dslite_data_path_debug_level; -extern u32 dslite_defrag_debug_level; -extern u32 dslite_debug_level; - -typedef struct { - u64 v6_to_v4_tcp_input_count; - u64 v6_to_v4_tcp_nat_error; - u64 v6_to_v4_tcp_output_count; -} dslite_v6_to_v4_tcp_counter_t; - -typedef struct { - u64 v4_to_v6_tcp_input_count; - u64 v4_to_v6_tcp_no_entry; - u64 v4_to_v6_tcp_output_count; -} dslite_v4_to_v6_tcp_counter_t; - -typedef struct { - u64 v6_to_v4_udp_input_count; - u64 v6_to_v4_udp_nat_error; - u64 v6_to_v4_udp_output_count; -} dslite_v6_to_v4_udp_counter_t; - -typedef struct { - u64 v4_to_v6_udp_input_count; - u64 v4_to_v6_udp_no_entry; - u64 v4_to_v6_udp_output_count; -} dslite_v4_to_v6_udp_counter_t; - -typedef struct { - u64 v6_to_v4_icmp_qry_input_count; - u64 v6_to_v4_icmp_qry_nat_error; - u64 v6_to_v4_icmp_qry_output_count; -} dslite_v6_to_v4_icmp_qry_counter_t; - -typedef struct { - u64 v4_to_v6_icmp_qry_input_count; - u64 v4_to_v6_icmp_qry_no_nat_entry; - u64 v4_to_v6_icmp_qry_output_count; -} dslite_v4_to_v6_icmp_qry_counter_t; - -typedef struct { - u64 v6_to_v4_icmp_error_input_count; - u64 v6_to_v4_icmp_error_nat_error; - u64 v6_to_v4_icmp_error_output_count; -} dslite_v6_to_v4_icmp_error_counter_t; - -typedef struct { - u64 v4_to_v6_icmp_error_input_count; - u64 v4_to_v6_icmp_error_no_nat_entry; - u64 v4_to_v6_icmp_error_output_count; -} dslite_v4_to_v6_icmp_error_counter_t; - -typedef struct { - u64 v6_icmp_error_input_count; - u64 v6_AFTR_echo_reply_count; - u64 v6_to_v4_icmp_error_unsupported_type_drop_count; - u64 v6_to_v4_icmp_error_no_db_entry_count; - u64 v6_to_v4_icmp_err_throttled_count; - u64 v6_to_v4_icmp_error_xlated_count; -} dslite_v6_icmp_error_counter_t; - -typedef struct { - u64 v4_to_v6_ttl_gen_count; - u64 v4_to_v6_icmp_throttle_count; - u64 v4_to_v6_ptb_gen_count; - u64 v4_to_v6_aftr_v4_echo_reply_count; - u64 v6_to_v4_ttl_gen_count; - u64 v6_to_v4_icmp_throttle_count; - u64 v6_to_v4_admin_prohib_icmp_count; - u64 v6_to_v4_aftr_v4_echo_reply_count; - u64 v6_icmp_gen_count; -} dslite_icmp_gen_counter_t; - -typedef struct { - u64 dslite_input_tunnel_pkt; - u64 dslite_encap_count; - u64 dslite_decap_count; - u64 dslite_sec_check_failed; - u64 dslite_unsupp_packet; -} dslite_common_counter_t; - -typedef struct { - - dslite_v6_to_v4_tcp_counter_t v64_tcp_counters; - dslite_v4_to_v6_tcp_counter_t v46_tcp_counters; - dslite_v6_to_v4_udp_counter_t v64_udp_counters; - dslite_v4_to_v6_udp_counter_t v46_udp_counters; - dslite_v6_to_v4_icmp_qry_counter_t v64_icmp_counters; - dslite_v4_to_v6_icmp_qry_counter_t v46_icmp_counters; - dslite_v6_to_v4_icmp_error_counter_t v64_icmp_error_counters; - dslite_v4_to_v6_icmp_error_counter_t v46_icmp_error_counters; - dslite_v6_icmp_error_counter_t dslite_v6_icmp_err_counters; - dslite_icmp_gen_counter_t dslite_icmp_gen_counters; - dslite_common_counter_t dslite_common_counters; -} dslite_counters_t; - -typedef struct { - u32 active_translations; - u32 translation_create_rate; - u32 translation_delete_rate; - u32 in2out_forwarding_rate; - u32 out2in_forwarding_rate; - u32 in2out_drops_port_limit_exceeded; - u32 in2out_drops_system_limit_reached; - u32 in2out_drops_resource_depletion; - u32 no_translation_entry_drops; - u32 pool_address_totally_free; - u32 num_subscribers; - u32 dummy; - u64 drops_sessiondb_limit_exceeded; -} dslite_common_stats_t; - -typedef struct { - u16 msg_id; - u8 rc; - u8 pad[5]; - dslite_counters_t counters; -} dslite_show_statistics_summary_resp; - - -#define CMD_GENERATE_PTB 0x1 -#define CMD_GENERATE_TTL 0x2 - -/* - * This structure is to provide abstraction for data exchanged from one - * VPP node to its disposition or further in the dslite node graph. - */ -typedef struct { - u32 icmp_gen_type; // ctx->feature_data[0] - u32 reserved1; // ctx->feature_data[1] - u32 reserved2; // ctx->feature_data[2] - u32 reserved3; // ctx->feature_data[3] -} dslite_feature_data_t; - -extern dslite_counters_t dslite_all_counters[DSLITE_MAX_DSLITE_ENTRIES]; -//extern dslite_inst_gen_counter_t dslite_inst_gen_counters[DSLITE_MAX_DSLITE_ENTRIES]; - - - extern void dslite_show_config(void); -#define STAT_PORT_RANGE_FROM_INST_PTR(inst) ((inst)->cnat_static_port_range) - -#endif /* __DSLITE_DEFS_H__ */ - diff --git a/plugins/plugins/vcgn/index_list.c b/plugins/plugins/vcgn/index_list.c deleted file mode 100644 index ec1b83b0..00000000 --- a/plugins/plugins/vcgn/index_list.c +++ /dev/null @@ -1,336 +0,0 @@ -/* - *------------------------------------------------------------------ - * index_list.c - vector-index-based lists. 64-bit pointers suck. - * - * Copyright (c) 2008-2009, 2011 Cisco and/or its affiliates. - * 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 -#include -//#include -#include -#include "index_list.h" - -/* - * index_slist_addhead - * - * args: headp -- pointer to e.g. a hash bucket - * vector -- vector containing the list - * elsize -- size of an element in this vector - * offset -- offset in each vector element of this list thread - * index_to_add -- index in the vector to add to the list - * - * Adds new items to the head of the list. Try not to screw up the args! - */ -void index_slist_addhead (index_slist_t *headp, - u8 *vector, u32 elsize, u32 offset, u32 index_to_add) -{ - return (index_slist_addhead_inline(headp, vector, elsize, offset, - index_to_add)); -} - -/* - * index_slist_remelem - * - * args: headp -- pointer to e.g. a hash bucket - * vector -- vector containing the list - * elsize -- size of an element in this vector - * offset -- offset in each vector element of this list thread - * index_to_del -- index in the vector to delete from the list - * - * Try not to screw up the args! - */ - -int index_slist_remelem (index_slist_t *headp, - u8 *vector, u32 elsize, u32 offset, - u32 index_to_delete) -{ - return (index_slist_remelem_inline(headp, vector, elsize, offset, - index_to_delete)); -} - - -/* - * index_dlist_addtail - * - * Append the indicated vector element to the doubly-linked list - * whose first element is pointed to by headp. - * - * args: head_index -- listhead vector element index. - * vector -- vector containing the list - * elsize -- size of an element in this vector - * offset -- offset in each vector element of this list thread - * index_to_add -- index in the vector to add to the list - * - * Do not call this routine to create the listhead. Simply set - * index_dlist->next = index_dlist->prev = index of item. - * - * Try not to screw up the args. - */ - -void index_dlist_addtail (u32 head_index, u8 *vector, u32 elsize, - u32 offset, u32 index_to_add) -{ - index_dlist_t *elp; - index_dlist_t *elp_next; - index_dlist_t *headp; - - headp = (index_dlist_t *)(vector + offset + elsize*head_index); - elp = (index_dlist_t *)(vector + offset + elsize*index_to_add); - elp->next = index_to_add; - elp->prev = index_to_add; - - elp->next = headp->next; - headp->next = index_to_add; - - elp_next = (index_dlist_t *)(vector + offset + elsize*elp->next); - elp->prev = elp_next->prev; - elp_next->prev = index_to_add; -} - -u32 index_dlist_remelem (u32 head_index, - u8 *vector, u32 elsize, u32 offset, - u32 index_to_delete) -{ - u32 rv = head_index; - index_dlist_t *headp, *elp, *elp_next; - - elp = (index_dlist_t *)(vector + offset + elsize*index_to_delete); - - /* Deleting the head index? */ - if (PREDICT_FALSE(head_index == index_to_delete)) { - rv = elp->next; - /* The only element on the list? */ - if (PREDICT_FALSE(rv == head_index)) - rv = EMPTY; - } - - headp = (index_dlist_t *)(vector + offset + elsize*elp->prev); - headp->next = elp->next; - elp_next = (index_dlist_t *)(vector + offset + elsize*elp->next); - elp_next->prev = elp->prev; - - elp->next = elp->prev = EMPTY; - - return rv; -} - - -#ifdef TEST_CODE2 - -typedef struct tv_ { - char junk[43]; - index_dlist_t l; -} tv_t; - - -void index_list_test_cmd(int argc, unsigned long *argv) -{ - int i, j; - u32 head_index; - index_dlist_t *headp; - tv_t *tp=0; - - vec_validate(tp, 3); - head_index = 3; - - memset(tp, 0xa, sizeof(tp[0])*vec_len(tp)); - - /* Here's how to set up the head element... */ - headp = &((tp + head_index)->l); - headp->next = headp->prev = head_index; - - for (i = 0; i < 3; i++) { - index_dlist_addtail(head_index, (u8 *)tp, sizeof(tp[0]), - STRUCT_OFFSET_OF(tv_t, l), i); - printf("headp next %d prev %d\n", - headp->next, headp->prev); - for (j = 0; j <= 3; j++) { - printf ("[%d]: next %d prev %d\n", j, - tp[j].l.next, tp[j].l.prev); - } - printf("---------------\n"); - - } - - printf("After all adds:\n"); - - printf("headp next %d prev %d\n", - headp->next, headp->prev); - - for (j = 0; j <= 3; j++) { - printf ("[%d]: next %d prev %d\n", j, - tp[j].l.next, tp[j].l.prev); - } - printf("---------------\n"); - - head_index = index_dlist_remelem (head_index, (u8 *)tp, sizeof(tp[0]), - STRUCT_OFFSET_OF(tv_t, l), 1); - - printf("after delete 1, head index %d\n", head_index); - headp = &((tp + head_index)->l); - printf("headp next %d prev %d\n", - headp->next, headp->prev); - for (j = 0; j <= 3; j++) { - printf ("[%d]: next %d prev %d\n", j, - tp[j].l.next, tp[j].l.prev); - } - printf("---------------\n"); - - index_dlist_addtail(head_index, (u8 *)tp, sizeof(tp[0]), - STRUCT_OFFSET_OF(tv_t, l), 1); - - printf("after re-add 1, head index %d\n", head_index); - headp = &((tp + head_index)->l); - printf("headp next %d prev %d\n", - headp->next, headp->prev); - for (j = 0; j <= 3; j++) { - printf ("[%d]: next %d prev %d\n", j, - tp[j].l.next, tp[j].l.prev); - } - printf("---------------\n"); - - for (i = 3; i >= 0; i--) { - head_index = index_dlist_remelem (head_index, (u8 *)tp, sizeof(tp[0]), - STRUCT_OFFSET_OF(tv_t, l), i); - printf("after delete, head index %d\n", head_index); - if (head_index != EMPTY) { - headp = &((tp + head_index)->l); - printf("headp next %d prev %d\n", - headp->next, headp->prev); - for (j = 0; j <= 3; j++) { - printf ("[%d]: next %d prev %d\n", j, - tp[j].l.next, tp[j].l.prev); - } - } else { - printf("empty list\n"); - } - printf("---------------\n"); - } -} -#endif /* test code 2 */ - -#ifdef TEST_CODE - -typedef struct tv_ { - char junk[43]; - index_slist_t l; -} tv_t; - - -void index_list_test_cmd(int argc, unsigned long *argv) -{ - int i, j; - tv_t *tp = 0; - index_slist_t *buckets = 0; - - vec_add1((u32 *)buckets, EMPTY); - vec_validate(tp, 9); - - for (i = 0; i < 10; i++) { - index_slist_addhead(buckets, (u8 *)tp, sizeof(*tp), - STRUCT_OFFSET_OF(tv_t, l), i); - } - - printf ("after adds, buckets[0] = %u\n", buckets[0]); - - for (j = 0; j < 10; j++) { - printf("tp[%d] next %u\n", j, tp[j].l); - - } - - for (i = 0; i < 10; i++) { - if (PREDICT_FALSE(index_slist_remelem(buckets, (u8 *) tp, sizeof(*tp), - STRUCT_OFFSET_OF(tv_t, l), i))) { - printf("OUCH: remelem failure at index %d\n", i); - } - if (PREDICT_FALSE(tp[i].l.next != EMPTY)) { - printf("OUCH: post-remelem next not EMPTY, index %d\n", i); - } - } - - printf ("after deletes, buckets[0] = %x\n", buckets[0]); - - for (i = 0; i < 10; i++) { - index_slist_addhead(buckets, (u8 *)tp, sizeof(*tp), - STRUCT_OFFSET_OF(tv_t, l), i); - } - - printf ("after adds, buckets[0] = %u\n", buckets[0]); - - for (j = 0; j < 10; j++) { - printf("tp[%d] next %u\n", j, tp[j].l); - - } - - for (i = 9; i >= 0; i--) { - if (PREDICT_FALSE(index_slist_remelem(buckets, (u8 *) tp, sizeof(*tp), - STRUCT_OFFSET_OF(tv_t, l), i))) { - printf("OUCH: remelem failure at index %d\n", i); - } - if ((tp[i].l.next != EMPTY)) { - printf("OUCH: post-remelem next not EMPTY, index %d\n", i); - } - } - - printf ("after deletes, buckets[0] = %x\n", buckets[0]); - - printf("add evens, then odds...\n"); - - for (i = 0; i < 10; i += 2) { - index_slist_addhead(buckets, (u8 *)tp, sizeof(*tp), - STRUCT_OFFSET_OF(tv_t, l), i); - - printf ("head = buckets[0].next = %d\n", buckets[0].next); - for (j = 0; j < 10; j++) { - printf("tp[%d] next %u\n", j, tp[j].l); - } - printf("-------------\n"); - } - - for (i = 1; i < 10; i += 2) { - index_slist_addhead(buckets, (u8 *)tp, sizeof(*tp), - STRUCT_OFFSET_OF(tv_t, l), i); - - printf ("head = buckets[0].next = %d\n", buckets[0].next); - for (j = 0; j < 10; j++) { - printf("tp[%d] next %u\n", j, tp[j].l); - } - printf("-------------\n"); - } - - printf ("after adds, buckets[0] = %u\n", buckets[0]); - - for (j = 0; j < 10; j++) { - printf("tp[%d] next %u\n", j, tp[j].l); - - } - - for (i = 9; i >= 0; i--) { - if (PREDICT_FALSE(index_slist_remelem(buckets, (u8 *) tp, sizeof(*tp), - STRUCT_OFFSET_OF(tv_t, l), i))) { - printf("OUCH: remelem failure at index %d\n", i); - } - if (PREDICT_FALSE(tp[i].l.next != EMPTY)) { - printf("OUCH: post-remelem next not EMPTY, index %d\n", i); - } - } - - printf ("after deletes, buckets[0] = %x\n", buckets[0]); - - vec_free(buckets); - vec_free(tp); -} -#endif /* test code */ diff --git a/plugins/plugins/vcgn/index_list.h b/plugins/plugins/vcgn/index_list.h deleted file mode 100644 index 498cd7eb..00000000 --- a/plugins/plugins/vcgn/index_list.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - *------------------------------------------------------------------ - * index_list.h - vector-index-based doubly-linked lists - * - * Copyright (c) 2008-2009 Cisco and/or its affiliates. - * 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 _INDEX_LIST_H_ -#define _INDEX_LIST_H_ 1 - -/* An index we can't possibly see in practice... */ -#define EMPTY ((u32)~0) - -typedef struct index_slist_ { - u32 next; -} index_slist_t; - -/* - * index_slist_addhead - * - * args: headp -- pointer to e.g. a hash bucket - * vector -- vector containing the list - * elsize -- size of an element in this vector - * offset -- offset in each vector element of this list thread - * index_to_add -- index in the vector to add to the list - * - * Adds new items to the head of the list. Try not to screw up the args! - */ -static inline void - index_slist_addhead_inline (index_slist_t *headp, - u8 *vector, u32 elsize, - u32 offset, u32 index_to_add) -{ - index_slist_t *addme; - - addme = (index_slist_t *)(vector + offset + elsize*index_to_add); - addme->next = EMPTY; - - if (headp->next == EMPTY) { - headp->next = index_to_add; - return; - } else { - addme->next = headp->next; - headp->next = index_to_add; - } -} - -/* - * index_slist_remelem - * - * args: headp -- pointer to e.g. a hash bucket - * vector -- vector containing the list - * elsize -- size of an element in this vector - * offset -- offset in each vector element of this list thread - * index_to_del -- index in the vector to delete from the list - * - * Try not to screw up the args! - */ - -static inline int - index_slist_remelem_inline (index_slist_t *headp, - u8 *vector, u32 elsize, - u32 offset, u32 index_to_delete) -{ - index_slist_t *findme; - index_slist_t *prev; - index_slist_t *cur; - - findme = (index_slist_t *)(vector + offset + elsize*index_to_delete); - - if (headp->next == index_to_delete) { - headp->next = findme->next; - findme->next = EMPTY; - return 0; - } - - prev = (index_slist_t *)(vector + offset + elsize*headp->next); - cur = (index_slist_t *)(vector + offset + elsize*prev->next); - while (cur != findme) { - if (cur->next == EMPTY) - return (1); - prev = cur; - cur = (index_slist_t *)(vector + offset + elsize*cur->next); - } - prev->next = findme->next; - findme->next = EMPTY; - return 0; -} - -void index_slist_addhead (index_slist_t *headp, - u8 *vector, u32 elsize, u32 offset, u32 index); -int index_slist_remelem (index_slist_t *headp, - u8 *vector, u32 elsize, u32 offset, u32 index); - -typedef struct index_dlist_ { - u32 next; - u32 prev; -} index_dlist_t; - -void index_dlist_addtail (u32 head_index, u8 *vector, u32 elsize, - u32 offset, u32 index_to_add); - -u32 index_dlist_remelem (u32 head_index, - u8 *vector, u32 elsize, u32 offset, - u32 index_to_delete); -#endif /* _INDEX_LIST_H_ */ diff --git a/plugins/plugins/vcgn/nat64_db.h b/plugins/plugins/vcgn/nat64_db.h deleted file mode 100644 index 837464f6..00000000 --- a/plugins/plugins/vcgn/nat64_db.h +++ /dev/null @@ -1,480 +0,0 @@ -/* - *------------------------------------------------------------------ - * nat64_db.h - Stateful NAT64 translation database definitions - * - * Copyright (c) 2010-2013 Cisco and/or its affiliates. - * 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 __NAT64_DB_H__ -#define __NAT64_DB_H__ - -#include "cnat_cli.h" -#include "index_list.h" -#include "cnat_ports.h" -#include "cnat_db.h" -#include "nat64_defs.h" -#include "cnat_bulk_port_defs.h" - -nat64_vrfmap_t *nat64_map_by_vrf; - -#define SESSION_OPT - -#define HASH_ENHANCE 4 - - -#define NAT64_MAIN_DB_SIZE \ - (PLATFORM_NAT64_MAX_SESSIONS / PLATFORM_CNAT_INSTS) -#define NAT64_MAIN_HASH_SIZE \ - (HASH_ENHANCE * PLATFORM_CNAT_MAIN_PRELIM_HASH_SIZE) - -#define NAT64_MAIN_HASH_MASK (NAT64_MAIN_HASH_SIZE-1) - - -/* nb: 200000 users / 64 CNAT = 3125, 76% occupancy */ -#define NAT64_USER_HASH_SIZE CNAT_USER_HASH_SIZE -#define NAT64_USER_HASH_MASK (NAT64_USER_HASH_SIZE-1) - -/* Number of sessions per BIB entry/NAT64 translation - - nsessions is u16 type. So selected 0xFFFF - - Ideally Sessions per transltion will not reach the limit - - Only DoS can possible. It can take care of it */ -#define NAT64_MAX_SESSIONS_PER_BIB 0xFFFF - -/* No. of per ip/port config will be limited to 1000 */ -/* totally 25K across all instances) */ -#define NAT64_TIMEOUT_HASH_SIZE \ - PLATFORM_NAT64_TIMEOUT_HASH_SIZE - -#define NAT64_TIMEOUT_HASH_MASK (NAT64_TIMEOUT_HASH_SIZE - 1) -#define NAT64_TIMEOUT_FULL_MASK 0xFFFFFFFFFFFFFFFF - - -#define FORCE_DEL 1 /* Delete static BIB entries as well */ - -/* default timeout values */ -#define NAT64_UDP_DEFAULT 300 /* 5 min */ -#define NAT64_UDP_MIN 120 /* 2 min */ -#define NAT64_TCP_TRANS 240 /* 4 min */ -#define NAT64_TCP_EST 7200 /* 2 hrs */ -#define NAT64_TCP_V4_SYN 6 /* 6 sec */ -#define NAT64_FRAG_MIN 2 /* 2 sec */ -#define NAT64_ICMP_DEFAULT 60 /* 1 min */ - - -#define NAT64_V6_GET_HASH(in_key, hash, mask) \ - a = in_key->ipv6[0] ^ in_key->ipv6[1] ^ in_key->ipv6[2] ^ in_key->ipv6[3] \ - ^ ((in_key->port << 16) | in_key->vrf); \ - b = c = 0x9e3779b9;\ - /* Jenkins hash, arbitrarily use c as the "answer" */ \ - hash_mix32(a, b, c); \ - hash = c & mask; \ - - -#define NAT64_V4_GET_HASH(in_key, hash, mask) \ - a = in_key.ipv4 ^ ((in_key.port << 16) | in_key.vrf); \ - b = c = 0x9e3779b9; \ - /* Jenkins hash, arbitrarily use c as the "answer" */ \ - hash_mix32(a, b, c); \ - hash = c & mask; - - - -#define NAT64_V6_GET_SESSION_HASH(bib_index, in_addr, port, vrf, hash, mask) \ - a = bib_index ^ in_addr[0] ^ in_addr[1] ^ in_addr[2] ^ in_addr[3] \ - ^ port ^ vrf; \ - b = c = 0x9e3779b9; \ - /* Jenkins hash, arbitrarily use c as the "answer" */ \ - hash_mix32(a, b, c); \ - hash = c & mask; - -#define NAT64_V4_GET_SESSION_HASH(bib_index, in_addr, port, vrf, hash, mask) \ - a = bib_index ^ in_addr ^ port ^ vrf; \ - b = c = 0x9e3779b9; \ - /* Jenkins hash, arbitrarily use c as the "answer" */ \ - hash_mix32(a, b, c); \ - hash = c & mask; - - -extern index_slist_t *nat64_bib_out2in_hash; -extern index_slist_t *nat64_bib_in2out_hash; -extern index_slist_t *nat64_bib_user_hash; -extern index_slist_t *nat64_session_out2in_hash; -#ifndef SESSION_OPT -extern index_slist_t *nat64_session_in2out_hash; -#endif -extern index_slist_t *nat64_frag_out2in_hash; -extern index_slist_t *nat64_frag_in2out_hash; -extern index_slist_t *nat64_timeout_hash; - - -/* - * nat64_ bib_entry_t - * This structure depicts Binding Information Base of NAT64 sessions. - * It stores information about the inside v6 source transport address and - * corresponding outside v4 source transport address for each protocol. - */ - -typedef struct { - - index_slist_t nat64_bib_out2in_hash; - index_slist_t nat64_bib_in2out_hash; - - /* 0x08 */ - u16 flags; /* flags in cnat_db.h (cnat_main_db_entry_t) */ -#define NAT64_DB_FLAG_STATIC_PORT CNAT_DB_FLAG_STATIC_PORT -#define NAT64_DB_NAT64_FLAG CNAT_DB_NAT64_FLAG -#define NAT64_DB_FLAG_ALG_ENTRY CNAT_DB_FLAG_ALG_ENTRY -#define NAT64_DB_FLAG_PCPI CNAT_DB_FLAG_PCPI -#define NAT64_DB_FLAG_PCPE CNAT_DB_FLAG_PCPE - - /* 0x0A */ - u16 nat64_inst_id; - /* 0x0C */ - u32 user_index; - - /* 0x10 */ - nat64_v4_key_t v4_out_key; - - /* 0x18 */ - nat64_v6_key_t v6_in_key; - - /* 0x2C */ - index_dlist_t user_ports; - /* 0x34 */ - u32 session_head_index; - /* 0x38 - 56B*/ - u16 nsessions; - u16 pad2; - - /* 0x3C - 60B */ - u32 in2outpkts; - u32 out2inpkts; - /* 0x44 - 68B */ - - /* 0x42 - 70B */ - union { /* used by FTP ALG, pkt len delta due to FTP PORT cmd */ - u16 delta; - i8 alg_dlt[2]; /* two delta values, 0 for previous, 1 for current */ - u16 il; /* Used to indicate if interleaved mode is used - in case of RTSP ALG */ - } alg; - - u16 temp1; - - u32 entry_expires; - - u32 temp3; - /* unused, temp1 ,temp2 and temp3 put to make it in sync with nat44 main db entry size */ - /* size of = 0x54 = 84 B */ - u32 unused; - -} nat64_bib_entry_t ; - -/* - * nat64_bib_user_entry_t - * This structure stores information about translations of a particular user - * (User here refers to a same inside source address) - */ -typedef struct { - /* 0x00 */ - index_slist_t user_hash; - /* 0x04 */ - u16 ntranslations; - /* 0x06 */ - u8 icmp_msg_count; - /* 0x07 */ - u8 flags; -#define NAT64_USER_DB_NAT64_FLAG CNAT_USER_DB_NAT64_FLAG - - /* 0x08 */ - u32 translation_list_head_index; - /* 0x0C */ - u32 portmap_index; - /* 0x10 */ - nat64_v6_key_t v6_in_key; - /* 0x24 = 36 B */ - - u32 align1; /* Make it 8B boundary and in sync with nat44 user db entry size */ -#ifndef NO_BULK_LOGGING - /* size of = 0x28 = 40 B */ - /* Now adding 8 more bytes for bulk allocation.. This makes it - * 0x30 (48). For nat64 stful, we may support bulk allocation - * later */ - /* Indicates the currently used bulk port range */ - i16 bulk_port_range_cache[BULK_RANGE_CACHE_SIZE]; -#endif /* NO_BULK_LOGGING */ -} nat64_bib_user_entry_t; - -/* - * nat64_session_entry_t - * This structure represents the session table. It maintains the information - * about the flow of the packets. It would consist of source and destination - * (inside and outside) ipv4 and ipv4 transport addresses. - */ -typedef struct { - - /* 0x00 */ - index_slist_t nat64_session_out2in_hash; - - /* 0x04 */ - u32 bib_index; /* would point to v4/v6 src transport address */ - - /* 0x08 */ - nat64_v4_key_t v4_dest_key; - -#ifndef SESSION_OPT - index_slist_t nat64_session_in2out_hash; - nat64_v6_key_t v6_dest_key; -#endif - - /* 0x10 */ - u16 flags;/* Will be used for flags same as nat44 session */ - - /* 0x12 */ - u16 timeout; - - /* 0x14 */ - u32 entry_expires; - /* 0x18 */ - index_dlist_t bib_list; - /* 0x20 = 32 B */ - - union { /* alg same as cnat_main_db_t */ - u16 delta; - i8 alg_dlt[2]; - u16 il; - } alg; - - /* 0x22 */ - u16 tcp_flags; /* Mainly TCP events - check nat64_tcp_sm.h */ - - /* 0x24 */ - u32 tcp_seq_num; - - /* 0x28 */ /* unused1, unused2 and unused3 are put to make it in sync with - * cnat_session_db */ - u32 unused1; - - /* 0x2C */ - u32 unused2; - - /* 0x30 */ - u16 unused3; - - /* 0x32 - 50B */ - -} nat64_session_entry_t; - -/* - * nat64_session_tcp_init_entry_t - * This structure will be used to store information about v4 initiation - * tcp entries. - */ -typedef struct { - nat64_v6_key_t v6_in_key; - nat64_v4_key_t v4_out_key; -} nat64_session_tcp_init_entry_t; - -/* - * nat64_in_v6_frag_entry_t - * This structure will be used to store information about fragment flows - * that are coming from inside v6 hosts. - */ -typedef struct { - index_slist_t nat64_frag_in2out_hash; - - u32 v6_src_addr[4]; - u32 v6_destn_addr[4]; - u32 frag_iden; - u16 vrf; - u16 pad1; -} nat64_in_v6_frag_entry_t ; - -/* - * nat64_out_v4_frag_entry_t - * This structure will be used to store information about fragment flows - * that are coming from outside v4 machines. - */ -typedef struct { - index_slist_t nat64_frag_out2in_hash; - - u32 v4_src_addr; - u32 v4_destn_addr; - u16 frag_iden; - u16 vrf; -} nat64_out_v4_frag_entry_t ; - -/* - * nat64_timeout _t - * These following structures will be used to store information destination - * timeouts configured. - */ -typedef struct { - nat64_v4_key_t timeout_key; - u16 timeout_value; -} nat64_timeout_t; - -/* - * nat64_timeout_db_entry_t - */ -typedef struct { - nat64_timeout_t t_key; - index_slist_t t_hash; -} nat64_timeout_db_entry_t; - - -typedef union { - cnat_main_db_entry_t nat44_main_db; - nat64_bib_entry_t nat64_bib_db; -} cgse_nat_db_entry_t; - -typedef union { - cnat_session_entry_t nat44_session_db; - nat64_session_entry_t nat64_session_db; -} cgse_nat_session_db_entry_t; - -typedef union { - cnat_user_db_entry_t nat44_user_db; - nat64_bib_user_entry_t nat64_user_db; -} cgse_nat_user_db_entry_t; - -extern index_slist_t *nat64_bib_out2in_hash; -extern index_slist_t *nat64_bib_in2out_hash; -extern index_slist_t *nat64_bib_user_hash; -extern index_slist_t *nat64_session_out2in_hash; -extern index_slist_t *nat64_session_in2out_hash; -extern index_slist_t *nat64_frag_out2in_hash; -extern index_slist_t *nat64_frag_in2out_hash; -extern index_slist_t *nat64_timeout_hash; - -extern nat64_bib_entry_t *nat64_bib_db; -extern nat64_bib_user_entry_t *nat64_bib_user_db; -extern nat64_session_entry_t *nat64_session_db; -extern nat64_in_v6_frag_entry_t *nat64_in_frag_db; -extern nat64_out_v4_frag_entry_t *nat64_out_frag_db; -extern nat64_session_tcp_init_entry_t *nat64_tcp_init_db ; -extern nat64_timeout_db_entry_t *nat64_timeout_db; - -extern nat64_table_entry_t nat64_table_array[NAT64_MAX_NAT64_ENTRIES]; -extern nat64_table_entry_t *nat64_table_ptr; - -extern cgse_nat_db_entry_t *cgse_nat_db; -extern cgse_nat_user_db_entry_t *cgse_user_db; -extern cgse_nat_session_db_entry_t *cgse_session_db; - -void nat64_bib_user_db_delete (nat64_bib_user_entry_t *up); - -nat64_bib_user_entry_t* -nat64_bib_user_db_create_entry(nat64_v6_key_t *uki, u32 bucket, - u32 portmap_index); - -nat64_bib_user_entry_t* -nat64_bib_user_db_lookup_entry(nat64_v6_key_t *uki, u32 *bucket); - - -nat64_bib_entry_t* -nat64_bib_db_lookup_entry(nat64_v6_key_t *ki); - -void nat64_bib_db_in2out_hash_delete (nat64_bib_entry_t *ep); - -void nat64_bib_db_out2in_hash_delete (nat64_bib_entry_t *ep); - -nat64_bib_entry_t * -nat64_create_bib_db_entry_and_hash(nat64_v6_key_t *ki, - nat64_v4_key_t *ko, - nat64_bib_user_entry_t *udb); - - -void nat64_delete_bib_db_entry (nat64_bib_entry_t *ep, u8 force); - -nat64_bib_entry_t * -nat64_bib_db_lookup_entry_out2in (nat64_v4_key_t *ko); - -nat64_bib_entry_t * -nat64_get_bib_db_entry (nat64_v6_key_t *ki, - port_pair_t port_pair_type, - port_type_t port_type, - cnat_gen_icmp_info *info); - - -nat64_bib_entry_t* -nat64_create_static_bib_db_entry (nat64_v6_key_t *ki, - nat64_v4_key_t *ko, - nat64_table_entry_t *my_table, - cnat_gen_icmp_info *info); - - - -//void nat64_session_db_in2out_hash_delete (nat64_session_entry_t *ep); -void nat64_session_db_out2in_hash_delete (nat64_session_entry_t *ep); - -/*nat64_session_entry_t * -nat64_session_db_lookup_entry(nat64_v6_key_t *ki, u32 bib_index); */ - - -nat64_session_entry_t * -nat64_session_db_lookup_entry_out2in (nat64_v4_key_t *ko,u32 bib_index); - -/* -nat64_session_entry_t * -nat64_create_session_db_entry(nat64_v6_key_t *ki, - nat64_v4_key_t *ko, - nat64_bib_entry_t *bdb); -*/ -nat64_session_entry_t * -nat64_create_session_db_entry_v2( nat64_v4_key_t *ko, - nat64_bib_entry_t *bdb); - - -//void nat64_delete_session_db_entry (nat64_session_entry_t *ep); -void nat64_delete_session_db_entry_v2 (nat64_session_entry_t *ep, u8 force); - -u32 nat64_timeout_db_hash_lookup (nat64_v4_key_t t_key); - -u16 query_and_update_db_timeout_nat64(nat64_session_entry_t *db); - -void nat64_timeout_db_hash_add (nat64_timeout_db_entry_t *t_entry); - -u16 nat64_timeout_db_create (nat64_timeout_t t_entry); - -void nat64_timeout_db_delete(nat64_v4_key_t t_key); - -#define NAT64_CMP_V6_KEY(key1, key2) \ - memcmp(key1, key2, sizeof(nat64_v6_key_t)) - -#define NAT64_CMP_V4_KEY(key1, key2) \ - memcmp(key1, key2, sizeof(nat64_v4_key_t)) - - -#define NAT64_CMP_V6_IP(ip1, ip2) \ - memcmp(ip1, ip2, (sizeof(u32) * 4)) - - -#define NAT64_CMP_V6_KEY1(key1, key2) \ - (key1.ipv6[0] == key2.ipv6[0]) && (key1.ipv6[1] == key2.ipv6[1]) && \ - (key1.ipv6[2] == key2.ipv6[2]) && (key1.ipv6[3] == key2.ipv6[3]) && \ - (key1.port == key2.port) && (key1.vrf == key2.vrf) - - -#define NAT64_CMP_V6_IP1(ip1, ip2) \ - ((ip1[0] == ip2[0]) && (ip1[1] == ip2[1]) && \ - (ip1[2] == ip2[2]) && (ip1[3] == ip2[3])) - -#define NAT64_CMP_V4_KEY1(key1, key2) \ - (key1.key64 == key2.key64) - - -extern u8 nat64_timeout_dirty_flag[NAT64_MAX_NAT64_ENTRIES]; - -#endif diff --git a/plugins/plugins/vcgn/nat64_defs.h b/plugins/plugins/vcgn/nat64_defs.h deleted file mode 100644 index 47e431a7..00000000 --- a/plugins/plugins/vcgn/nat64_defs.h +++ /dev/null @@ -1,576 +0,0 @@ -/* - *------------------------------------------------------------------ - * nat64_defs.h - NAT64 structure definiitions - * - * Copyright (c) 2007-2013 Cisco and/or its affiliates. - * 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 __NAT64_DEFS_H__ -#define __NAT64_DEFS_H__ - -#ifdef TOBE_PORTED -#include "spp_platform_common.h" -#include "cgse_defs.h" -#include "xlat_defs.h" -#endif -#include "cnat_cli.h" -#include "cnat_ports.h" -#include "tcp_header_definitions.h" -#include "nat64_tcp_sm.h" -#include "cnat_db.h" - -#define NAT64_MAX_FRAG_ID_COUNTERS (256) - -#define NAT64_MAX_NAT64_ENTRIES 500 - -#define NAT64_MAX_ID (NAT64_MAX_NAT64_ENTRIES-1) - -#define NAT64_INVALID_ID (0) - -#define NAT64_MAX_CFG_INSTANCES 64 - -#define NAT64_TABLE_ENTRY_DELETED 0 -#define NAT64_TABLE_ENTRY_ACTIVE 1 -#define NAT64_TABLE_ENTRY_DORMANT 2 -#define NAT64_TABLE_ENTRY_INVALID_UIDB 3 - -#define NAT64_MAX_TRANSLATION_ENTRIES PLATFORM_MAX_TRANSLATION_ENTRIES - -#define NAT64_WKP_PREFIX_LEN 96 -#define NAT64_WKP_PREFIX_0 0x0064FF9B -#define NAT64_WKP_PREFIX_1 0x00000000 -#define NAT64_WKP_PREFIX_2 0x00000000 -#define NAT64_WKP_PREFIX_3 0x00000000 - - -/* Reset the expiry time only if it is not 0 -** if it is 0 - then queue for delete by clear command -**/ - -#define NAT64_TIMEOUT_RST(db) \ - if(PREDICT_TRUE(db->entry_expires !=0 )) \ - db->entry_expires = cnat_current_time; - -extern u32 nat64_config_debug_level; -extern u32 nat64_data_path_debug_level; - -extern u32 nat64_translation_create_count[NAT64_MAX_NAT64_ENTRIES]; -extern u32 nat64_translation_delete_count[NAT64_MAX_NAT64_ENTRIES]; -extern u32 nat64_translation_create_rate[NAT64_MAX_NAT64_ENTRIES]; -extern u32 nat64_translation_delete_rate[NAT64_MAX_NAT64_ENTRIES]; -extern u32 nat64_in2out_forwarding_count[NAT64_MAX_NAT64_ENTRIES]; -extern u32 nat64_in2out_forwarding_rate[NAT64_MAX_NAT64_ENTRIES]; -extern u32 nat64_out2in_forwarding_count[NAT64_MAX_NAT64_ENTRIES]; -extern u32 nat64_out2in_forwarding_rate[NAT64_MAX_NAT64_ENTRIES]; - -extern u32 nat64_translation_create_count_old[NAT64_MAX_NAT64_ENTRIES]; -extern u32 nat64_translation_delete_count_old[NAT64_MAX_NAT64_ENTRIES]; -extern u32 nat64_in2out_forwarding_count_old[NAT64_MAX_NAT64_ENTRIES]; -extern u32 nat64_out2in_forwarding_count_old[NAT64_MAX_NAT64_ENTRIES]; - -extern u16 *nat64_frag_id_counter_ptr; - -typedef struct { - u64 v6_to_v4_tcp_input_count; - u64 v6_to_v4_tcp_non_translatable_drop_count; - u64 v6_to_v4_tcp_state_drop_count; - u64 v6_to_v4_tcp_no_db_drop_count; - u64 v6_to_v4_tcp_output_count; -} nat64_v6_to_v4_tcp_counter_t; - -typedef struct { - u64 v4_to_v6_tcp_input_count; - u64 v4_to_v6_tcp_no_db_drop_count; - u64 v4_to_v6_tcp_v4_init_policy_drop_count; - u64 v4_to_v6_tcp_state_drop_count; - u64 v4_to_v6_tcp_output_count; - u64 v4_to_v6_tcp_filter_drop_count; -} nat64_v4_to_v6_tcp_counter_t; - -typedef struct { - u64 v6_to_v4_udp_input_count; - u64 v6_to_v4_udp_non_translatable_drop_count; - u64 v6_to_v4_udp_no_db_drop_count; - u64 v6_to_v4_udp_output_count; - u64 v6_to_v4_udp_checksum_zero_count; -} nat64_v6_to_v4_udp_counter_t; - -typedef struct { - u64 v4_to_v6_udp_input_count; - u64 v4_to_v6_udp_no_db_drop_count; - u64 v4_to_v6_udp_filter_drop_count; - u64 v4_to_v6_udp_output_count; - u64 v4_to_v6_udp_crc_zero_drop_count; - u64 v4_to_v6_udp_frag_crc_zero_drop_count; - u64 v4_to_v6_udp_crc_zero_recycle_sent_count; - u64 v4_to_v6_udp_crc_zero_recycle_drop_count; -} nat64_v4_to_v6_udp_counter_t; - -typedef struct { - u64 v6_to_v4_icmp_input_count; - u64 v6_to_v4_icmp_no_db_drop_count; - u64 v6_to_v4_icmp_non_translatable_drop_count; - u64 v6_to_v4_icmp_qry_output_count; -} nat64_v6_to_v4_icmp_counter_t; - -typedef struct { - u64 v4_to_v6_icmp_input_count; - u64 v4_to_v6_icmp_no_db_drop_count; - u64 v4_to_v6_icmp_filter_drop; - u64 v4_to_v6_icmp_qry_output_count; -} nat64_v4_to_v6_icmp_counter_t; - -typedef struct { - u64 v6_to_v4_icmp_error_input_count; - u64 v6_to_v4_icmp_error_no_db_drop_count; - u64 v6_to_v4_icmp_error_invalid_next_hdr_drop_count; - u64 v6_to_v4_icmp_error_non_translatable_drop_count; - u64 v6_to_v4_icmp_error_unsupported_type_drop_count; - u64 v6_to_v4_icmp_error_output_count; -} nat64_v6_to_v4_icmp_error_counter_t; - -typedef struct { - u64 v4_to_v6_icmp_error_input_count; - u64 v4_to_v6_icmp_error_no_db_drop_count; - u64 v4_to_v6_icmp_error_unsupported_type_drop_count; - u64 v4_to_v6_icmp_error_unsupported_protocol_drop_count; - u64 v4_to_v6_icmp_error_output_count; -} nat64_v4_to_v6_icmp_error_counter_t; - - - -typedef struct { - u64 nat64_v4_frag_input_count; - u64 nat64_v4_frag_forward_count; - u64 nat64_v4_frag_drop_count; - u64 nat64_v4_frag_throttled_count; - u64 nat64_v4_frag_timeout_drop_count; - u64 nat64_v4_frag_tcp_input_count; - u64 nat64_v4_frag_udp_input_count; - u64 nat64_v4_frag_icmp_input_count; - - u64 nat64_v6_frag_input_count; - u64 nat64_v6_frag_forward_count; - u64 nat64_v6_frag_drop_count; - u64 nat64_v6_frag_throttled_count; - u64 nat64_v6_frag_timeout_drop_count; - u64 nat64_v6_frag_tcp_input_count; - u64 nat64_v6_frag_udp_input_count; - u64 nat64_v6_frag_icmp_input_count; - u64 nat64_v6_frag_invalid_input_count; -} nat64_frag_counter_t; - -typedef struct { - u64 v6_to_v4_options_input_count; - u64 v6_to_v4_options_drop_count; - u64 v6_to_v4_options_forward_count; - u64 v6_to_v4_options_no_db_drop_count; - u64 v6_to_v4_unsupp_proto_count; - - u64 v4_to_v6_options_input_count; - u64 v4_to_v6_options_drop_count; - u64 v4_to_v6_options_forward_count; - u64 v4_to_v6_options_no_db_drop_count; - u64 v4_to_v6_unsupp_proto_count; -} nat64_options_counter_t; - -typedef struct { - u64 v4_icmp_gen_count; - u64 v6_icmp_gen_count; -} nat64_icmp_gen_counter_t; - -typedef struct{ - u32 nat64_num_translations; - u32 nat64_num_dynamic_translations; - u32 nat64_num_static_translations; - u32 nat64_sessions; - u64 nat64_port_limit_exceeded; - u64 nat64_system_limit_reached; - u64 nat64_resource_depletion_drops; - u64 nat64_no_translation_entry_drops; - u64 nat64_filtering_drops ; - u64 nat64_invalid_ipv6_prefix_drops; - u32 num_subscribers; - u32 dummy; - u64 drops_sessiondb_limit_exceeded; -} nat64_inst_gen_counter_t; - -typedef struct { - - nat64_v6_to_v4_tcp_counter_t v64_tcp_counters; - nat64_v4_to_v6_tcp_counter_t v46_tcp_counters; - nat64_v6_to_v4_udp_counter_t v64_udp_counters; - nat64_v4_to_v6_udp_counter_t v46_udp_counters; - nat64_v6_to_v4_icmp_counter_t v64_icmp_counters; - nat64_v4_to_v6_icmp_counter_t v46_icmp_counters; - nat64_v6_to_v4_icmp_error_counter_t v64_icmp_error_counters; - nat64_v4_to_v6_icmp_error_counter_t v46_icmp_error_counters; - nat64_frag_counter_t nat64_frag_counters; - nat64_options_counter_t nat64_options_counters; - nat64_icmp_gen_counter_t nat64_icmp_gen_counters; - -} nat64_counters_t; - -/* - * nat64_portmap_v2_t - * This structure stores information about the IP address and ports - * available for NAT for this nat64 instance. - */ - -typedef struct { - u32 delete_time; - u32 last_sent_timestamp; - u32 inuse; - u32 ipv4_address; /* native bit order */ - uword bm[(BITS_PER_INST + BITS(uword)-1)/BITS(uword)]; -} nat64_portmap_t; - -/* - * nat64_v4_db_key_t - * This structure gives information about the v4 transport address - * (ipv4, port, protocol) - */ -typedef struct { - u32 ipv4; - u16 port; - u16 vrf; //bit0-12:inst_id, bit13:unused, bit14-15:protocol -} nat64_v4_db_key_t; - -/* Union will be easier while compare/hash */ -typedef union { - nat64_v4_db_key_t k; - u64 key64; -} nat64_v4_key_t; -/* - * nat64_v6_db_key_t - * This structure gives information about the v6 transport address - * (ipv6, port, protocol) - */ -typedef struct { - u32 ipv6[4]; - u16 port; - u16 vrf; //bit0-12:inst_id, bit13:unused, bit14-15:protocol -} nat64_v6_key_t; - - -typedef struct { - u16 udp_timeout; - u16 tcp_trans_timeout; - u16 tcp_est_timeout; - u16 tcp_v4_init_timeout; - u16 frag_timeout; - u16 icmp_timeout; -} nat64_timeout_info_t; - -#define NAT64_UDP_DEF 300 /* 5min */ -#define NAT64_TCP_TRANS_DEF 240 /* 4min */ -#define NAT64_TCP_EST_DEF 7200 /* 2Hrs */ -#define NAT64_TCP_V4_DEF 6 /* 6 sec */ -#define NAT64_FRAG_DEF 2 /* 2 sec */ -#define NAT64_ICMP_DEF 60 /* 60 sec */ - -/* - * nat64_table_entry_t - * This structure is used to store information regarding every nat64 instance. - */ - -/* structure will hold the L4 information, of a particular frag stream set - * src_port - holds the original src port - * dst_port - holds the original dst port - * total_len - useful only in ICMP nodes - * cnat_port - vlaue used for looksups - * next_prot - Protocol after translation */ - -typedef struct l4_frag_info { - u16 next_node_idx; - u16 src_port; - u16 dst_port; - u16 total_length; - u8 protocol; - u16 cnat_prot; - u16 next_prot; -} l4_frag_info_t; - -typedef struct { - u16 state; - u16 nat64_id; /* nat64_id value for this table entry - for easy access */ - - u16 v4_uidb_index; /* V4 uidb index */ - u16 v6_uidb_index; /* V6 uidb index */ - - u8 octet0_position; - u8 octet1_position; - u8 octet2_position; - u8 octet3_position; - - u16 v4_to_v6_tcp_mss; /* TCP MSS */ - u16 v6_to_v4_tcp_mss; /* TCP MSS */ - - /* - * V6 NAT64 prefix value and mask size - */ - u32 v6_prefix[4]; - u32 v6_prefix_mask[4]; - - u8 v6_prefix_mask_len; - u8 ubits_reserved_on; -#define IPV4_TOS_OVERRIDE_FLAG 0x1 -#define IPV6_TOS_OVERRIDE_FLAG 0x2 -#define NAT64_STFUL_RTSP_ALG_ENABLE 0x4 - u8 feature_flags; - - u8 ipv4_tos_value; - u8 ipv6_tos_value; - u8 df_bit_clear; - u8 ipv6_mtu_set; - - u8 filtering_policy; -#define NAT64_ADDRESS_DEPENDENT_ENABLE 1 - u8 tcp_policy; -#define NAT64_TCP_SECURITY_FLAG_DISABLE 1 - u8 ftp_flags; - - u8 tcp_v4_init_enable; -#define NAT64_TCP_V4_INIT_ENABLE 1 - - u8 logging_policy; -#define NAT64_BIB_LOG_ENABLE 0 /* Default */ -#define NAT64_SESSION_LOG_ENABLE 1 - -#define NAT64_BIDIR_REFRESH 1 /* 1 - timer refresh in both direction */ -#define NAT64_UNIDIR_REFRESH 0 /* 0 - default (only v6 side refresh timer)*/ - - u8 nat64_refresh_both_direction; /* 0 - default (only v6 side refresh timer) */ -#define NAT64_BIDIR_REFRESH 1 /* 1 - timer refresh in both direction */ - - u8 udp_zero_checksum; /* 0 - default (calc checksum) */ -#define NAT64_UDP_ZERO_CHECKSUM_DROP 1 /* 1 -drop */ - - u16 port_limit; - - cnat_portmap_v2_t *port_map; - - u32 logging_index; - - nat64_timeout_info_t timeout_info; - /* - * These fields are not used much, let us keep it in the end - */ - u32 v4_vrf_id; /* V4 vrf id */ - u32 v6_vrf_id; /* V6 vrf id */ - - u32 v4_if_num; /* V4 SVI ifnum */ - u32 v6_if_num; /* V6 SVI ifnum */ - - u16 dyn_start_port; - - u16 pcp_server_port; - u32 pcp_server_addr[4]; - u32 rseed_ip; -#define NAT64_FRAG_ENABLE 1 -#define NAT64_FRAG_DISABLE 0 - u8 frag_state; - u8 nat64_enable; /* Enable/Disable this instance. */ - - u16 rtsp_port; - -} nat64_table_entry_t; - - - -extern nat64_table_entry_t nat64_table_array[NAT64_MAX_NAT64_ENTRIES]; -extern nat64_table_entry_t *nat64_table_ptr; -extern nat64_counters_t nat64_all_counters[NAT64_MAX_NAT64_ENTRIES]; -extern nat64_inst_gen_counter_t nat64_inst_gen_counters[NAT64_MAX_NAT64_ENTRIES]; - -typedef struct nat64_common_pipeline_data_ { -#ifdef TOBE_PORTED - spp_node_main_vector_t *nmv; -#endif - - u16 *nat64_id_ptr; - - nat64_table_entry_t *nat64_entry_ptr; - -} nat64_common_pipeline_data_t; - -typedef struct nat64_v6_to_v4_pipeline_data_ { - nat64_common_pipeline_data_t common_data; - - u32 bib_bucket; - u32 session_bucket; - - nat64_v6_key_t v6_in_key; - nat64_v6_key_t v6_dest_key; - - /* - * IPv6 Data, everthing in host order except for the addr fields - */ - u32 version_trafficclass_flowlabel; - - u16 payload_length; - u8 next_header; - u8 hop_limit; - - /* - * These Address fields are in Network Order, so that - * it is easy to extract the IPv4 address from them - */ - u32 ipv6_src[4]; - - u32 ipv6_dst[4]; - - u8 frag_next_header; - u8 frag_reserved; - u16 frag_offset_res_m; - u32 frag_identification; - - ipv4_header *ipv4_header; - union { - struct _v4_l4_info { - u8 *ipv4_l4_header; - u8 pad0; - u8 pad1; - u8 pad2; - u8 pad3; - } v4_l4_info; - struct _v4_icmp_info { - icmp_v4_t *ipv4_icmp_header; - u8 old_icmp_type; - u8 new_icmp_type; - u8 old_icmp_code; - u8 new_icmp_code; - u16 checksum; - u16 old_iden; // length (ICMP extn), ptr (param) - u16 new_iden; // ----- do ------------- - u16 old_seq; // MTU for PTB case - u16 new_seq; // ----- do ------------- - } v4_icmp_info; - struct _v4_udp_info { - udp_hdr_type_t *ipv4_udp_header; - u8 pad0; - u8 pad1; - u8 pad2; - u8 pad3; - } v4_udp_info; - struct _v4_tcp_info { - tcp_hdr_type *ipv4_tcp_header; - u16 old_src_port; - u16 new_src_port; - u16 dest_port; - nat64_tcp_events tcp_event; - } v4_tcp_info; - } l4_u; - - - l4_frag_info_t *frag_info; /* port for tcp/udp, ident - icmp */ - - - /* Counters will be added here */ - union { - nat64_v6_to_v4_tcp_counter_t *tcp_counter; - nat64_v6_to_v4_udp_counter_t *udp_counter; - nat64_v6_to_v4_icmp_counter_t *icmp_counter; - nat64_v6_to_v4_icmp_error_counter_t *icmp_error_counter; - nat64_frag_counter_t *frag_counter; - nat64_options_counter_t *options_counter; - } nat64_ctr_u; - nat64_icmp_gen_counter_t *icmp_gen_counter; -} nat64_v6_to_v4_pipeline_data_t; - - -typedef struct nat64_v4_to_v6_pipeline_data_ { - nat64_common_pipeline_data_t common_data; - - u32 bib_bucket; - u32 session_bucket; - - nat64_v4_key_t v4_src_key; /* Will be translated using Prefix */ - nat64_v4_key_t v4_dest_key; /* will be the out key for NAT64 */ - - /* - * IPv4 data - */ - u8 version_hdr_len_words; - u8 tos; - u16 total_len_bytes; - - u16 identification; - u16 frag_flags_offset; - - u8 ttl; - u8 protocol; - u16 l4_checksum; - - u32 ipv4_src_addr; - u32 ipv4_dst_addr; - - /* - * Pointers to IPv6 headers - */ - ipv6_header_t *ipv6_header; - ipv6_frag_header_t *ipv6_frag_header; - - union { - struct _v6_l4_info { - u8 *ipv6_l4_header; - u8 pad0; - u8 pad1; - u8 pad2; - u8 pad3; - } v6_l4_info; - struct _v6_icmp_info { - icmp_v6_t *ipv6_icmp_header; - u8 old_icmp_type; - u8 new_icmp_type; - u8 old_icmp_code; - u8 new_icmp_code; - u16 old_iden; // length (ICMP extn), ptr (param) - u16 new_iden; // ----- do ------------- - u16 old_seq; // MTU for PTB case - u16 new_seq; // ----- do ------------- - } v6_icmp_info; - struct _v6_udp_info { - udp_hdr_type_t *ipv6_udp_header; - u8 pad0; - u8 pad1; - u8 pad2; - u8 pad3; - } v6_udp_info; - struct _v6_tcp_info { - tcp_hdr_type *ipv6_tcp_header; - u16 old_dest_port; - u16 new_dest_port; - u16 src_port; - nat64_tcp_events tcp_event; - } v6_tcp_info; - } l4_u; - - l4_frag_info_t *frag_info; /* port for tcp/udp, ident - icmp */ - - /* Need to add counters here */ - union { - nat64_v4_to_v6_tcp_counter_t *tcp_counter; - nat64_v4_to_v6_udp_counter_t *udp_counter; - nat64_v4_to_v6_icmp_counter_t *icmp_counter; - nat64_v4_to_v6_icmp_error_counter_t *icmp_error_counter; - nat64_frag_counter_t *frag_counter; - nat64_options_counter_t *options_counter; - } nat64_ctr_u; - nat64_icmp_gen_counter_t *icmp_gen_counter; - -} nat64_v4_to_v6_pipeline_data_t; - -#endif diff --git a/plugins/plugins/vcgn/nat64_tcp_sm.h b/plugins/plugins/vcgn/nat64_tcp_sm.h deleted file mode 100644 index 3a505bc1..00000000 --- a/plugins/plugins/vcgn/nat64_tcp_sm.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - *------------------------------------------------------------------ - * nat64_tcp_sm.h - Stateful NAT64 translation TCP State machine - * - * Copyright (c) 2011 Cisco and/or its affiliates. - * 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 __NAT64_TCP_SM_H__ -#define __NAT64_TCP_SM_H__ - - -/* TCP States */ -typedef enum { - TCP_CLOSED, - TCP_V4_INIT, - TCP_V6_INIT, - TCP_ESTABLISHED, - TCP_V4_FIN_RCV, - TCP_V6_FIN_RCV, - TCP_V4V6_FIN_RCV, - TCP_TRANS, - TCP_NONE -} nat64_tcp_states; - -/* TCP Events */ -typedef enum { - TCP_TIMEOUT_EV, - TCP_V6_SYN_EV, - TCP_V4_SYN_EV, - TCP_V6_FIN_EV, - TCP_V4_FIN_EV, - TCP_V6_RST_EV, - TCP_V4_RST_EV, - TCP_DEFAULT_EV, - TCP_EV_COUNT -} nat64_tcp_events; - -/* TCP Actions */ -typedef enum { - TCP_FORWARD, - TCP_COND_FORWARD, /* Conditional forward, based on presence of - * session and bib entries */ - TCP_STORE, - TCP_PROBE, - TCP_CREATE_SESSION, - TCP_DELETE_SESSION, - TCP_DROP, - TCP_ACTION_NONE, - TCP_ACTION_COUNT -} nat64_tcp_actions; - -typedef struct { - nat64_tcp_states next_state; - nat64_tcp_actions action; -} nat64_tcp_trans_t; - -typedef struct { - nat64_tcp_trans_t event[TCP_EV_COUNT]; -} nat64_tcp_state_trans_t; - -extern nat64_tcp_state_trans_t nat64_tcp_sm_lookup[TCP_NONE]; - -/* -inline void -nat64_update_v6_to_v4_tcp (nat64_v6_to_v4_pipeline_data_t *pctx_ptr, - nat64_bib_entry_t *bib_ptr); - -inline u8 nat64_v6_to_v4_tcp_perform_action ( - spp_ctx_t *ctx, - nat64_v6_to_v4_pipeline_data_t *pctx_ptr, - nat64_bib_entry_t *bib_db, - nat64_session_entry_t *session_db); - -inline void -nat64_copy_tcp_into_pctx (nat64_v6_to_v4_pipeline_data_t *pctx_ptr); -*/ - - - -#endif diff --git a/plugins/plugins/vcgn/platform_common.h b/plugins/plugins/vcgn/platform_common.h deleted file mode 100644 index 2805b607..00000000 --- a/plugins/plugins/vcgn/platform_common.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - *--------------------------------------------------------------------------- - * platform_common.h -- file has all platform related macros defined as NULL - * included "platform_common_override.h will have actual - * platform specific defines - * - * Copyright (c) 2011-2013 Cisco and/or its affiliates. - * 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 __PLATFORM_COMMON_H__ -#define __PLATFORM_COMMON_H__ - -/* $$$ FIXME causes printf format warnings */ -#define PLATFORM_DEBUG_PRINT(...) /* printf(__VA_ARGS__) */ -#define PLATFORM_FILL_DST_ADDR_PORT_TABLE -#define PLATFORM_SET_CTX_RU_TX_FROM_NODE(ctx, value) -#define PLATFORM_SET_CTX_RU_TX_DST_IPPORT_IDX(ctx, value) -#define PLATFORM_SET_CTX_RU_TX_PKT_TYPE(ctx, type) -#define PLATFORM_SET_RX_VRF(ctx, rx_vrf, hardcode, mask) -#define PLATFORM_SET_TX_VRF(ctx, tx_vrf) -/* PLATFORM_CNAT_SET_RX_VRF definition is not same as PLATFORM_SET_RX_VRF, - * So, maintaining two different definitions - */ -#define PLATFORM_CNAT_SET_RX_VRF(ctx, rx_vrf, proto) -#define PLATFORM_CNAT_SET_TX_VRF(ctx, tx_vrf) - -#define PLATFORM_PRINT_TESTING_PG() -#define PLATFORM_INIT_TEMP_SENSORS() -#define PLATFORM_READ_CPU_SENSORS(value) -#define PLATFORM_SET_TEMP_READ_BLOCK(var, val) -#define PLATFORM_NFV9_DISP_NODE_IDX - - -/* Assumption is, syslog packets - * are sent out via same channel as that of NFV9. - * Has to be overridden if this assumption is false. - */ -#define PLATFORM_SYSLOG_DISP_NODE_IDX PLATFORM_NFV9_DISP_NODE_IDX - -#define PLATFORM_CNAT_DB_DUMP_POLICY_PRINT() -#define PLATFORM_PRINT_CTX_VALUES(ctx) -#define PLATFORM_ADD_VRF_MAP_HANDLE_PARTITION(uidb_index, partition_id) -#define PLATFORM_DEL_VRF_MAP_HANDLE_PARTITION(uidb_index, partition_id) -#define PLATFORM_ALLOC_NFV9_PKT_BUFFER(ctx, to_lc_cpu) -#define PLATFORM_SET_DSLITE_ENABLE_FLAG(uidb_index, dslite_id) -#define PLATFORM_CHECK_DSLITE_ENABLE_FLAG - -#define PLATFORM_CNAT_INSTS 1 -#define PLATFORM_HANDLE_TTL_DECREMENT 0 // Don't handle TTL in NAT44 Application (default). - -// For ISM, we need to copy the ipv6->hop_limit to ipv4 ttl. -#define PLATFORM_6RD_COPY_TTL_IPV6_TO_IPV4 0 - -//For ISM case, need to allow as the TTL decrement happens at ingress LC -#define PLATFORM_6RD_ALLOW_TTL_1 0 - -#define PLATFORM_HANDLE_ICMP_TTL_EXPIRED 0 // Don't handle ICMP_ERROR msg for TTL <=1 in NAT44 App (default). - -#define PLATFORM_IPV4_FRAG_FRAG_HOLD_LIMIT 1 -#define PLATFORM_MAX_IPV4_CTX_ENTRIES 1 -#define PLATFORM_MAPE_FRAG 0 - -#define PLATFORM_ADDR_MASK_PER_CORE 0 -#define PLATFORM_ADDR_MASK_PER_CORE_PER_PARTITION 0 -#define PLATFORM_MAX_CORES 1 -#define PLATFORM_MAX_CORES_PER_PARTITION 1 -#define PLATFORM_MAX_NAT_ENTRIES 1 -#define PLATFORM_MAX_USER_ENTRIES 1 -#define PLATFORM_CNAT_MAX_ADDR_POOL_SIZE 0x1 -#define PLATFORM_DBL_SUPPORT 0 /* Default no DBL support, no NAT44 session table */ - -#define PLATFORM_MAX_DB_ENTRY_PER_SCAN 1 -#define PLATFORM_MAX_DB_ENTRY_SELECTED_PER_SCAN 1 -#define MAX_COMBINED_DB_ENTRIES_PER_SCAN 0 - -#define PLATFORM_CNAT_TIMEOUT_IPPROT_MASK 0 -#define PLATFORM_CNAT_TIMEOUT_PORTPROT_MASK 0 - -#define PLATFORM_MAX_SHOW_BUFFER_SIZE 1700 -#define PLATFORM_MAX_TRANSLATION_ENTRIES (50) -#define PLATFORM_MAX_UTIL_ENTRIES (100) -#define PLATFORM_MAX_NAT44_UTIL_ENTRIES ((64)/PLATFORM_MAX_CORES) - -#define PLATFORM_CNAT_NFV9_SHIM_HDR_OFFSET 0 -#define PLATFORM_CNAT_NFV9_L2_ENCAPS_OFFSET 0 - - -/* Below are nat64 statful related define */ -#define PLATFORM_NAT64_SET_RX_VRF(rx_vrf, proto, inst_id) \ - rx_vrf = proto | (inst_id & CNAT_VRF_MASK); - -#define PLATFORM_NAT64_MAX_TRANSLATION_ENTRIES (30) -#define PLATFORM_DS_LITE_MAX_TRANSLATION_ENTRIES (30) - -#define PLATFORM_SET_NAT64_ENABLE_FLAG(uidb_index, nat64_id) \ - { \ - nat64_set_enable_flag(nat64_id, ENABLE); \ - } - -#define PLATFORM_CHECK_NAT64_ENABLE_FLAG 1 -#define PLATFORM_SET_MAPE_ENABLE_FLAG(uidb_index, mape_id) -#define PLATFORM_CHECK_MAPE_ENABLE_FLAG 1 - -/* very small number , PD has correct value. - this is bcoz, if platform doesnt support nat64..shudnt take too much..*/ -#define PLATFORM_NAT64_MAX_SESSIONS 10 -#define PLATFORM_NAT64_TIMEOUT_HASH_SIZE 10 -#define PLATFORM_MAP_ADDR_PER_CORE 1024 - -#define ENABLE 1 -#define DISABLE 0 - -/* Platform Xlat inline learn function */ -#define PLATFORM_INLINE_LEARN_FUNC(a,b,c) - - -/* Checksum calculation to be done in software */ -#define PLATFORM_XLAT_SW_CHECKSUM_CALC 0 - - -/* Below include overrides all the above null defs and defines platform specific - define */ -#include "platform_common_override.h" - -#endif /* __PLATFORM_COMMON_H__ */ diff --git a/plugins/plugins/vcgn/platform_common_override.h b/plugins/plugins/vcgn/platform_common_override.h deleted file mode 100644 index d6d3b078..00000000 --- a/plugins/plugins/vcgn/platform_common_override.h +++ /dev/null @@ -1,304 +0,0 @@ -/* - *--------------------------------------------------------------------------- - * platform_common_override.h -- Files has actual platform specific defines. - * Will only included by platform_common.h - * - * Copyright (c) 2011-2013 Cisco and/or its affiliates. - * 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 __PLATFORM_COMMON_OVERRIDE_H__ -#define __PLATFORM_COMMON_OVERRIDE_H__ - -extern unsigned char my_octeon_id; - -#undef PLATFORM_DBL_SUPPORT -#define PLATFORM_DBL_SUPPORT 1 // Destination Based logging support - // NAT44 session table required. - -#undef PLATFORM_ADDR_MASK_PER_CORE -/* commenting this. Currently we are considering only single core */ -//#define PLATFORM_ADDR_MASK_PER_CORE 0x3f // Using 64 cores -#define PLATFORM_ADDR_MASK_PER_CORE 0x01 - -#undef MAX_COMBINED_DB_ENTRIES_PER_SCAN -#define MAX_COMBINED_DB_ENTRIES_PER_SCAN 128 - -#undef PLATFORM_MAX_CORES -#define PLATFORM_MAX_CORES (PLATFORM_ADDR_MASK_PER_CORE + 1) - -// Roddick does not have any partition of cores -#undef PLATFORM_ADDR_MASK_PER_CORE_PER_PARTITION -#define PLATFORM_ADDR_MASK_PER_CORE_PER_PARTITION \ - PLATFORM_ADDR_MASK_PER_CORE - -#undef PLATFORM_MAX_CORES_PER_PARTITION -#define PLATFORM_MAX_CORES_PER_PARTITION PLATFORM_MAX_CORES - -#undef PLATFORM_CNAT_INSTS -//#define PLATFORM_CNAT_INSTS 64 -#define PLATFORM_CNAT_INSTS 1 /* currently its only single instance */ - -#undef PLATFORM_MAX_NAT_ENTRIES -//#define PLATFORM_MAX_NAT_ENTRIES 20000000 // 20M -#define PLATFORM_MAX_NAT_ENTRIES 1666660 // ~80M/48 (79999680/48) - -#undef PLATFORM_MAX_USER_ENTRIES -#define PLATFORM_MAX_USER_ENTRIES 20800 // ~1M/48 (998400/48) - - -/* 524288: - (20000000 translations) / (64 CNAT INSTANCES) = 312500 - nearest higher number which is power of 2 next to 312500 -*/ -#undef PLATFORM_CNAT_MAIN_PRELIM_HASH_SIZE -//#define PLATFORM_CNAT_MAIN_PRELIM_HASH_SIZE 524288 -#define PLATFORM_CNAT_MAIN_PRELIM_HASH_SIZE (5<<20) -/* 4096: - (200000 users) / (64 CNAT INSTANCES) = 3125 - nearest higher number which is power of 2 next to 3125 -*/ -#undef PLATFORM_CNAT_USER_PRELIM_HASH_SIZE -#define PLATFORM_CNAT_USER_PRELIM_HASH_SIZE 4096 - -#undef PLATFORM_CNAT_MAX_ADDR_POOL_SIZE -#define PLATFORM_CNAT_MAX_ADDR_POOL_SIZE 0x10000 // max /16 - -#undef PLATFORM_MAX_DB_ENTRY_PER_SCAN -#define PLATFORM_MAX_DB_ENTRY_PER_SCAN 400 - -#undef PLATFORM_MAX_DB_ENTRY_SELECTED_PER_SCAN -#define PLATFORM_MAX_DB_ENTRY_SELECTED_PER_SCAN 100 // 1/4th of above - -#undef PLATFORM_CNAT_TIMEOUT_IPPROT_MASK -#define PLATFORM_CNAT_TIMEOUT_IPPROT_MASK 0xFFFFFFFF0000FFFF - -#undef PLATFORM_CNAT_TIMEOUT_PORTPROT_MASK -#define PLATFORM_CNAT_TIMEOUT_PORTPROT_MASK 0x00000000FFFFFFFF - -#ifdef TARGET_RODDICK /* EVB doesnt need it */ -#undef PLATFORM_FILL_DST_ADDR_PORT_TABLE -#define PLATFORM_FILL_DST_ADDR_PORT_TABLE fill_dst_addr_port_table(); -#endif - - -#ifndef RODDICK_ON_LINUX_OR_EVB -#undef PLATFORM_SET_CTX_RU_TX_FROM_NODE -#undef PLATFORM_SET_CTX_RU_TX_DST_IPPORT_IDX -#undef PLATFORM_SET_CTX_RU_TX_PKT_TYPE - -#define PLATFORM_SET_CTX_RU_TX_FROM_NODE(ctx, value) \ - (vnet_buffer(ctx))->vcgn_uii.ru.tx.from_node = value; -#define PLATFORM_SET_CTX_RU_TX_DST_IPPORT_IDX(ctx, value) \ - (vnet_buffer(ctx))->vcgn_uii.ru.tx.dst_ip_port_idx = value; -#define PLATFORM_SET_CTX_RU_TX_PKT_TYPE(ctx, type) \ - (vnet_buffer(ctx))->vcgn_uii.ru.tx.packet_type = type; -#endif - -#undef PLATFORM_SET_RX_VRF -#undef PLATFORM_SET_TX_VRF -#ifdef TARGET_RODDICK -#define PLATFORM_SET_RX_VRF(ctx, rx_vrf, hardcode, mask) \ - rx_vrf = (ctx->ru.rx.uidb_index & CNAT_VRF_MASK); -#define PLATFORM_SET_TX_VRF(ctx, tx_vrf) \ - ctx->ru.tx.uidb_index = tx_vrf; -#else /*EVB */ -#define PLATFORM_SET_RX_VRF(ctx, rx_vrf, hardcode, mask) \ - rx_vrf = hardcode; -#define PLATFORM_SET_TX_VRF(ctx, tx_vrf) -#endif - -#undef PLATFORM_CNAT_SET_RX_VRF -#undef PLATFORM_CNAT_SET_TX_VRF - -#define PLATFORM_CNAT_SET_RX_VRF(if_index, rx_vrf, proto) \ - rx_vrf = proto | ((if_index) & CNAT_VRF_MASK); - -#define PLATFORM_CNAT_SET_TX_VRF(if_index, tx_vrf) \ - (if_index) = ((tx_vrf) & CNAT_VRF_MASK); - - - -#undef PLATFORM_NAT64_SET_RX_VRF - -#ifdef TARGET_RODDICK - -#define PLATFORM_NAT64_SET_RX_VRF(rx_vrf, proto, inst_id) \ - rx_vrf = proto | (inst_id & CNAT_VRF_MASK); - -#else /* EVB */ - -#define PLATFORM_NAT64_SET_RX_VRF(rx_vrf, proto, inst_id) \ - rx_vrf = proto | inst_id; - -#endif - -#ifdef TARGET_EVB -#define VRF_MAP_CONFIG -#endif - -#undef PLATFORM_PRINT_TESTING_PG -#if defined(TARGET_LINUX_UDVR) || defined(CNAT_PG) -#define PLATFORM_PRINT_TESTING_PG() printf("testing pg\n"); -#else -#define PLATFORM_PRINT_TESTING_PG() -#endif - -#ifdef TARGET_RODDICK -#undef PLATFORM_INIT_TEMP_SENSORS -#undef PLATFORM_READ_CPU_SENSORS -#undef PLATFORM_SET_TEMP_READ_BLOCK - -#define PLATFORM_INIT_TEMP_SENSORS() Init_temperature_sensors(); -#define PLATFORM_READ_CPU_SENSORS(value) read_octeon_sensors(value); -#define PLATFORM_SET_TEMP_READ_BLOCK(var, val) var = &val->param[0]; -#endif - -#undef PLATFORM_HANDLE_ICMP_TTL_EXPIRED -#define PLATFORM_HANDLE_ICMP_TTL_EXPIRED 1 // handle TTL in NAT44 Application (for AVSM) - -#undef PLATFORM_NFV9_DISP_NODE_IDX -#ifdef TARGET_RODDICK -#define PLATFORM_NFV9_DISP_NODE_IDX "roddick_infra_l3_tx" -#else /* EVB */ -#define PLATFORM_NFV9_DISP_NODE_IDX "cnat_rewrite_output" -#endif - -#undef PLATFORM_CNAT_DB_DUMP_POLICY_PRINT -#define PLATFORM_CNAT_DB_DUMP_POLICY_PRINT() \ - printf("my instance:%d\n" \ - "icmp timeout %d udp init timeout %d act timeout %d\n" \ - "tcp init timeout %d act timeout %d mapping refresh %d\n" \ - "port limit per user %d ftp alg %d lb debug %d\n" \ - "icmp rate limit 0x%x config delete timer 0x%x\n" \ - "global debug flag 0x%x\n" \ - "icmp rate limit (pkts/per sec) %d\n" \ - "dynamic port range start %d\n" \ - "debug ivrf 0x%x flag 0x%x start_addr 0x%x end_addr 0x%x\n" \ - "debug ovrf 0x%x flag 0x%x start_addr 0x%x end_addr 0x%x\n", \ - my_instance_number, \ - icmp_session_timeout, udp_init_session_timeout, udp_act_session_timeout, \ - tcp_initial_setup_timeout, tcp_active_timeout, \ - mapping_refresh_both_direction, cnat_main_db_max_ports_per_user, \ - ftp_alg_enabled, lb_debug_enable, per_user_icmp_msg_limit, \ - config_delete_timeout, \ - global_debug_flag, \ - cnat_main_db_icmp_rate_limit, \ - cnat_static_port_range, \ - debug_i_vrf, debug_i_flag, debug_i_addr_start, debug_i_addr_end, \ - debug_o_vrf, debug_o_flag, debug_o_addr_start, debug_o_addr_end); - - -#undef PLATFORM_PRINT_CTX_VALUES -#ifdef TARGET_RODDICK -#define PLATFORM_PRINT_CTX_VALUES(ctx) \ - printf("\nAFTER: %s cur_hdr %p, uidb %d, pkt_type %d, cur_len %d\n", \ - type_str, \ - ctx->current_header, \ - ctx->ru.tx.uidb_index, \ - ctx->ru.tx.packet_type, \ - ctx->current_length); -#else /* EVB */ -#define PLATFORM_PRINT_CTX_VALUES(ctx) \ - printf("\nAFTER: %s cur_hdr %p, cur_len %d\n", \ - type_str,\ - ctx->current_header, \ - ctx->current_length); -#endif - -#undef PLATFORM_ADD_VRF_MAP_HANDLE_PARTITION -#define PLATFORM_ADD_VRF_MAP_HANDLE_PARTITION(uidb_index, partition_id) - -#undef PLATFORM_DEL_VRF_MAP_HANDLE_PARTITION -#define PLATFORM_DEL_VRF_MAP_HANDLE_PARTITION(uidb_index, partition_id) - -#undef PLATFORM_ALLOC_NFV9_PKT_BUFFER -#define PLATFORM_ALLOC_NFV9_PKT_BUFFER(ctx, to_lc_cpu) - -#undef PLATFORM_CNAT_NFV9_SHIM_HDR_OFFSET -#ifdef TARGET_RODDICK -// This corresponds to the length of the IMETRO SHIM Header for RODDICK -#define PLATFORM_CNAT_NFV9_SHIM_HDR_OFFSET 8 -#else -#define PLATFORM_CNAT_NFV9_SHIM_HDR_OFFSET 0 -#endif - -#undef PLATFORM_CNAT_NFV9_L2_ENCAPS_OFFSET -#ifdef TARGET_RODDICK -#define PLATFORM_CNAT_NFV9_L2_ENCAPS_OFFSET 0 -#else -#define PLATFORM_CNAT_NFV9_L2_ENCAPS_OFFSET 16 -#endif - -#undef PLATFORM_MAX_SHOW_BUFFER_SIZE -#undef PLATFORM_MAX_TRANSLATION_ENTRIES -#undef PLATFORM_MAX_UTIL_ENTRIES - -#define PLATFORM_MAX_SHOW_BUFFER_SIZE 1700 -#define PLATFORM_MAX_TRANSLATION_ENTRIES (50) -#define PLATFORM_NAT64_MAX_TRANSLATION_ENTRIES (30) -#define PLATFORM_MAX_UTIL_ENTRIES (100) - - -#undef PLATFORM_NAT64_MAX_SESSIONS -#undef PLATFORM_NAT64_TIMEOUT_HASH_SIZE -#define PLATFORM_NAT64_MAX_SESSIONS 20000000 -#define PLATFORM_NAT64_TIMEOUT_HASH_SIZE 24001 /* Ref: CSCtr36242 */ - -#undef PLATFORM_CHECK_DSLITE_ENABLE_FLAG -#define PLATFORM_CHECK_DSLITE_ENABLE_FLAG 1 - -/* Fragment hold limit is Platform specific */ -/* For Roddick, it is 63 due to hardware limitation */ -#undef PLATFORM_IPV4_FRAG_FRAG_HOLD_LIMIT -#define PLATFORM_IPV4_FRAG_FRAG_HOLD_LIMIT 63 - -#undef PLATFORM_MAX_IPV4_CTX_ENTRIES -#define PLATFORM_MAX_IPV4_CTX_ENTRIES 80 - -#undef PLATFORM_DIRN_IN_TO_OUT -#undef PLATFORM_DIRN_OUT_TO_IN -#undef PLATFORM_SET_SVI_PARAMS_FIELD - -#define PLATFORM_DIRN_IN_TO_OUT -#define PLATFORM_DIRN_OUT_TO_IN -#define PLATFORM_SET_SVI_PARAMS_FIELD(var, value) - -#undef PLATFORM_GET_NFV9_L3_HDR_OFFSET -#define PLATFORM_GET_NFV9_L3_HDR_OFFSET \ - ((u8 *)ctx + ctx->data + CNAT_NFV9_IP_HDR_OFFSET); - -#undef PLATFORM_GET_NFV9_L4_HDR_OFFSET -#define PLATFORM_GET_NFV9_L4_HDR_OFFSET \ - ((u8 *) ctx + ctx->data + CNAT_NFV9_UDP_HDR_OFFSET); - -#undef PLATFORM_MEMSET_CNAT_LOG_PKT_DATA -#define PLATFORM_MEMSET_CNAT_LOG_PKT_DATA - -/* - Index 0 -- SE_P2MP - Index 1 -- HA Destination 1 - Index 2 -- HA Destination 2 - Index 3 -- EXT_LOG_SRVR -*/ -enum { - NODE_CGNCFG, - NODE_HA, - NODE_PD_CONFIG, - NODE_LOGGING, - NODE_TRACE_BACKUP, - NODE_MAX, -}; - -#endif /* __PLATFORM_COMMON_OVERRIDE_H__ */ diff --git a/plugins/plugins/vcgn/spp_ctx.h b/plugins/plugins/vcgn/spp_ctx.h deleted file mode 100644 index 2d3c95c8..00000000 --- a/plugins/plugins/vcgn/spp_ctx.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - *------------------------------------------------------------------ - * spp_ctx.h - packet / context definitions - * - * Copyright (c) 2007-2014 Cisco and/or its affiliates. - * 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 __SPP_CTX_H__ -#define __SPP_CTX_H__ - -/* Packet header / data */ - -/* Any change to spp_ctx_t structure should be updated in vnet/buffer.h - * as well. - */ -typedef struct _spp_ctx { -#ifdef TOBE_PORTED - /* Following fields are required to handle multibuffer */ - u32 num_buffers; /* Number of buffers part of packet */ - vlib_buffer_t *next_ctx_this_packet; - - /* Following is used by non-UDP protocols */ -#define SPP_CTX_FEATURE_DATA_SIZE 16 - - u8 feature_data[SPP_CTX_FEATURE_DATA_SIZE]; -#endif - - union { /* Roddick specific */ - u32 roddick_info; - struct __tx_pkt_info { /* Used by PI to PI communication for TX */ - u32 uidb_index:16; /* uidb_index to transmit */ - u32 packet_type:2; /* 1-IPv4, 2-Ipv6, - 0,3 - Unused */ - u32 ipv4_defrag:1; /* 0 - Normal, 1 - update first - * segment size - * (set by 6rd defrag node) - */ - - u32 dst_ip_port_idx:4;/* Index to dst_ip_port_table */ - u32 from_node:4; - u32 calc_chksum:1; - u32 reserved:4; - } tx; - struct __rx_pkt_info { /* Used by PD / PI communication */ - u32 uidb_index:16; /* uidb_index received in packet */ - u32 packet_type:2; /* 1-IPv4, 2-Ipv6, - 0,3 - Unused */ - u32 icmp_type:1; /* 0-ICMP query type, 1-ICMP error type */ - u32 protocol_type:2; /* 1-TCP, 2-UDP, 3-ICMP, 0 - Unused */ - u32 ipv4_defrag:1; /* 0 - Normal, 1 - update first - * segment size - * (set by 6rd defrag node) - */ - - u32 direction:1; /* 0-Outside, 1-Inside */ - u32 frag:1; /*IP fragment-1, Otherwise-0*/ - u32 option:1; /* 0-No IP option (v4) present, non-fragHdr - * option hdr present (v6) - */ - u32 df_bit:1; /* IPv4 DF bit copied here */ - u32 reserved1:6; - } rx; - } ru; -} spp_ctx_t; - -#endif diff --git a/plugins/plugins/vcgn/spp_platform_trace_log.c b/plugins/plugins/vcgn/spp_platform_trace_log.c deleted file mode 100644 index a96894f9..00000000 --- a/plugins/plugins/vcgn/spp_platform_trace_log.c +++ /dev/null @@ -1,989 +0,0 @@ -/* - *------------------------------------------------------------------ - * spp_platform_trace_log.c - * - * Copyright (c) 2008-2011, 2013 Cisco and/or its affiliates. - * 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 -#include -#include -#include -#include -#include -#include -#include - -#include "tcp_header_definitions.h" -#include "platform_common.h" -#include "spp_platform_trace_log.h" - -#define WORD_SIZE sizeof(u32) - -int temperature_read_blocked = 1; - -spp_cnat_logger_tbl_t spp_cnat_logger_table[] = -{ - { CNAT_ERROR_SUCCESS, - 3, - 0, - {"i-vrf", - "ipv4 addr", - "port"} - }, - { CNAT_NO_CONFIG_ERROR, - 3, - 180, - {"i-vrf", - "ipv4 addr", - "port"} - }, - { CNAT_NO_VRF_RUN_ERROR, - 3, - 180, - {"i-vrf", - "ipv4 addr", - "port"} - }, - { CNAT_NO_POOL_FOR_ANY_ERROR, - 3, - 180, - {"i-vrf", - "ipv4 addr", - "port"} - }, - { CNAT_NO_PORT_FOR_ANY_ERROR, - 3, - 60, - {"i-vrf", - "ipv4 addr", - "port"} - }, - { CNAT_BAD_INUSE_ANY_ERROR, - 3, - 60, - {"i-vrf", - "ipv4 addr", - "port"} - }, - { CNAT_NOT_FOUND_ANY_ERROR, - 3, - 60, - {"i-vrf", - "ipv4 addr", - "port"} - }, - { CNAT_INV_PORT_FOR_DIRECT_ERROR, - 3, - 60, - {"i-vrf", - "ipv4 addr", - "port"} - }, - { CNAT_BAD_INUSE_DIRECT_ERROR, - 3, - 1, - {"i-vrf", - "ipv4 addr", - "port"} - }, - { CNAT_NOT_FOUND_DIRECT_ERROR, - 3, - 1, - {"i-vrf", - "ipv4 addr", - "port"} - }, - { CNAT_OUT_OF_PORT_LIMIT_ERROR, - 3, - 60, - {"i-vrf", - "ipv4 addr", - "port"} - }, - { CNAT_MAIN_DB_CREATE_ERROR, - 0, - 30, - {""} - }, - { CNAT_LOOKUP_ERROR, - 1, - 30, - {"Type"} - }, - { CNAT_INDEX_MISMATCH_ERROR, - 2, - 30, - {"in2out_index", - "out2in_index"} - }, - { CNAT_PACKET_DROP_ERROR, - 3, - 15, - {"i-vrf", - "ipv4 addr", - "port"} - }, - { CNAT_INV_UNUSED_USR_INDEX, - 1, - 10, - {"invalid/unused user index"} - }, - { CNAT_INVALID_VRFMAP_INDEX, - 0, - 60, - {""} - }, - { CNAT_USER_OUT_OF_PORTS, - 2, - 1800, - {"i-vrf", - "ipv4 addr"} - }, - { CNAT_EXT_PORT_THRESH_EXCEEDED, - 2, - 180, - {"i-vrf", - "ipv4 address"} - }, - { CNAT_EXT_PORT_THRESH_NORMAL, - 2, - 180, - {"vrf", - "ipv4 address"} - }, - { CNAT_NO_EXT_PORT_AVAILABLE, - 0, - 1, - {"",} - }, - { CNAT_SESSION_THRESH_EXCEEDED, - 2, - 1800, - {"vrf", - "ipv4 address"} - }, - { CNAT_SESSION_THRESH_NORMAL, - 2, - 30, /* changed to 30 */ - {"vrf", - "ipv4 address"} - }, - { WQE_ALLOCATION_ERROR, - 0, - 180, /* changed to 180 */ - {""} - }, - { ERROR_PKT_DROPPED, - 2, - 60, /* changed to 60 */ - {"spi-port", - "error-code"} - }, - { SYSMGR_PD_KEY_CREATION_ERROR, - 0, - 30, - {""} - }, - { SYSMGR_PD_SHMEM_ID_ERROR, - 0, - 1, - {""} - }, - { SYSMGR_PD_SHMEM_ATTACH_ERROR, - 0, - 1, - {""} - }, - { OCTEON_CKHUM_SKIPPED, - 2, - 60, /* changed to 60 */ - {"version", - "protocol"} - }, - { PK0_SEND_STATUS, - 1, - 15, - {"status"} - }, - { CMD_BUF_ALLOC_ERR, - 0, - 60, - {""} - }, - { SPP_CTX_ALLOC_FAILED, - 1, - 300, /* every 5 min */ - {"node"} - }, - { SPP_MAX_DISPATCH_REACHED, - 1, - 60, - {"node"} - }, - { HA_SIGCHILD_RECV, - 3, - 1, - {"pid", - "uid", - "signal",} - }, - { SIGACTION_ERR, - 0, - 1, - {""} - }, - { HA_INVALID_SEQ_OR_CONFIG_OR_TYPE, - 2, - 10, - {"seq-id or config option", - "Type"} - }, - { NODE_CREATION_ERROR, - 1, - 1, - {"node"} - }, - - { CNAT_CLI_INVALID_INPUT, - 4, - 0, - {"Error Type", - "Passed", - "Expected", - "Type"} - }, - { CNAT_DUMMY_HANDLER_HIT, - 1, - 0, - {"Handler"} - }, - { CNAT_CONFIG_ERROR, - 5, - 0, - {"Sub code", - "Param 1", - "Param 2", - "Param 3", - "Param 4"} - }, - { CNAT_NFV9_ERROR, - 1, - 180, /* changed to 180 */ - {"Sub code"} - }, - { CNAT_CMVX_TWSI_READ_WRITE_FAIL, - 3, - 180, - {"Operation", - "Location", - "Data"} - }, - { CNAT_TEMP_SENSOR_TIMEOUT, - 0, - 180, - {""} - }, - { CNAT_TEMP_SENSOR_DATA_MISMATCH, - 2, - 180, - {"Actual", - "Expected"} - }, - { CNAT_TEMP_SENSOR_CONFIG_FAILED, - 1, - 180, - {"Glik"} - }, - { HA_APP_NOT_RESPONDING, - 2, - 180, - {"CPU", - "Core"} - }, - { HA_DATA_PATH_TEST_FAILED, - 0, - 30, - {""} - }, - { CNAT_WRONG_PORT_ALLOC_TYPE, - 3, - 60, - {"i-vrf", - "ipv4 addr", - "port"} - }, - { CNAT_NEW_PORT_ALLOC_ERROR, - 3, - 60, - {"i-vrf", - "ipv4 addr", - "port"} - }, - { CNAT_INVALID_INDEX_TO_FREE_PORT, - 0, - 60, - {""} - }, - { CNAT_DELETE_DB_ENTRY_NO_PORTMAP, - 0, - 60, - {""} - }, - { CNAT_MAIN_DB_LIMIT_ERROR, - 0, - 180, - {""} - }, - { CNAT_USER_DB_LIMIT_ERROR, - 0, - 180, - {""} - }, - { CNAT_FRAG_DB_ERROR, - 1, - 180, - {"Type"} - }, - - { DROP_PKT_DUMP, - 0, - 20, - {""} - } -}; - -#define LOG_TABLE_MAX_ENTRIES \ - (sizeof(spp_cnat_logger_table)/sizeof(spp_cnat_logger_table[0])) - -u32 error_code_timestamps[LOG_TABLE_MAX_ENTRIES]; -spp_timer_t sensor_timer; -spp_trace_log_global_info_t spp_trace_log_global_info; -spp_global_counters_t spp_global_counters; - -/* - * Logging information structures - */ -spp_trace_log_info_t spp_default_trace_log_info; -spp_trace_log_info_t *spp_trace_log_info_pool; - -#ifdef TOBE_PORTED -/* - * The following 2 functions are temporary hacks until - * we have RTC support from the PD nodes - */ -inline -u32 spp_trace_log_get_sys_up_time_in_ms (void) -{ - spp_node_main_vector_t *nmv; - u32 sys_up_time; - - nmv = spp_get_node_main_vectorized_inline(); - - sys_up_time = (u32) (nmv->ticks / nmv->ticks_per_ms); - - return (sys_up_time); -} - -u32 spp_trace_log_get_unix_time_in_seconds (void) -{ - spp_node_main_vector_t *nmv; - u32 unix_time; - - nmv = spp_get_node_main_vectorized_inline(); - - unix_time = (u32) (nmv->ticks / nmv->ticks_per_second); - - return (unix_time); -} - -/* - * edt: * * spp_trace_log_send_queued_pkt - * - * Tries to send a logging pkt that has been queued earlier - * because it could not be sent due to downstream constipation - * - * Argument: spp_trace_log_info_t *trace_logging_info - * structure that contains the packet context - */ -inline -void spp_trace_log_send_queued_pkt (spp_trace_log_info_t *trace_logging_info) -{ - spp_node_t *output_node; - - output_node = spp_get_nodes() + - spp_trace_log_global_info.spp_trace_log_disp_node_index; - - if (PREDICT_TRUE(output_node->sf.nused < SPP_MAXDISPATCH)) { - /* - * Move the logging context to output node - */ - spp_dispatch_make_node_runnable(output_node); - output_node->sf.ctxs[output_node->sf.nused++] = - trace_logging_info->queued_logging_context; - - /* - * Context has been queued, it will be freed after the pkt - * is sent. Clear this from the logging_context_info structure - */ - trace_logging_info->queued_logging_context = NULL; - - } else { - /* - * Can't do much, just return, may be we can send it later - */ - spp_global_counters.spp_trace_log_downstream_constipation_count++; - } -} - -/* - * edt: * * spp_trace_log_send_pkt - * - * Tries to send a logging pkt. If the packet cannot be sent - * because of rewrite_output node cannot process it, queue - * it temporarily and try to send it later. - * - * Argument: spp_trace_log_info_t *trace_logging_info - * structure that contains the packet context - */ -inline -void spp_trace_log_send_pkt (spp_trace_log_info_t *trace_logging_info) -{ - spp_node_t *output_node; - - - output_node = spp_get_nodes() + - spp_trace_log_global_info.spp_trace_log_disp_node_index; - - if (PREDICT_TRUE(output_node->sf.nused < SPP_MAXDISPATCH)) { - /* - * Move the logging context to output node - */ - spp_dispatch_make_node_runnable(output_node); - output_node->sf.ctxs[output_node->sf.nused++] = - trace_logging_info->current_logging_context; - - } else { - /* - * Queue the context into the logging_info structure, - * We will try to send it later. Currently, we will - * restrict to only one context queued. - */ - spp_global_counters.spp_trace_log_downstream_constipation_count++; - - /* - * Attach the current logging context which is full to the - * queued context list in trace_logging_info structure - */ - trace_logging_info->queued_logging_context = - trace_logging_info->current_logging_context; - - /* - * Whether the context is queued or not, set the current context index - * to EMPTY, as the earlier context can no more be used to send - * more logging records. - */ - } - - trace_logging_info->current_logging_context = NULL; -} - -/* - * edt: * * spp_trace_log_send_pkt_always_success - * - * Tries to send a logging pkt. This cannot fail due to downstream - * constipation because we have already checked if the rewrite_output - * node can accept it. - * - * Argument: spp_trace_log_info_t *trace_logging_info - * structure that contains the packet context - * - * Argument: spp_node_t *output_node - * spp_node_t structure for rewrite_output node - */ -inline -void spp_trace_log_send_pkt_always_success ( - spp_trace_log_info_t *trace_logging_info, - spp_node_t *output_node) -{ - /* - * At this point we either have a current or queued logging context - */ - if (PREDICT_TRUE(trace_logging_info->current_logging_context != NULL)) { - - output_node->sf.ctxs[output_node->sf.nused++] = - trace_logging_info->current_logging_context; - - trace_logging_info->current_logging_context = NULL; - } else { - /* - * For queued logging context - */ - output_node->sf.ctxs[output_node->sf.nused++] = - trace_logging_info->queued_logging_context; - - trace_logging_info->queued_logging_context = NULL; - } - - /* - * Move the logging context to output node - */ - spp_dispatch_make_node_runnable(output_node); - -} - -/* - * edt: * * spp_create_trace_log_context - * - * Tries to create a logging context with packet buffer - * to send a new logging packet - * - * Argument: spp_trace_log_info_t *trace_logging_info - * structure that contains the nfv9 logging info and will store - * the packet context as well. - */ -inline -void spp_create_trace_log_context ( - spp_trace_log_info_t *trace_logging_info) -{ - spp_ctx_t *ctx; - - /* - * If queued_logging_context_index is non-EMPTY, we already have a logging - * packet queued to be sent. First try sending this before allocating - * a new context. We can have only one active packet context per - * trace_logging_info structure - */ - if (PREDICT_FALSE(trace_logging_info->queued_logging_context != NULL)) { - spp_trace_log_send_queued_pkt(trace_logging_info); - /* - * If we cannot still send the queued pkt, just return - * Downstream Constipation count would have increased anyway - */ - if (trace_logging_info->queued_logging_context != NULL) { - spp_global_counters.spp_trace_log_context_creation_deferred_count++; - return; - } - } - - - /* - * No context can be allocated, return silently - * calling routine will handle updating the error counters - */ - if (spp_ctx_alloc(&ctx, 1) < 1) { - spp_global_counters.spp_trace_log_context_creation_fail_count++; - return; - } - - trace_logging_info->current_logging_context = ctx; - trace_logging_info->pkt_length = 0; - - trace_logging_info->current_logging_context_timestamp = - spp_trace_log_get_sys_up_time_in_ms(); - - ctx->flags = SPP_CTX_END_OF_PACKET; - ctx->ru.tx.from_node = NODE_TRACE_BACKUP; - ctx->ru.tx.dst_ip_port_idx = EXT_TRACE_BACKUP_INDEX; - ctx->next_ctx_this_packet = (spp_ctx_t*) SPP_CTX_NO_NEXT_CTX; - ctx->current_header = &ctx->packet_data[SPP_TRACE_LOG_HDR_OFFSET]; - ctx->current_length = 0; - - trace_logging_info->log_record = 0; - trace_logging_info->total_record_count = 0; - trace_logging_info->next_data_ptr = - (u8 *) &ctx->packet_data[SPP_TRACE_LOG_HDR_OFFSET]; - -} - -/* - * edt: * * spp_trace_log_add_record_create - * - * Tries to create an add record to the NFV9 packet - * - * Argument: spp_trace_log_info_t *trace_logging_info - * structure that contains the nfv9 logging info and will store - * the packet context as well. - */ -inline -void spp_trace_log_add_record_create (spp_trace_log_info_t *trace_logging_info) -{ - - trace_logging_info->log_header = - (spp_trace_log_hdr_t *) (trace_logging_info->next_data_ptr); - - /* - * Initialize the number of traces recorded - */ - trace_logging_info->log_header->num_traces = - spp_host_to_net_byte_order_32(0); - - - trace_logging_info->log_record = - (spp_trace_log_t *) (trace_logging_info->log_header + 1); - - /* - * Update the length of the total pkt - */ - trace_logging_info->pkt_length += - SPP_LOG_TRACE_HEADER_LENGTH; - - /* - * Set the data pointer beyond the trace header field - */ - trace_logging_info->next_data_ptr = - (u8 *) (trace_logging_info->log_header + 1); - -} - -/* - * edt: * * spp_trace_logger - * - * Tries to log spp/cnat event/errors - * - * Argument: u8 *error_code - * Error code passed - * - * Argument: optional arguments - */ -void spp_trace_logger (u16 error_code, u16 num_args, u32 *arg) -{ - spp_trace_log_info_t *trace_logging_info = 0; - u8 i; - - trace_logging_info = - spp_trace_log_info_pool + - spp_trace_log_global_info.spp_log_pool_index[SPP_LOG_LTRACE]; - - if (PREDICT_FALSE(trace_logging_info->current_logging_context == NULL)) { - spp_create_trace_log_context(trace_logging_info); - - /* - * If still empty, return after increasing the count - */ - if (PREDICT_FALSE(trace_logging_info->current_logging_context == NULL)) { - return; - } - } - - if (PREDICT_FALSE(trace_logging_info->log_record == NULL)) { - spp_trace_log_add_record_create(trace_logging_info); - } - - /* - * We should definitely have add_record now, no need to sanitize - */ - trace_logging_info->log_record->error_code = - spp_host_to_net_byte_order_16(error_code); - trace_logging_info->log_record->num_args = - spp_host_to_net_byte_order_16(num_args); - - for (i = 0; i < num_args; i++) { - trace_logging_info->log_record->arg[i] = - spp_host_to_net_byte_order_32(*(arg + i)); - } - - trace_logging_info->pkt_length += SPP_TRACE_LOG_RECORD_LENGTH + WORD_SIZE*num_args; - trace_logging_info->current_logging_context->current_length = - trace_logging_info->pkt_length; - trace_logging_info->total_record_count += 1; - - trace_logging_info->next_data_ptr = - (u8 *) (trace_logging_info->next_data_ptr + WORD_SIZE + WORD_SIZE*num_args); - - trace_logging_info->log_record = - (spp_trace_log_t *) (trace_logging_info->next_data_ptr); - - /* - * Initialize the number of traces recorded - */ - trace_logging_info->log_header->num_traces = - spp_host_to_net_byte_order_32(trace_logging_info->total_record_count); - - - - /* - * If we have exceeded the packet length, let us send the - * packet now. There is buffer of additional bytes beyond - * max_pkt_length to ensure that the last add/delete record - * can be stored safely. - */ - if (trace_logging_info->pkt_length > - trace_logging_info->max_length_minus_max_record_size) { - spp_trace_log_send_pkt(trace_logging_info); - } -} - - -/* - * edt: * * spp_trace_log_timer_handler - * - * Timer handler for sending any pending NFV9 record - * - * Argument: spp_timer_t * timer_p - * Timer handler structure - */ -inline -void spp_trace_log_timer_handler (spp_timer_t * timer_p) -{ - spp_node_t *output_node; - spp_trace_log_info_t *trace_logging_info = 0; - u32 current_timestamp = spp_trace_log_get_sys_up_time_in_ms(); - i16 sf_nused; - - output_node = spp_get_nodes() + - spp_trace_log_global_info.spp_trace_log_disp_node_index; - - sf_nused = output_node->sf.nused; - - pool_foreach (trace_logging_info, spp_trace_log_info_pool, ({ - /* - * Check if no more logging contexts can be queued - */ - if (PREDICT_FALSE(sf_nused >= SPP_MAXDISPATCH)) { - break; - } - - /* - * If there is a current logging context and timestamp - * indicates it is pending for long, send it out - * Also if there is a queued context send it out as well - */ - if (trace_logging_info->queued_logging_context || - (trace_logging_info->current_logging_context && - (current_timestamp - - trace_logging_info->current_logging_context_timestamp) - > 1000)) { - spp_trace_log_send_pkt_always_success(trace_logging_info, - output_node); - sf_nused++; - } - })); - - timer_p->expires = - spp_timer_in_n_ms_inline(1000); /* every 1 sec */ - spp_timer_start(timer_p); - -} -inline -void spp_sensor_timer_handler (spp_timer_t * timer_p) -{ -#ifdef TARGET_RODDICK - if (!temperature_read_blocked) { - Init_temperature_sensors(); - read_octeon_sensors(TEMPERATURE_SENSOR_QUIET_MODE); - } - - timer_p->expires = - spp_timer_in_n_ms_inline(60000); /* every 1 sec */ - spp_timer_start(timer_p); - -#endif -} -void init_trace_log_buf_pool (void) -{ - spp_trace_log_info_t *my_spp_log_info; - u8 found; - spp_log_type_t log_type; - - /* - * Init SPP logging info as needed, this will be done only once - */ - spp_trace_log_init(); - - found = 0; - - for (log_type = SPP_LOG_LTRACE; log_type < SPP_LOG_MAX; log_type++ ) { - /* Do we already have a map for this log type? */ - pool_foreach (my_spp_log_info, spp_trace_log_info_pool, ({ - if (my_spp_log_info->log_type == log_type) { - found = 1; - break; - } - })); - - /* - * Entry not present - */ - if (!found) { - pool_get(spp_trace_log_info_pool, my_spp_log_info); - memset(my_spp_log_info, 0, sizeof(*my_spp_log_info)); - - /* - * Make the current and head logging context indeices as EMPTY. - * When first logging happens, these get set correctly - */ - my_spp_log_info->current_logging_context = NULL; - my_spp_log_info->queued_logging_context = NULL; - - my_spp_log_info->log_type = log_type; - my_spp_log_info->max_length_minus_max_record_size = - SPP_TRACE_LOG_MAX_PKT_LENGTH; - - spp_trace_log_global_info.spp_log_pool_index[log_type] = - my_spp_log_info - spp_trace_log_info_pool; - } - - } - - return; -} - - -/* - * one time function - * has to be called at the init time - */ -void spp_trace_log_init (void) -{ - if (!spp_trace_log_global_info.spp_trace_log_init_done) { - -#ifdef TARGET_RODDICK - spp_trace_log_global_info.spp_trace_log_disp_node_index = - spp_lookup_node_index("roddick_infra_l3_tx"); -#elif defined(TARGET_BOOSTER) - spp_trace_log_global_info.spp_trace_log_disp_node_index = - spp_lookup_node_index("booster_infra_l3_tx"); -#endif - ASSERT(spp_trace_log_global_info.spp_trace_log_disp_node_index != (u16)~0); - - spp_trace_log_global_info.log_timer.cb_index = - spp_timer_register_callback(spp_trace_log_timer_handler); - spp_trace_log_global_info.log_timer.expires = - spp_timer_in_n_ms_inline(1000); /* every 1 sec */ - spp_timer_start(&spp_trace_log_global_info.log_timer); - - if (!my_core_id) { - sensor_timer.cb_index = - spp_timer_register_callback(spp_sensor_timer_handler); - sensor_timer.expires = - spp_timer_in_n_ms_inline(60000); /* every 1 sec */ - spp_timer_start(&sensor_timer); - } - - spp_trace_log_global_info.spp_trace_log_init_done = 1; - - /* - * Set MSC ip_addr, port values - */ -#ifdef TARGET_RODDICK - dst_ipv4_port_table[EXT_TRACE_BACKUP_INDEX].ipv4_address = - vpp_boot_params.msc_ip_address; - switch(vpp_boot_params.octeon_number) { - case 0: - dst_ipv4_port_table[EXT_TRACE_BACKUP_INDEX].port = 0x15BF; - break; - case 1: - dst_ipv4_port_table[EXT_TRACE_BACKUP_INDEX].port = 0x15BF; - break; - case 2: - dst_ipv4_port_table[EXT_TRACE_BACKUP_INDEX].port = 0x15BF; - break; - case 3: - dst_ipv4_port_table[EXT_TRACE_BACKUP_INDEX].port = 0x15BF; - break; - } -#else - dst_ipv4_port_table[EXT_TRACE_BACKUP_INDEX].ipv4_address = 0x01020304; - dst_ipv4_port_table[EXT_TRACE_BACKUP_INDEX].port = 0x15BF; -#endif - - } -} - -void spp_printf (u16 error_code, u16 num_args, u32 *arg) -{ - u32 current_timestamp; - spp_node_main_vector_t *nmv; - - if (PREDICT_FALSE(error_code >= LOG_TABLE_MAX_ENTRIES)) - { - /* printf("Error code invalid %d, %d, %d, %d\n", - error_code, LOG_TABLE_MAX_ENTRIES, - sizeof(spp_cnat_logger_table), sizeof(spp_cnat_logger_table[0])); - */ - return; /* Should not happen */ - } - - nmv = spp_get_node_main_vectorized_inline(); - current_timestamp = nmv->ticks / nmv->ticks_per_second; - - /* Check if any further hashing is required */ - - if (PREDICT_FALSE(error_code == DUMP_PKT_IDX)) { -#ifdef TARGET_RODDICK || defined(TARGET_BOOSTER) - spp_trace_logger(error_code, num_args, arg); -#else - u8 j ; - - printf("PKT DUMP :: "); - for (j = 0 ; j < num_args; j++) { - printf("0x%x ", arg[j]); - if (j == (num_args - 1)) { - printf("\n"); - } - } -#endif - } else if (PREDICT_TRUE((current_timestamp - error_code_timestamps[error_code]) >= - spp_cnat_logger_table[error_code].rate_limit_time)) { - /* update timestamp */ - error_code_timestamps[error_code] = current_timestamp; - -#ifdef TARGET_RODDICK || defined(TARGET_BOOSTER) - spp_trace_logger(error_code, num_args, arg); -#else - u8 j ; - - for (j = 0 ; j < num_args; j++) { - printf("%s: %d ", spp_cnat_logger_table[error_code].param_name[j], arg[j]); - if (j == (num_args - 1)) { - printf("\n"); - } - } -#endif - } -} - -#else /* TOBE_PORTEED */ -void spp_trace_logger(u16 error_code, u16 num_args, u32 *arg) -{ - /* To be filled */ -} - -void spp_trace_log_init(void) -{ - /* To be filled */ -} - -void init_trace_log_buf_pool(void) -{ - /* To be filled */ -} - -void spp_printf(u16 error_code, u16 num_args, u32 *arg) -{ - /* To be filled */ -} - -inline u32 spp_trace_log_get_unix_time_in_seconds (void) -{ - vlib_main_t *vlib_main; - - vlib_main = vlib_get_main(); - return(vlib_time_now((vlib_main_t *) vlib_main)); -} - -#endif /* TOBE_PORTED */ - diff --git a/plugins/plugins/vcgn/spp_platform_trace_log.h b/plugins/plugins/vcgn/spp_platform_trace_log.h deleted file mode 100644 index 36da710f..00000000 --- a/plugins/plugins/vcgn/spp_platform_trace_log.h +++ /dev/null @@ -1,358 +0,0 @@ -/* - *------------------------------------------------------------------ - * spp_platform_trace_log.h - * - * Copyright (c) 2009-2013 Cisco and/or its affiliates. - * 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 __SPP_PLATFORM_TRACE_LOG_H__ -#define __SPP_PLATFORM_TRACE_LOG_H__ - -#include -#include -#include -#include -#include -#include - -#include "spp_ctx.h" -#include "spp_timers.h" - - -typedef enum { - SPP_LOG_LTRACE, - SPP_LOG_MAX -} spp_log_type_t; - -typedef struct { - u32 num_traces; -} spp_trace_log_hdr_t; - -typedef struct { - u16 error_code; - u16 num_args; - u32 arg[0]; -} spp_trace_log_t; - -#define DUMP_PKT_IDX 61 -#define OCTEON_SENSOR_READ 62 - -typedef enum { - CNAT_ERROR_SUCCESS, - CNAT_NO_CONFIG_ERROR, - CNAT_NO_VRF_RUN_ERROR, - CNAT_NO_POOL_FOR_ANY_ERROR, - CNAT_NO_PORT_FOR_ANY_ERROR, - CNAT_BAD_INUSE_ANY_ERROR, - CNAT_NOT_FOUND_ANY_ERROR, - CNAT_INV_PORT_FOR_DIRECT_ERROR, - CNAT_BAD_INUSE_DIRECT_ERROR, - CNAT_NOT_FOUND_DIRECT_ERROR, - CNAT_OUT_OF_PORT_LIMIT_ERROR, - CNAT_MAIN_DB_CREATE_ERROR, - CNAT_LOOKUP_ERROR, - CNAT_INDEX_MISMATCH_ERROR, - CNAT_PACKET_DROP_ERROR, - CNAT_INV_UNUSED_USR_INDEX, - CNAT_INVALID_VRFMAP_INDEX, - CNAT_USER_OUT_OF_PORTS, - CNAT_EXT_PORT_THRESH_EXCEEDED, - CNAT_EXT_PORT_THRESH_NORMAL, - CNAT_NO_EXT_PORT_AVAILABLE, - CNAT_SESSION_THRESH_EXCEEDED, - CNAT_SESSION_THRESH_NORMAL, - WQE_ALLOCATION_ERROR, - ERROR_PKT_DROPPED, - SYSMGR_PD_KEY_CREATION_ERROR, - SYSMGR_PD_SHMEM_ID_ERROR, - SYSMGR_PD_SHMEM_ATTACH_ERROR, - OCTEON_CKHUM_SKIPPED, - PK0_SEND_STATUS, - CMD_BUF_ALLOC_ERR, - SPP_CTX_ALLOC_FAILED, - SPP_MAX_DISPATCH_REACHED, - HA_SIGCHILD_RECV, - SIGACTION_ERR, - HA_INVALID_SEQ_OR_CONFIG_OR_TYPE, - NODE_CREATION_ERROR, - CNAT_CLI_INVALID_INPUT, /* new adds as part of CSCto04510, see sub codes below */ - CNAT_DUMMY_HANDLER_HIT, /* Has sub codes , see spp_dummy_handler_sub_cdes_t */ - CNAT_CONFIG_ERROR, /* has subcodes-see spp_config_error_sub_codes_t below */ - CNAT_NFV9_ERROR, /* Has sub codes see spp_nfv9_error_sub_codes_t below */ - CNAT_CMVX_TWSI_READ_WRITE_FAIL, /* Hassub codes see spp_cmvx_error_sub_codes_t */ - CNAT_TEMP_SENSOR_TIMEOUT, - CNAT_TEMP_SENSOR_DATA_MISMATCH, - CNAT_TEMP_SENSOR_CONFIG_FAILED, - HA_APP_NOT_RESPONDING, - HA_DATA_PATH_TEST_FAILED, - CNAT_WRONG_PORT_ALLOC_TYPE, - CNAT_NEW_PORT_ALLOC_ERROR, - CNAT_INVALID_INDEX_TO_FREE_PORT, - CNAT_DELETE_DB_ENTRY_NO_PORTMAP, - CNAT_MAIN_DB_LIMIT_ERROR, - CNAT_USER_DB_LIMIT_ERROR, - CNAT_FRAG_DB_ERROR, /* see spp_frag_db_error_sub_codes_t below */ - - DROP_PKT_DUMP, - CNAT_NAT64_SYSTEM_LIMIT_ERROR, - CNAT_ERROR_MAX -} spp_error_codes_t; - -typedef enum { - - TCP_MSS_INVALID_IVRF = 10, /* 1 param - vrf id */ - NFV9_LOG_INVALID_IP_OR_PORT = 20, /* 2 params - nfv9 server ip and port */ - NFV9_LOG_INVALID_PARAMS_OTHERS, /* 3 params, ref rate, time out, path mtu */ - NFV9_LOG_PATH_MTU_TOO_SMALL, /* 1 param, path mtu passed */ - NFV9_LOG_CANNOT_ADD_VRF_NOT_FOUND, /* 1 param, in vrf id */ - - VRF_MAP_ADDR_POOL_START_ADDR_GT_END_ADDR = 30, /* 2 params, start and end addr */ - VRF_MAP_ADDR_POOL_ADDR_POOL_TOO_LARGE, /* 2 params, start and end addr */ - VRF_MAP_ADDR_POOL_INVALID_IN_OR_OUT_VRF, /* 2 params, in vrf and out vrf */ - VRF_MAP_ADDR_POOL_TOO_LARGE_FOR_CORE, /* 2 params, pool size, core instance */ - VRF_MAP_DEL_POOL_START_ADDR_GT_END_ADDR, /* 2 params, start and end addr */ - VRF_MAP_DEL_POOL_ADDR_POOL_NOT_FOUND, /* 2 params, start and end addr */ - VRF_MAP_DEL_POOL_VRF_MAP_EMPTY, /* 2 params, start and end addr */ - - ADD_SVI_ADDR_INVALID_VRF = 40, /* 2 params, vrf passed and ipv4 addr */ - ADD_SVI_INDEX_INVALID_VRF, /* 2 params, vrf, uidb_index */ - - MAPPED_STAT_PORT_INVALID_OUTPUT_PARAMS = 50, - /* 3 params, out vrf, out ip, out port */ - MAPPED_STAT_PORT_UDP_PORT_POLARITY_MISMATCH, /* 2 params, in port and out port */ - MAPPED_STAT_PORT_IN_VRF_MAP_EMPTY, /* 1 param, in vrf id passed */ - MAPPED_STAT_PORT_VRF_MAP_NOT_IN_S_RUN, /* 1 param, vrf map status */ - MAPPED_STAT_PORT_INVALID_OUT_VRF_ID, /* 1 param, out vrf id passed */ - MAPPED_STAT_PORT_FAILED_TO_ADD_STAT_PORT, /* 4 params, in vrf, in ip, in port, error code */ - - STAT_PORT_INVALID_IN_PARAMS = 60, /* 4 params, in vrf, in ip, in port, proto */ - STAT_PORT_FAILED_TO_ADD_STAT_PORT, /* 4 params, in vrf, in ip, in port, error code */ - STAT_PORT_CONFIG_IN_USE, /* 4 params, in vrf, in ip, in port, proto */ - - DEL_STAT_PORT_IN_VRF_MAP_EMPTY = 70, /* 1 param, in vrf id passed */ - DEL_STAT_PORT_INVALID_IN_PARAMS, /* 4 params, in vrf, in ip, in port, proto */ - DEL_STAT_PORT_CANNOT_DELETE_NO_ENTRY, /* 4 params, in vrf, in ip, in port, proto */ - DEL_STAT_PORT_CANNOT_DELETE_NOT_STATIC_PORT, /* 4 params, in vrf, in ip, in port, proto*/ - - XLAT_SVI_CFG_INVALID_INDEX = 80, /* 1 param - uidb_index */ - XLAT_WRONG_V6_PREFIX_MASK, /* 1 param - v6 prefix mask */ - XLAT_INVALID_XLAT_ID_ERROR, /* 1 param - id */ - - V6RD_INVALID_6RD_ID_ERROR = 90, /*1 param - id */ - MAPE_INVALID_MAPE_ID_ERROR = 100 /* param - id */ -} spp_config_error_sub_codes_t; - -typedef enum { - CONFIG_DUMMY, - CONFIG_DUMMY_MAX, - SHOW_DUMMY, - SHOW_DUMMY_MAX, - DEBUG_DUMMY, - DEBUG_DUMMY_MAX -} spp_dummy_handler_sub_cdes_t; - -typedef enum { - CMVX_READ, - CMVX_WRITE -} spp_cmvx_error_sub_codes_t; - -typedef enum { - FRAG_DB_INVALID_BUCKET, - FRAG_DB_NO_ENTRY -} spp_frag_db_error_sub_codes_t; - -typedef enum { - CLI_INVALID_PAYLOAD_SIZE, - CLI_INVALID_MSG_ID -} spp_cli_error_sub_codes_t; - -typedef enum { - NFV9_DOWNSTREAM_CONGESTION, - NFV9_FAILED_TO_CREATE_CONTEXT -} spp_nfv9_error_sub_codes_t; - -typedef struct spp_cnat_logger_tbl_t_ { - u16 error_code; // The thread id stored by software - u16 num_args; - u16 rate_limit_time; // If we need to rate_limit logging - u8 param_name[7][32];// Parameter name for debug purposes -} spp_cnat_logger_tbl_t; - -extern spp_cnat_logger_tbl_t spp_cnat_logger_table[]; - -/* - * This corresponds to the length of the IMETRO SHIM Header for RODDICK - * For non-roddick cases, introduce an Ethernet header as well - */ -#if defined(RODDICK) -#define SPP_TRACE_LOG_SHIM_HDR_OFFSET 8 -#define SPP_TRACE_LOG_ENCAPS_OFFSET 0 -#else -#define SPP_TRACE_LOG_SHIM_HDR_OFFSET 0 -#define SPP_TRACE_LOG_ENCAPS_OFFSET 16 -#endif - -#define SPP_LOG_TRACE_HEADER_LENGTH \ - (sizeof(spp_trace_log_hdr_t)) - - -#define SPP_TRACE_LOG_IP_HDR_OFFSET \ - (SPP_TRACE_LOG_ENCAPS_OFFSET + \ - SPP_TRACE_LOG_SHIM_HDR_OFFSET) - - -#define SPP_TRACE_LOG_UDP_HDR_OFFSET \ - (SPP_TRACE_LOG_IP_HDR_OFFSET + sizeof(ipv4_header)) - -#define SPP_TRACE_LOG_HDR_OFFSET \ - (SPP_TRACE_LOG_UDP_HDR_OFFSET + sizeof(udp_hdr_type_t)) - -#define SPP_TRACE_LOG_RECORD_LENGTH 4 - -/* - * Let us put the maximum length of the log data to be 1400 - */ -#define SPP_TRACE_LOG_MAX_PKT_LENGTH 800 - -/* Structures and defines to store log info for MSC */ -#define SPP_TRACE_LOG_INVALID_LOGGING_INDEX 0xffffffff - -/* - * This structure stores the Logging information on per LOG TYPE - * basis. This structure is allocated from a pool and index - * to this structure based on log type - */ -typedef struct { - /* - * This field determines the maximum size of the Netflow V9 information - * that can be stored in a logging packet - */ - u16 max_length_minus_max_record_size; - - u32 sequence_num; /* Sequence number of the logging packet */ - u32 last_pkt_sent_count; - u16 pkt_length; /* Length of the currently NFv9 information */ - u16 log_record_length; /* Length of add record */ - u16 total_record_length; /* number of trace records */ - u16 total_record_count; - spp_log_type_t log_type; - /* - * current logging context - */ - spp_ctx_t *current_logging_context; - - /* - * Timestamp in UNIX seconds corresponding to when the current - * logging packet was created - */ - u32 current_logging_context_timestamp; - - /* - * Queued logging context waiting to be sent to the l3 infra node - */ - spp_ctx_t *queued_logging_context; - - /* - * Headers corresponding to various records in this - * current nfv9 logging context - */ - spp_trace_log_t *log_record; - spp_trace_log_hdr_t *log_header; - u8 *next_data_ptr; - -} spp_trace_log_info_t; - -typedef struct { - /* - * spp_ctx_alloc() call failed - */ - u64 spp_trace_log_context_creation_fail_count; - - /* - * Cannot send the existing logging pkt, so cannot create - * any additional packets for logging purposes - */ - u64 spp_trace_log_context_creation_deferred_count; - - /* - * Cannot send the existing logging pkt due to cnat_rewrite_output - * superframe being full. - */ - u64 spp_trace_log_downstream_constipation_count; -} spp_global_counters_t; - - -/* - * Global structure for SPP LOGS - */ -typedef struct { - /* A timer structure to periodically send log packets - * that have been waiting to be full for a long time. This will - * ensure event/error logs don't get delayed too much before they - * are sent to the MSC. - */ - spp_timer_t log_timer; - - /* - * Node index corresponding to the infra L3 output node - * to which the nfv9 logging node will send the packet - */ - u16 spp_trace_log_disp_node_index; - - /* - * Whether we have initialized the NFv9 information - */ - u8 spp_trace_log_init_done; - - /* - * pool index in global pool based on log type - */ - u32 spp_log_pool_index[SPP_LOG_MAX]; - -} spp_trace_log_global_info_t; - - -extern spp_timer_t sensor_timer; -extern spp_trace_log_info_t spp_default_trace_log_info; -extern spp_trace_log_info_t *spp_trace_log_info_pool; - -extern spp_trace_log_global_info_t spp_trace_log_global_info; - -void spp_trace_logger(u16 error_code, u16 num_args, u32 *arg); -void spp_trace_log_init(void); -void init_trace_log_buf_pool(void); -void spp_printf(u16 error_code, u16 num_args, u32 *arg); - -/* - * The following 2 functions are temporary hacks until - * we have RTC support from the PD nodes - */ -#if 0 -inline -u32 spp_trace_log_get_sys_up_time_in_ms (void); -#endif -extern -u32 spp_trace_log_get_unix_time_in_seconds (void); - -enum { - TEMPERATURE_SENSOR_TEST_MODE, - TEMPERATURE_SENSOR_QUIET_MODE, -}; - -extern int temperature_read_blocked; - -void read_octeon_sensors(u8 mode); -void Init_temperature_sensors(); -#endif /* __SPP_PLATFORM_TRACE_LOG_H__ */ diff --git a/plugins/plugins/vcgn/spp_timers.h b/plugins/plugins/vcgn/spp_timers.h deleted file mode 100644 index afb0147b..00000000 --- a/plugins/plugins/vcgn/spp_timers.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - *------------------------------------------------------------------ - * spp_timers.h - * - * Copyright (c) 2008-2009 Cisco and/or its affiliates. - * 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 __SPP_TIMERS_H__ -#define __SPP_TIMERS_H__ - - -typedef struct d_list_el_ { - struct d_list_el_ *next; - struct d_list_el_ *prev; -} d_list_el_t; - -/* - * d_list_init - */ - -static inline void d_list_init (d_list_el_t *headp) -{ - headp->prev = headp->next = headp; -} - -/* - * d_list_init - add at head of list - */ - -static inline void d_list_add_head (d_list_el_t *headp, - d_list_el_t *elp) -{ - ASSERT(elp->prev == elp); /* multiple enqueue, BAD! */ - ASSERT(elp->next == elp); - - elp->next = headp->next; - headp->next = elp; - elp->prev = elp->next->prev; - elp->next->prev = elp; -} - -/* - * d_list_add_tail - add element at tail of list - */ -static inline void d_list_add_tail (d_list_el_t *headp, - d_list_el_t *elp) -{ - ASSERT(elp->prev == elp); /* multiple enqueue, BAD! */ - ASSERT(elp->next == elp); - - headp = headp->prev; - - elp->next = headp->next; - headp->next = elp; - elp->prev = elp->next->prev; - elp->next->prev = elp; -} - -/* - * d_list_rem_head - removes first element from list - */ -static inline d_list_el_t *d_list_rem_head (d_list_el_t *headp) -{ - d_list_el_t *elp; - - elp = headp->next; - if (elp == headp) - return (NULL); - headp->next = elp->next; - elp->next->prev = elp->prev; - - elp->next = elp->prev = elp; - return (elp); -} - -/* - * d_list_rem_elem - removes specific element from list. - */ -static inline void d_list_rem_elem (d_list_el_t *elp) -{ - d_list_el_t *headp; - - headp = elp->prev; - - headp->next = elp->next; - elp->next->prev = elp->prev; - elp->next = elp->prev = elp; -} - -#define TIMER_BKTS_PER_WHEEL 128 /* power of 2, please */ -#define TIMER_NWHEELS 4 - -typedef struct { - i32 curindex; /* current index for this wheel */ - d_list_el_t *bkts; /* vector of bucket listheads */ -} spp_timer_wheel_t; - - -typedef struct { - u64 next_run_ticks; /* Next time we expire timers */ - spp_timer_wheel_t **wheels; /* pointers to wheels */ -} spp_timer_axle_t; - - -typedef struct { - d_list_el_t el; - u16 cb_index; - u16 flags; - u64 expires; -} spp_timer_t; - -#define SPP_TIMER_RUNNING 0x0001 - - -/* - * prototypes - */ -void spp_timer_set_ticks_per_ms(u64); -void spp_timer_axle_init (spp_timer_axle_t *ta); -void spp_timer_expire(spp_timer_axle_t *ta, u64 now); -void spp_timer_final_init(void); - -void spp_timer_start(spp_timer_t *tp); -void spp_timer_start_axle(spp_timer_axle_t *ta, spp_timer_t *tp); -void spp_timer_stop(spp_timer_t *tp); -u16 spp_timer_register_callback (void (*fp)(spp_timer_t *)); - -#endif /* __SPP_TIMERS_H__ */ diff --git a/plugins/plugins/vcgn/tcp_header_definitions.h b/plugins/plugins/vcgn/tcp_header_definitions.h deleted file mode 100644 index 02920bcc..00000000 --- a/plugins/plugins/vcgn/tcp_header_definitions.h +++ /dev/null @@ -1,1582 +0,0 @@ -/* - *----------------------------------------------------------------------------- - * - * Filename: tcp_header_definitions.h - * - * Description: Layer 2, 3, 4 definitions and header types - * - * Assumptions and Constraints: - * - * Copyright (c) 2012-2013 Cisco and/or its affiliates. - * 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 __TCP_HEADER_DEFINITIONS_H__ -#define __TCP_HEADER_DEFINITIONS_H__ - -/* - * A general list of Layer 3 protocols, used by many Layer 2 encaps. - * - * formerly: - * TYPE_IP TYPE_IP10MB - * TYPE_ARP TYPE_RFC826_ARP - * TYPE_RARP TYPE_REVERSE_ARP - * TYPE_MPLS TYPE_TAGSWITCH - */ -#define TYPE_IP 0x0800 -#define TYPE_IP_V6 0x86DD -#define TYPE_ARP 0x0806 -#define TYPE_RARP 0x8035 -#define TYPE_MPLS 0x8847 -#define TYPE_CDP 0x2000 -#define TYPE_CGMP 0x2001 -#define TYPE_LACP 0x8808 /* 802.3ad */ -#define TYPE_CLNS 0xFEFE - -#define TYPE_PPPOE_SESSION 0x8864 /* PTA plus */ -#define TYPE_PPPOE_DISCOVERY 0x8863 /* PTA plus */ - -/* - * for atm arp handling - */ -#define IN_ATM_ARP_BIT 0x0008 - -/* - * The Layer 2 header structures. - */ - - -/* -** HDLC -*/ - -typedef struct hdlc_hdr_type { - u16 addr; - u16 type; - u8 data[0]; -} hdlc_hdr_type; - -#define HDLC_ADDR_CMD 0x0F00 -#define HDLC_HDR_LEN 4 -#define HDLC_BROADCAST_BIT 31 -#define TYPE_KEEP 0x8035 - -#define HDLC_CLNS (HDLC_ADDR_CMD<<16|TYPE_CLNS) -#define HDLC_CDP (HDLC_ADDR_CMD<<16|TYPE_CDP) -#define HDLC_MPLS (HDLC_ADDR_CMD<<16|TYPE_MPLS) -#define HDLC_IP (HDLC_ADDR_CMD<<16|TYPE_IP) -#define HDLC_IP_V6 (HDLC_ADDR_CMD<<16|TYPE_IP_V6) -#define HDLC_KEEPALIVE_CMD (HDLC_ADDR_CMD<<16|TYPE_KEEP) - -/* -** PPP -*/ - -typedef struct ppp_comp_hdr_type { - union { - u8 ppp_u8[4]; - u16 ppp_u16[2]; - u32 ppp_u32; - } ppp_comp_u; -} ppp_comp_hdr_type; - -#define PPP_STATION 0xFF03 -#define PPP_STATION_LEN 0x2 -#define PPP_ENDPROTO 0x01 -#define PPP_NOT_ENDPROTO 0xfffffffe -#define PPP_CONTROL_PROTOCOL_MASK 0x8000 -#define PPP_CONTROL_PROTOCOL_BIT 15 -#define PPP_CSCO_LEN 4 -#define PPP_RFC1661_LEN 2 -#define PPP_RFC1661_COMP_LEN 1 - -#define TYPE_PPP_IP 0x0021 -#define TYPE_PPP_IP_V6 0x0057 -#define TYPE_PPP_MPLS_UNICAST 0x0281 -#define TYPE_PPP_MPLS_CONTROL 0x8281 -#define TYPE_PPP_CLNS 0x0023 -#define TYPE_PPP_CDP 0x0207 - -#define TYPE_PPP_IPCP 0x8021 -#define TYPE_PPP_LCP 0xC021 -#define TYPE_PPP_PAP 0xC023 -#define TYPE_PPP_LQR 0xC025 -#define TYPE_PPP_CHAP 0xC223 - - -#define TYPE_PPP_LCP_ECHO_REQUEST 0x09 -/* -** MultiLink PPP -*/ - -#define MLPPP_FLAGS_FIELD_LEN 4 -#define MLPPP_BEGIN_MASK 0x80000000 -#define MLPPP_END_MASK 0x40000000 -#define MLPPP_BEGIN_END_MASK (MLPPP_BEGIN_MASK|MLPPP_END_MASK) -#define MLPPP_BEGIN_END_SHIFT 30 -#define MLPPP_SEQUENCE_NUM_MASK 0x00FFFFFF -#define MLPPP_MC_CLASS_ID_MASK 0x3C000000 -#define MLPPP_MC_CLASS_SHIFT 26 - -#define TYPE_PPP_MULTILINK 0x003D - -/* these are needed in the micro-code, for optimizations */ -#define TYPE_PPP_FULL_IP_4 0xff030021 -#define TYPE_PPP_FULL_IP_3 0xff0321 -#define TYPE_PPP_FULL_IP_2 0x0021 -#define TYPE_PPP_FULL_IP_1 0x21 - -#define MLPPP_BEGIN_END_MASK_BYTE 0xC0 -#define MLPPP_BEGIN_BIT 7 -#define MLPPP_END_BIT 6 -#define MLPPP_MC_CLASS_ID_MASK_BYTE 0x3C -#define MLPPP_MC_CLASS_ID_SHIFT_BYTE 2 - -#define MLPOA_BEGIN_END_SHIFT 24 - -/* -** Ethernet ARPA -*/ - - -typedef struct ethernet_arpa_hdr_type { - u8 daddr[6]; - u8 saddr[6]; - u16 type; - u8 data[0]; -} ethernet_arpa_hdr_type; - -typedef struct extension_802p3_type { - u16 type; - u8 ctl; - u8 data[0]; -} extension_802p3_type; - -typedef struct ethernet_802p3_hdr_type { - u8 daddr[6]; - u8 saddr[6]; - u16 length; - extension_802p3_type extension; -} ethernet_802p3_hdr_type; - - -typedef struct ethernet_vlan_802p3_hdr_type { - u8 daddr[6]; - u8 saddr[6]; - u16 type1; - u16 vlan_id; - u16 length; - extension_802p3_type extension; -} ethernet_vlan_802p3_hdr_type; - -#define MIN_ETHERNET_PKT_LEN 60 -#define MAX_ETHERNET_PKT_LEN 1500 -#define ETHERNET_ARPA_HDR_LEN 14 -#define ETHERNET_TYPE_FIELD_SIZE 2 - - -/* -** Ethernet 802.1q (VLAN) -*/ - -typedef struct ethernet_vlan_hdr_type { - u8 dest_addr[6]; - u8 src_addr[6]; - u16 type1; - u16 vlan_hdr; - u16 type2; - u8 data[0]; -} ethernet_vlan_hdr_type; - - -/* -** Ethernet 802.1.q-in-q (QinQ) -*/ - -typedef struct ethernet_qinq_hdr_type { - u8 dest_addr[6]; - u8 src_addr[6]; - u16 type1; - u16 vlan_hdr1; - u16 type2; - u16 vlan_hdr2; - u16 type3; - u8 data[0]; -} ethernet_qinq_hdr_type; - - -/* -** Ethernet 802.3ad EtherChannel control -*/ - -typedef struct ethernet_lacp_hdr_type { - u8 daddr[6]; - u8 saddr[6]; - u16 type; - u16 LAcmd; - u8 data[0]; -} ethernet_lacp_hdr_type; - - -/* -** Ethernet 802.1 Bridge (spanning tree) PDU -*/ - -typedef struct ethernet_bpdu_hdr_type { - u8 daddr[6]; - u8 saddr[6]; - u8 dsap; - u8 ssap; - u8 control; - u8 more[0]; -} ethernet_bpdu_hdr_type; - -#define ETH_BPDU_DSAP 0x42 -#define ETH_BPDU_SSAP 0x42 -#define ETH_BPDU_CONTROL 0x03 -#define ETH_BPDU_MATCH 0x424203 - - -/************************************************************/ -/* PTA PLUS ETHERNET ENCAPSULATIONS */ -/* - * PPPoEoARPA 20 bytes - */ -typedef struct ethernet_pppoe_arpa_hdr_type { - u8 daddr[6]; - u8 saddr[6]; - u16 type; - /* pppoe hdr at begining of enet payload */ - u16 vtc; /* version(4b), type(4b) and code(8b) fields */ - u16 sid; - u16 len; - u8 ppp_header[0]; /* PPP header start, no ff03 field present */ -} ethernet_pppoe_arpa_hdr_type; - -typedef struct pppoe_hdr_type { - /* pppoe hdr at begining of enet payload */ - u16 vtc; /* version(4b), type(4b) and code(8b) fields */ - u16 sid; - u16 len; - u8 ppp_header[0]; /* PPP header start, no ff03 field present */ -} pppoe_hdr_type; - -/* -** PPPoEoVLAN (802.1p or 802.1q) 24 bytes -*/ -typedef struct ethernet_pppoe_vlan_hdr_type { - u8 dest_addr[6]; - u8 src_addr[6]; - u16 type1; - u16 vlan_hdr; - u16 type2; - /* pppoe hdr at begining of enet payload */ - u16 vtc; /* version(4b), type(4b) and code(8b) fields */ - u16 sid; - u16 len; - u8 ppp_header[0]; /* PPP header start, no ff03 field present */ -} ethernet_pppoe_vlan_hdr_type; - -/* -** PPPoEoQinQ 28 bytes -*/ -typedef struct ethernet_pppoe_qinq_hdr_type { - u8 dest_addr[6]; - u8 src_addr[6]; - u16 type1; - u16 vlan_hdr1; - u16 type2; - u16 vlan_hdr2; - u16 type3; - /* pppoe hdr at begining of enet payload */ - u16 vtc; /* version(4b), type(4b) and code(8b) fields */ - u16 sid; - u16 len; - u8 ppp_header[0]; /* PPP header start, no ff03 field present */ -} ethernet_pppoe_qinq_hdr_type; - -#define ETH_PPPOE_ARPA_HDR_LEN sizeof(ethernet_pppoe_arpa_hdr_type) -#define ETH_PPPOE_VLAN_HDR_LEN sizeof(ethernet_pppoe_vlan_hdr_type) -#define ETH_PPPOE_QINQ_HDR_LEN sizeof(ethernet_pppoe_qinq_hdr_type) -#define PPPOE_HDR_LEN 6 -/* End PTA PLUS ETHERNET ENCAPSULATIONS */ -/****************************************************************/ - - - -#define TYPE_DOT1Q 0x8100 -#define DOT1Q_HDR_LEN 18 -#define DOT1Q_VLAN_ID_MASK 0x0FFF -#define DOT1Q_VLAN_ID_RES_0 0x0000 -#define DOT1Q_VLAN_ID_RES_4095 0x0FFF -#define DOT1Q_ARPA_INDEX DOT1Q_VLAN_ID_RES_0 - -#define TYPE_QINQ_91 0x9100 -#define TYPE_QINQ_92 0x9200 -#define TYPE_QINQ_88A8 0x88A8 -#define QINQ_HDR_LEN 22 - -/* - * 802.1p support - */ -#define DOT1P_VLAN_COS_MASK 0xE000 -#define DOT1P_VLAN_COS_SHIFT 13 -#define DOT1P_MAX_COS_VALUE 7 - -/* -** Frame Relay -*/ - -/* - * formerly: - * TYPE_FR_IETF_IPV4 ENCAPS_FR_IETF - * TYPE_FR_CISCO_IPV4 ENCAPS_FR_CISCO - * TYPE_FR_ISIS ENCAPS_FR_ISIS - * - * FR_LMI_DLCI_CISCO LMI_DLCI_CISCO - * FR_LMI_DLCI_IETF LMI_DLCI_ITUANSI - */ - -typedef struct frame_relay_hdr_type { - u16 address; - u16 control_nlpid; - u8 data[0]; -} frame_relay_hdr_type; - -typedef struct fr_snap_hdr_type { - u16 address; - u8 control; - u8 pad; - u8 nlpid; - u8 oui[3]; - u16 protocol_id; -} fr_snap_hdr_type; - -#define FR_ADDR_LEN 2 -#define FR_CTL_NLPID_LEN 2 -#define FR_HDR_LEN (FR_ADDR_LEN+FR_CTL_NLPID_LEN) - -/* - * These defines are for the FR-SNAP header. - * The SNAP header is set up solely so that we can - * identify ARP packets, which look like this: - * - * control pad nlpid oui protocol_id - * 03 00 80 00 00 00 0806 - */ -#define FR_ARP_CONTROL 0x03 -#define FR_ARP_PAD 0x00 -#define FR_ARP_NLPID 0x80 -#define FR_ARP_OUI_0 0x00 -#define FR_ARP_OUI_1 0x00 -#define FR_ARP_OUI_2 0x00 -/* - * these are used only in the tmc code - */ -#define FR_NLPID_OUI_LEN 4 -#define FR_ARP_CONTROL_PAD 0x0300 -#define FR_ARP_NLPID_OUI 0x80000000 - - -#define FR_DLCI_UPPER_MASK 0xFC00 -#define FR_DLCI_UPPER_SHIFT 6 -#define FR_DLCI_LOWER_MASK 0x00F0 -#define FR_DLCI_LOWER_SHIFT 4 - -/* - * Defines for converting a DLCI for insertion into a synthesized FR address - * field for FRoMPLS disposition. - - * bit 8 7 6 5 4 3 2 1 - * +-------------------------------+ - * | Flag | - * | 0 1 1 1 1 1 1 0 | - * +-------------------------------+ - * | Upper DLCI |C/R| 0 | - * +-------------------------------+ - * | Lower DLCI | F | B | DE| 1 | - * +-------------------------------+ - * | | - * :Frame relay information field : - * : (i.e.payload) : - * | | - * +-------------------------------+ - * | FCS (2 or 4 octets) | - * | | - * +-------------------------------+ - * | Flag | - * | 0 1 1 1 1 1 1 0 | - * +-------------------------------+ - * - * a-With 10 bits for the DLCI - */ -#define FR_DLCI_TO_HDR_UPPER_MASK 0x3f0 -#define FR_DLCI_TO_HDR_UPPER_SHIFT (10-4) -#define FR_DLCI_TO_HDR_LOWER_MASK 0xf -#define FR_DLCI_TO_HDR_LOWER_SHIFT 4 - -#define TYPE_FR_IETF_IP 0x03CC -#define TYPE_FR_IETF_IP_V6 0x038E -#define TYPE_FR_CISCO_IP 0x0800 -#define TYPE_FR_CISCO_IP_V6 0x86DD -#define TYPE_FR_ISIS 0x0383 -#define TYPE_FR_SNAP0PAD 0x0380 -#define TYPE_FR_SNAP1PAD 0x0300 -#define TYPE_FR_FRF12 0x03B1 -#define TYPE_FR_MLP 0x03CF -#define TYPE_FR_EEK 0x8037 - -#define FR_LMI_DLCI_CISCO 1023 -#define FR_LMI_DLCI_IETF 0 - -#define FR_NOT_NOT_NOT 0 -#define FR_NOT_NOT_DE 1 -#define FR_NOT_BECN_NOT 2 -#define FR_NOT_BECN_DE 3 -#define FR_FECN_NOT_NOT 4 -#define FR_FECN_NOT_DE 5 -#define FR_FECN_BECN_NOT 6 -#define FR_FECN_BECN_DE 7 - -#define FR_FECN_BECN_DE_MASK 0x000E -#define FR_FECN_BECN_DE_SHIFT 1 - -/* Address field extension bit for standard 2-byte FR address field */ -#define FR_EA1_MASK 0x0001 -#define FR_EA1_MASK_BIT 0 - -/* - * these are needed in the micro-code, for optimizations - */ - -/* the bit position (in the address field) of the LSB of the DLCI */ -#define FR_DLCI_LS_BIT 4 - - -/* -** -** MultiLink Frame Relay -** -*/ - -typedef struct mlfr_hdr_type { - u16 frag_hdr; - u16 address; - u16 control_nlpid; - u8 data[0]; -} mlfr_hdr_type; - -/* - * LIP frames have B, E and C set--the other - * bits in the frag_hdr field are irrelevant. - * - * NOTE: Injected LIP packets have a frag_hdr of 0xE100. - * - */ -#define MLFR_LIP_FRAME 0xE100 -#define MLFR_LIP_MASK 0xE000 -#define MLFR_FRAG_HDR_LEN 2 - -#define MLFR_BEGIN_MASK 0x8000 -#define MLFR_END_MASK 0x4000 -#define MLFR_BEGIN_END_MASK (MLFR_BEGIN_MASK|MLFR_END_MASK) -#define MLFR_BEGIN_END_SHIFT 14 - -#define MLFR_SEQ_NUM_HI_MASK 0x1E00 -#define MLFR_SEQ_NUM_HI_SHIFT 1 -#define MLFR_SEQ_NUM_LO_MASK 0x00FF - -/* - * these are needed in the micro-code, for optimizations - */ -#define MLFR_BEGIN_END_MASK_BYTE 0xC0 - - -/* - * FRF.12 definitions - */ -typedef struct frf12_hdr_type_ { - u16 address; - u16 control_nlpid; - u16 frag_hdr; - u8 data[0]; -} frf12_hdr_type; - -#define FRF12_FRAG_HDR_LEN sizeof(frf12_hdr_type) - -#define FRF12_BEGIN_MASK 0x8000 -#define FRF12_END_MASK 0x4000 -#define FRF12_BEGIN_END_MASK (FRF12_BEGIN_MASK|FRF12_END_MASK) -#define FRF12_BEGIN_END_SHIFT 8 - -#define FRF12_SEQ_NUM_HI_MASK 0x1E00 -#define FRF12_SEQ_NUM_HI_SHIFT 1 -#define FRF12_SEQ_NUM_LO_MASK 0x00FF -#define FRF12_BEGIN_END_MASK_BYTE 0xC0 - - - -/* -** -** MLP over Frame Relay -** The ppp hdr can be either a -** an MLP hdr or a PPP hdr -** -** MLP can be compressed or not: -** a) 0xff03003d -** b) 0x003d -** c) 0x3d -** followed by: -** 1 byte with begin/end bits -** 3 bytes of a sequence # -** -** PPP can be also be compressed or not. -** Only these will be fwded: -** a) 0xff030021 -** b) 0xff0321 -** c) 0x0021 -** d) 0x21 -** -** -*/ -typedef struct mlpofr_hdr_type { - u16 address; - u16 control_nlpid; - u8 ppp_header[0]; -} mlpofr_hdr_type; - -/* -** ATM - -*/ - -/* - * channel_handle is defined as follows: - * - * bits 15 = reserved (must be 0) - * bits 14 - 0 = channel handle - * - * - * flags is a bitfield defined as follows: - * - * bits 15 - 13 = proto (PPPoA RFC1661 = 0, - * PPPoE = 1, - * RBE = 2, - * PPPoA Cisco = 3, - * MLPoATM RFC1661 = 4, - * MLPoATM Cisco = 5, - * Reserved = 6-7) - * bit 12 = encap (MUX=0, - * SNAP=1) - * bits 11 - 6 = reserved (must be 0) - * bits 5 - 3 = pkt_type (AAL5 pkt = 0, - * Raw cell (includes F4 OAM) = 1, - * F5 segment OAM cell = 2 - * F5 end-to-end OAM cell = 3 - * Reserved = 4-7) - * bit 2 = EFCI (congestion indication) - * bit 1 = reserved (must be 0) - * bit 0 = CLP (cell loss priority) - */ - -typedef struct apollo_atm_generic_hdr_type { - u16 channel_handle; - u16 flags; -} apollo_atm_generic_hdr_type; - -typedef struct apollo_atm_aal5_snap_hdr_type { - u16 channel_handle; - u16 flags; - u8 dsap; - u8 ssap; - u8 control; - u8 oui[3]; - u16 type; - u8 data[0]; -} apollo_atm_aal5_snap_hdr_type; - -typedef struct atm_aal5_snap_hdr_type { - u8 dsap; - u8 ssap; - u8 control; - u8 oui[3]; - u16 pid; - u16 pad; - u8 data[0]; -} atm_aal5_snap_hdr_type; - - -typedef struct apollo_atm_aal5_snap_hdr1_type { - u16 channel_handle; - u16 flags; - u8 dsap; - u8 ssap; - u8 control; - u8 oui0; - u8 oui1; - u8 oui2; - u16 type; - u8 data[0]; -} apollo_atm_aal5_snap_hdr1_type; - -typedef struct apollo_atm_aal5_clns_hdr_type { - u16 channel_handle; - u16 flags; - u16 type; - u16 data; -} apollo_atm_aal5_clns_hdr_type; - -typedef struct apollo_atm_aal5_ilmi_hdr_type { - u16 channel_handle; - u16 flags; - u8 data[0]; -} apollo_atm_aal5_ilmi_hdr_type; - -typedef struct apollo_atm_aal5_mux_hdr_type { - u16 channel_handle; - u16 flags; - u8 data[0]; -} apollo_atm_aal5_mux_hdr_type; - -typedef struct apollo_atm_oam_f4_hdr_type { - u16 channel_handle; - u16 flags; - /* - * gcf_vpi_vci_pt_clp is a bitfield defined as follows: - * - * bits 31 - 28 = GCF - * bits 27 - 20 = VPI - * bits 19 - 4 = VCI - * bits 3 - 1 = PT - * bit 0 = CLP - */ - u32 gcf_vpi_vci_pt_clp; - u8 data[0]; -} apollo_atm_oam_f4_hdr_type; - -#define APOLLO_ATM_OAM_F4_HDR_PT_MASK 0xE -#define APOLLO_ATM_OAM_F4_HDR_PT_SHIFT 1 - -typedef struct apollo_atm_oam_f5_hdr_type { - u16 channel_handle; - u16 flags; - u8 data[0]; -} apollo_atm_oam_f5_hdr_type; - -#define APOLLO_IRONBUS_EXT_LESS_PROTO 0xFFFF0FFF -#define APOLLO_CHANNEL_HANDLE_MASK 0xFFFF -#define APOLLO_PKT_TYPE_MASK 0x0038 -#define APOLLO_PKT_TYPE_SHIFT 3 -#define APOLLO_FLAG_CLP_MASK 0x0001 -#define APOLLO_FLAG_CLP_BIT 0 - -#define APOLLO_CHANNEL_HANDLE_RES_0 0x0000 -/* - * The 1 byte HEC field is removed by the line card. - */ -#define APOLLO_F4_RX_CELL_SIZE 52 -#define APOLLO_F5_RX_CELL_SIZE 52 - -#define APOLLO_ATM_PACKET_TYPE_AAL5 0 -#define APOLLO_ATM_PACKET_TYPE_F4 1 -#define APOLLO_ATM_PACKET_TYPE_F5_SEG 2 -#define APOLLO_ATM_PACKET_TYPE_F5_E_TO_E 3 -#define APOLLO_ATM_PACKET_TYPE_4 4 -#define APOLLO_ATM_PACKET_TYPE_5 5 -#define APOLLO_ATM_PACKET_TYPE_6 6 -#define APOLLO_ATM_PACKET_RESERVED 7 - -#define APOLLO_AAL5_MUX_IP_HDR_LEN 4 -#define APOLLO_AAL5_SNAP_HDR_LEN 12 - -#define APOLLO_RCV_IRON_BUS_EXT_LEN 4 -#define APOLLO_TX_IRON_BUS_EXT_LEN 8 - -/* - * MLPoA type definitions - */ -#define MLPOA_CISCO_HDR 0xFF03 -#define MLPOA_SNAP_HDR_LEN 4 -#define MLPOA_CISCO_HDR_LEN 2 - -/************************************************************/ -/* PTA PLUS ATM ENCAPSULATIONS */ - -/* RBE header 28 bytes*/ -typedef struct apollo_atm_aal5_llcsnap_rbe_hdr_type { - u16 channel_handle; - u16 flags; - u8 dsap; - u8 ssap; - u8 control; - u8 oui[3]; - u16 pid; - u16 pad; - /* enet header within */ - u8 daddr[6]; - u8 saddr[6]; - u16 type; - u8 data[0]; /* start of IP */ -} apollo_atm_aal5_llcsnap_rbe_hdr_type; - -/* PPPoEoA header 34 bytes*/ -typedef struct apollo_atm_aal5_llcsnap_pppoe_hdr_type { - u16 channel_handle; - u16 flags; - u8 dsap; - u8 ssap; - u8 control; - u8 oui[3]; - u16 pid; - u16 pad; - /* enet header within */ - u8 daddr[6]; - u8 saddr[6]; - u16 type; - /* pppoe hdr at begining of enet payload */ - u16 vtc; /* version(4b), type(4b) and code(8b) fields */ - u16 sid; - u16 len; - u8 ppp_header[0]; /* PPP header start, no ff03 field present */ -} apollo_atm_aal5_llcsnap_pppoe_hdr_type; - - -/* PPPoA MUX 4 bytes*/ -typedef struct apollo_atm_aal5_mux_pppoa_hdr_type { - u16 channel_handle; - u16 flags; - u8 ppp_header[0]; -} apollo_atm_aal5_mux_pppoa_hdr_type; - - -/* PPPoA SNAP LLC 8 bytes */ -typedef struct apollo_atm_aal5_llcsnap_pppoa_hdr_type { - u16 channel_handle; - u16 flags; - u8 dsap; - u8 ssap; - u8 control; - u8 nlpid; - u8 ppp_header[0]; -} apollo_atm_aal5_llcsnap_pppoa_hdr_type; - -/* MLPoA MUX (generic) */ -typedef struct apollo_atm_aal5_mux_mlpoa_hdr_type { - u16 channel_handle; - u16 flags; - u8 ppp_header[0]; -} apollo_atm_aal5_mux_mlpoa_hdr_type; - -/* MLPoA SNAP LLC */ -typedef struct apollo_atm_aal5_llcsnap_mlpoa_hdr_type { - u16 channel_handle; - u16 flags; - u8 dsap; - u8 ssap; - u8 control; - u8 nlpid; - u8 ppp_header[0]; -} apollo_atm_aal5_llcsnap_mlpoa_hdr_type; - - -#define PPPOA_SNAPLLC_HDR_LEN sizeof(apollo_atm_aal5_llcsnap_pppoa_hdr_type) -#define PPPOA_MUX_HDR_LEN sizeof(apollo_atm_aal5_mux_pppoa_hdr_type) -#define PPPOE_SNAPLLC_HDR_LEN sizeof(apollo_atm_aal5_llcsnap_pppoe_hdr_type) -#define RBE_SNAPLLC_HDR_LEN sizeof(apollo_atm_aal5_llcsnap_rbe_hdr_type) - -/* End PTA PLUS ATM ENCAPSULATIONS */ -/****************************************************************/ - -#define LLCSNAP_PID_DOT3_NOFCS 0x0007 - -/* -** the SNAP header -*/ - -/* - * Note that some of these definitions are split - * up along certain word or half word boundaries - * to help expediate the TMC code. - */ -#define LLC_SNAP_HDR_DSAP 0xAA -#define LLC_SNAP_HDR_SSAP 0xAA -#define LLC_SNAP_HDR_CONTROL 0x03 -#define LLC_SNAP_HDR_OUI_0 0x00 -#define LLC_SNAP_HDR_OUI_1 0x00 -#define LLC_SNAP_HDR_OUI_2 0x00 -#define LLC_SNAP_HDR_OUI_2_CDP 0x0C - -#define LLC_SNAP_HDR_DSAP_SSAP 0xAAAA -#define LLC_SNAP_HDR_DSAP_SSAP_CTRL_OUI0 0xAAAA0300 -#define LLC_SNAP_HDR_CONTROL_OUI 0x03000000 -#define LLC_SNAP_HDR_OUI1_OUI2_CDP 0x000C2000 - - - -/* -** SRP -*/ - -/* - * The v2_gen_hdr is a 2-byte field that contains the following: - * - * [ ttl | ring_id | mode | priority | parity ] - * bits 8 1 3 3 1 - */ -typedef struct srp_hdr_type { - u16 v2_gen_hdr; - u8 dest_addr[6]; - u8 src_addr[6]; - u16 protocol; - u8 data[0]; -} srp_hdr_type; - -#define SRP_HDR_LEN 16 - -#define SRP_IB_CHANNEL_CONTROL 0x0000 -#define SRP_IB_CHANNEL_DATA_HI 0x0001 -#define SRP_IB_CHANNEL_DATA_LO 0x0002 - -#define SRP_RING_ID_MASK 0x0080 -#define SRP_RING_ID_BIT 7 - -#define SRP_MODE_BITS_MASK 0x0070 -#define SRP_MODE_BITS_SHIFT 4 -#define SRP_MODE_CONTROL_TOPOLOGY 4 -#define SRP_MODE_CONTROL_IPS 5 -#define SRP_MODE_DATA 7 - -#define SRP_PRIORITY_BITS_MASK 0x000E -#define SRP_PRIORITY_BITS_SHIFT 1 -#define SRP_PRIORITY_HIGH 7 -#define SRP_PRIORITY_PAK_PRIORITY 6 - -/* this is for the tmc code */ -#define SRP_INV_PRIORITY_BITS_MASK 0xFFF1 - -#define SRP_PROT_CONTROL_TOPOLOGY 0x2007 -#define SRP_PROT_CONTROL_IPS 0x2007 - -/* this is for the tmc code */ -#define SRP_TRUE 1 -#define SRP_FALSE 0 - -/* -** MPLS -*/ -#define MPLS_EOS_BIT 0x00000100 -#define MPLS_EOS_SHIFT 8 -#define MPLS_LABEL_SIZE 4 -#define MAX_MPLS_LABEL_STACK 6 -#define MPLS_LABEL_MASK 0xfffff000 -#define MPLS_LABEL_SHIFT 12 -#define MPLS_TTL_MASK 0x000000ff -#define MPLS_EXP_MASK 0x00000e00 -#define MPLS_EXP_SHIFT 9 -#define MPLS_EXP_TTL_MASK 0x00000eff - - - -typedef union _layer2 { - hdlc_hdr_type hdlc; - ppp_comp_hdr_type ppp; - ethernet_arpa_hdr_type eth_arpa; - ethernet_vlan_hdr_type eth_vlan; - ethernet_qinq_hdr_type eth_qinq; - ethernet_lacp_hdr_type eth_lacp; - ethernet_bpdu_hdr_type eth_bpdu; - ethernet_802p3_hdr_type eth_802p3; - ethernet_vlan_802p3_hdr_type eth_vlan_802p3; - ethernet_pppoe_arpa_hdr_type eth_pppoe_arpa; /* PTA plus */ - ethernet_pppoe_vlan_hdr_type eth_pppoe_vlan; /* PTA plus */ - ethernet_pppoe_qinq_hdr_type eth_pppoe_qinq; /* PTA plus */ - frame_relay_hdr_type frame_relay; - fr_snap_hdr_type fr_snap; - mlfr_hdr_type mlfr; - mlpofr_hdr_type mlpofr; - frf12_hdr_type frf12; - apollo_atm_generic_hdr_type atm_generic; - apollo_atm_aal5_snap_hdr_type atm_aal5_snap; - apollo_atm_aal5_snap_hdr1_type atm_aal5_snap1; - apollo_atm_aal5_clns_hdr_type atm_aal5_clns; - apollo_atm_aal5_ilmi_hdr_type atm_aal5_ilmi; - apollo_atm_aal5_mux_hdr_type atm_aal5_mux; - apollo_atm_oam_f4_hdr_type atm_oam_f4; - apollo_atm_oam_f5_hdr_type atm_oam_f5; - apollo_atm_aal5_llcsnap_rbe_hdr_type atm_aal5_rbe_snapllc; /* PTA plus */ - apollo_atm_aal5_llcsnap_pppoe_hdr_type atm_aal5_pppoe_snapllc; /* PTA plus */ - apollo_atm_aal5_mux_pppoa_hdr_type atm_aal5_pppoa_mux; /* PTA plus */ - apollo_atm_aal5_llcsnap_pppoa_hdr_type atm_aal5_pppoa_snapllc; /* PTA plus */ - apollo_atm_aal5_mux_mlpoa_hdr_type mlpoa_generic; - apollo_atm_aal5_llcsnap_mlpoa_hdr_type mlpoa_snapllc; - srp_hdr_type srp; -} layer2_t; - -/* - * Define the Common OAM cell format - F4 & F5 cells - * For F4 cells: - * VPI == User VPI - * VCI == (3 == Segment), (4 == End-to-End) - * - * For F5 cells: - * VPI == User VPI - * VCI == User VCI - * PT == (100 == Segment, 101 == End-to-End) - * - * OAM Cell Type & Function Type: - * - * OAM_TYPE = (0001 == Fault management) - * OAM_FUNC == (0000 == AIS, 0001 == RDI, 0100 == CC, - * 1000 == loopback) - * - * OAM_TYPE = (0010 == Performance management) - * OAM_FUNC == (0000 == Forward Monitoring(FM), - * 0001 == Backward monitoring(BR), - * 0010 == Monitoring & reporting (FM+BR)) - * - * OAM_TYPE = (1000 == Activation/Deactivation) - * OAM_FUNC == (0000 == Performance Monitoring, - * 0001 == Continuity Check) - * - * OAM_TYPE = (1111 == Sytem Management) - * OAM_FUNC == (0001 == Security - non-real-time, - * 0010 == Security - real-time) - * - */ -#define ATM_OAM_FAULT_MGMT 0x1 /* OAM Fault mgmt. code */ -#define ATM_OAM_PRFRM_MGMT 0x2 /* performance mgmt code */ -#define ATM_OAM_ACT_DEACT 0x8 /* OAM Activation/Deactivation - code */ -#define ATM_OAM_SYSTEM_MGMT 0xF /* System Management code */ - -#define ATM_OAM_AIS_FUNC 0x0 /* AIS function type */ -#define ATM_OAM_RDI_FUNC 0x1 /* RDI function type */ -#define ATM_OAM_CC_FUNC 0x4 /* OAM CC FM function code */ -#define ATM_OAM_LOOP_FUNC 0x8 /* Loopback function type */ - -#define ATM_OAM_F5_SEGMENT 0x4 /* Segment function */ -#define ATM_OAM_F5_ENDTOEND 0x5 /* End-to-End function */ -#define ATM_OAM_F4_SEGMENT 0x3 /* Segment function */ -#define ATM_OAM_F4_ENDTOEND 0x4 /* End-to-End function */ -#define ATM_OAM_F4_PTI_ZERO 0x0 /* PTI=0 for F4 OAM */ - -typedef struct atm_oam_hdr_t_ { - unsigned oam_gfc:4; /* GFC */ - unsigned oam_vpi:8; /* VPI */ - unsigned oam_vci_ms:4; /* VCI (Most Significant Bits) */ - - unsigned oam_vci_ls:12; /* VCI (Least Significant Bits) */ - unsigned oam_pt:3; /* Payload Type */ - unsigned oam_clp:1; /* Cell Loss Priority */ - u8 data[0]; -} atm_oam_hdr_t; - -typedef struct atm_oam_type_func_t_ { - u8 oam_type:4; - u8 oam_func:4; - u8 data[0]; -} atm_oam_type_func_t; - -/* -** IP Version 4 header -*/ - -/* - * version_hdr_len_words [7-4] IP Header Version - * [3-0] IP Header Length in 32-bit words - * tos Type of Service - * total_len_bytes Total IP datagram length in bytes - * (including IP header) - * identification Unique fragmentation identifier - * frag_flags_offset [15-13] Fragmentation flags - * [12-0] Fragmentation Offset - * ttl Time To Live - * protocol_id Protocol Identifier - * checksum 16-bit 1's complement IP Header checksum - * src_addr IP Source Address - * dest_addr IP Destination Address - */ -typedef struct ipv4_header { - u8 version_hdr_len_words; - u8 tos; - u16 total_len_bytes; - u16 identification; - u16 frag_flags_offset; - u8 ttl; - u8 protocol; - u16 checksum; - u32 src_addr; - u32 dest_addr; - u8 data[0]; -} ipv4_header; - -/*OPTIONS PACKET TYPE - * +-+-+-+-+-+-+-+-+ - * |C| CL| OP | - * +-+-+-+-+-+-+-+-+ - */ -typedef struct ipv4_options { - u8 copy :1 ; - u8 op_class :2 ; - u8 option :5 ; - u8 pad ; -}ipv4_options; - -#define LOOSE_SOURCE_ROUTE 131 -#define STRICT_SOURCE_ROUTE 137 -#define IPV4_NO_OPTIONS_HDR_LEN (sizeof(ipv4_header)) -#define IPV4_VERSION 4 -#define IPV4_HEADER_LENGTH_WORDS 5 -#define IPV4_VERSION_HDR_LEN_FIELD ((u8) 0x45) -#define IPV4_HEADER_LENGTH_WORDS 5 -#define IPV4_MIN_HEADER_LENGTH_BYTES 20 -#define IP_HDR_LEN sizeof(ipv4_header) -#define IPV4_VERSION_VALUE_SHIFT 4 - -#define IPV4_FRAG_OFFSET_MASK (0x1fff) -#define IPV4_FRAG_MF_MASK (0x2000) -#define IPV4_FRAG_MF_SHIFT (13) - -/* 0.0.0.0 */ -#define IP_BOOTP_SOURCE_ADDRESS 0 -/* 255.255.255.255 */ -#define IP_LIMITED_BROADCAST_ADDRESS 0xFFFFFFFF - -/* - * IPv4 header - version & length fields - */ -#define IP_VER_LEN 0x45 -#define IP_VER 0x4 -#define IP_MIN_LEN 0x5 -#define IP_VER_MASK 0xf0 -#define IP_LEN_MASK 0x0f - -/* - * IPv4 header - TOS field - */ -#define PS_IP_TOS_MASK 0xff -#define IP_PRECEDENCE_SHIFT 5 /* shift value up to precedence bits */ -#define IP_DSCP_SHIFT 2 /* shift value up to dscp bits */ - -#define IP_TOS_PRECEDENCE 0xe0 /* mask of precedence in tos byte */ -#define IP_TOS_NO_PRECEDENCE 0x1f -#define IP_TOS_LOW_DELAY 8 /* values must be shifted 1 bit */ -#define IP_TOS_HIGH_TPUT 4 /* before using */ -#define IP_TOS_HIGH_RELY 2 -#define IP_TOS_LOW_COST 1 -#define IP_TOS_NORMAL 0 -#define IP_TOS_MASK 0x1e /* mask of tos in tos byte */ -#define IP_TOS_MBZ_MASK 0x01 /* mask for MZB bit in tos byte */ -#define IP_TOS_DSCP 0xfc /* mask for dscp in tos byte */ -#define IP_TOS_NO_DSCP 0x03 - -#define IP_TOS_METRIC_TYPES 8 -#define IP_TOS_SHIFT 1 - -#define IP_TOS_PRECEDENCE_MASK (IP_TOS_PRECEDENCE | IP_TOS_MASK) - -/* - * IP TOS Precedence values (High order 3 bits) - */ -#define TOS_PREC_NET_CONTROL 0xe0 -#define TOS_PREC_INET_CONTROL 0xc0 -#define TOS_PREC_CRIT_ECP 0xa0 -#define TOS_PREC_FLASH_OVER 0x80 -#define TOS_PREC_FLASH 0x60 -#define TOS_PREC_IMMEDIATE 0x40 -#define TOS_PREC_PRIORITY 0x20 -#define TOS_PREC_ROUTINE 0x00 -#define TOS_PREC_ILLEGAL 0xff /* invalid precedence value */ - -#define TOS_PREC_NET_CONTROL_NUM 7 -#define TOS_PREC_INET_CONTROL_NUM 6 -#define TOS_PREC_CRIT_ECP_NUM 5 -#define TOS_PREC_FLASH_OVER_NUM 4 -#define TOS_PREC_FLASH_NUM 3 -#define TOS_PREC_IMMEDIATE_NUM 2 -#define TOS_PREC_PRIORITY_NUM 1 -#define TOS_PREC_ROUTINE_NUM 0 - - - -/* - * IPv4 header - flags and fragment offset fields - */ -#define IP_FRAG_OFFSET_MASK 0x1fff - - -#define IP_FRAG_MORE_MASK 0x2000 -#define IP_FRAG_DF_MASK 0x4000 -#define IP_FRAG_UNDEF_MASK 0x8000 -#define IP_FRAG_NO_DF_SET 0x0000 - -/* bit definitions for fragment flags */ -#define IP_FRAG_MORE_BIT 13 -#define IP_FRAG_DF_BIT 14 -#define IP_FRAG_UNDEF_BIT 15 - -/* - * IPv4 header - TTL field - */ -#define TTL_DEFAULT 255 -#define TTL_1 1 -#define TTL_2 2 -#define TTL_255 255 - - -/* - * IPv4 header - protocol field - * - * ICMP_PROT 1 ICMP - * IGMP_PROT 2 group management - * GGP_PROT 3 GGP - * IPINIP_PROT 4 IPv4 in IPv4 encapsulation - * TCP_PROT 6 TCP - * EGP_PROT 8 EGP - * IGRP_PROT 9 IGRP - * UDP_PROT 17 UDP - * HMP_PROT 20 HMP - * RDP_PROT 27 RDP - * IPV6_INIP_PROT 41 IPV6 in IPv4 encapsulation - * RSVP_PROT 46 RSVP - * GRE_PROT 47 GRE - * ESP_PROT 50 ESP - * AHP_PROT 51 AHP - * SDNS0_PROT 53 SNDS - * NHRP_PROT 54 NHRP - * SDNS1_PROT 55 SDNS1 - * HELLO_PROT 63 HELLO - * ND_PROT 77 ND - * EONIP_PROT 80 CLNS over IP - * VINES_PROT 83 Banyan Vines - * NEWIGRP_PROT 88 IGRP - * OSPF_PROT 89 OSPF - * FST_RSRB_PROT 90 RSRB - * FST_DLSW_PROT 91 DLSW - * NOSIP_PROT 94 KA9Q/NOS compatible IP over IP - * PIM_PROT 103 PIMv2 - * PCP_PROT 108 PCP - * PGM_PROT 113 PGM - * MAX_PROT 113 maximum protocol number in the above list, - * used in creating case registry - */ -#define ICMP_PROT 1 -#define IGMP_PROT 2 -#define GGP_PROT 3 -#define IPINIP_PROT 4 -#define TCP_PROT 6 -#define EGP_PROT 8 -#define IGRP_PROT 9 -#define UDP_PROT 17 -#define HMP_PROT 20 -#define RDP_PROT 27 -#define IPV6_INIP_PROT 41 -#define RSVP_PROT 46 -#define GRE_PROT 47 -#define ESP_PROT 50 -#define AHP_PROT 51 -#define SDNS0_PROT 53 -#define NHRP_PROT 54 -#define SDNS1_PROT 55 -#define HELLO_PROT 63 -#define ND_PROT 77 -#define EONIP_PROT 80 -#define VINES_PROT 83 -#define NEWIGRP_PROT 88 -#define OSPF_PROT 89 -#define FST_RSRB_PROT 90 -#define FST_DLSW_PROT 91 -#define NOSIP_PROT 94 -#define PIM_PROT 103 -#define PCP_PROT 108 -#define PGM_PROT 113 -#define MAX_PROT 113 - -/*Well Known Application ports */ -#define FTP_PORT 21 /* For control connection */ -/* - * TCP header - */ -typedef struct tcp_hdr_type { - u16 src_port; - u16 dest_port; - u32 seq_num; - u32 ack_num; - u8 hdr_len; - u8 flags; - u16 window_size; - u16 tcp_checksum; - u16 urgent_pointer; - u8 option_data[0]; -} tcp_hdr_type; - -#define TCP_FLAG_FIN 0x01 -#define TCP_FLAG_SYN 0x02 -#define TCP_FLAG_RST 0x04 -#define TCP_FLAG_PUSH 0x08 -#define TCP_FLAG_ACK 0x10 -#define TCP_FLAG_URG 0x20 -#define TCP_FLAG_ECE 0x40 -#define TCP_FLAG_CWR 0x80 - -/* - * TCP Option - */ -typedef struct tcp_option_s { - u8 kind; - u8 length; - u8 data[0]; -} tcp_option_t; - -#define TCP_END_OPTIONS_LIST 0 -#define TCP_OPTION_NOP 1 -#define TCP_OPTION_MSS 2 -#define TCP_OPTION_WINDOW_SCALE 3 -#define TCP_OPTION_SACK_PERMITTED 4 -#define TCP_OPTION_SACK_DATA 5 -#define TCP_OPTION_ECHO 6 -#define TCP_OPTION_ECHO_REPLY 7 -#define TCP_OPTION_TSOPT 8 -/* - 9 2 Partial Order Connection Permitted. RFC 1693 - 10 3 Partial Order Service Profile. RFC 1693 - 11 6 CC, Connection Count. RFC 1644 - 12 6 CC.NEW RFC 1644 - 13 6 CC.ECHO RFC 1644 - 14 3 TCP Alternate Checksum Request. RFC 1146 - 15 Variable. TCP Alternate Checksum Data. RFC 1146 - 16 Skeeter. - 17 Bubba. - 18 3 Trailer Checksum Option. -*/ -#define TCP_OPTION_MD5_SIGNATURE 19 -/* - 20 SCPS Capabilities. - 21 Selective Negative Acknowledgements. - 22 Record Boundaries. - 23 Corruption experienced. - 24 SNAP. - 25 - 26 TCP Compression Filter. -*/ -#define TCP_OPTION_QUICK_START 27 - -#define TCP_OPTION_NUM_MAX 27 - -#ifdef TARGET_CISCO -#define tcp_printf(format_str, params...) //printf(format_str, ## params) -#else -#define tcp_printf(format_str, params...) printf(format_str, ## params) -#endif - -typedef struct udp_hdr_type { - u16 src_port; - u16 dest_port; - u16 udp_length; - u16 udp_checksum; -} udp_hdr_type_t; - -#define TYPE_IPV6 0x86dd -#define TYPE_IPV4 0x0800 - -/* - * version_trafficclass_flowlabel [31:28] IP Header Version, - [27:20] traffic_class, - [19:0] flow_label[20] - * payload_length Length of packet in bytes excluding header size(s) - * next_header Identifies the type of header following the IPv6 header - * hop_limit Decremented by 1 by each forwarding node, packet discarded when zero - * src_addr IPv6 Source Address - * dst_addr IPv6 Destination Address - */ -typedef struct ipv6_header { - u32 version_trafficclass_flowlabel; - u16 payload_length; - u8 next_header; - u8 hop_limit; - u32 src_addr[4]; - u32 dst_addr[4]; - u8 data[0]; -} ipv6_header_t; - -#define IPV6_HDR_LEN 40 -#define IPV6_HDR_LEN_WORDS 10 -#define IPV6_FLABLE_MASK 0x000FFFFF -#define IPV6_MIN_PATH_MTU (1280) - -#define IPV6_GET_IP_VER(ih) ((clib_net_to_host_u32((ih) \ - ->version_trafficclass_flowlabel) >> 28) & 0xf) -#define IPV6_GET_TOS(ih) ((clib_net_to_host_u32((ih) \ - ->version_trafficclass_flowlabel) >> 20) & 0xff) -#define IPV6_GET_FLOW_LABEL(ih) ((clib_net_to_host_u32((ih) \ - ->version_trafficclass_flowlabel)) & 0xfffff) - -#define IPV6_VERSION_VALUE (6) -#define IPV6_VERSION_VALUE_SHIFT (28) -#define IPV6_TRAFFIC_CLASS_VALUE_SHIFT (20) -#define IPV6_TRAFFIC_CLASS_VALUE_MASK (0xff) - -#define IPV6_PROTO_HOPOPTS 0 -#define IPV6_PROTO_TCP 6 -#define IPV6_PROTO_UDP 17 -#define IPV6_PROTO_IPV6 41 -#define IPV6_PROTO_ROUTING 43 -#define IPV6_PROTO_FRAGMENT 44 -#define IPV6_PROTO_DESTOPTS 60 -#define IPV6_PROTO_ESP 50 -#define IPV6_PROTO_AH 51 -#define IPV6_PROTO_ICMPV6 58 -#define IPV6_PROTO_NONE 59 - -/* standard v6 extension header are 2 tytes - * one byte next header - * one byte header length - */ - -typedef struct ipv6_frag_header { - u8 next_header; - u8 reserved; - u16 frag_offset_res_m; - u32 identification; -} ipv6_frag_header_t; - -#define IPV6_FRAG_HDR_LEN (sizeof(ipv6_frag_header_t)) - -#define IPV6_FRAG_OFFSET_MASK (0xFFF8) -#define IPV6_FRAG_OFFSET_SHIFT (3) -#define IPV6_FRAG_MORE_FRAG_MASK (0x0001) - -#define IPV6_TOS_SHIFT 20 -#define IPV6_TOS_SHIFT_HLF_WD 4 -#define IPV6_NEXT_HDR_SHIFT 8 - -typedef struct ipv6_routing_header { - u8 next_header; - u8 hdr_ext_len; - u8 routing_type; - u8 segments_left; - u8 data[0]; -} ipv6_routing_header_t; -#define IPV6_ROUTING_HDR_LEN (sizeof(ipv6_routing_header_t)) - -typedef struct ipv6_hop_header { - u8 next_header; - u8 hdr_ext_len; - u8 options[0]; -} ipv6_hop_header_t; -#define IPV6_HOP_LEN (sizeof(ipv6_hop_header_t)) - -typedef struct ipv6_dest_opt_header { - u8 next_header; - u8 hdr_ext_len; - u8 options[0]; -} ipv6_dest_opt_header_t; -#define IPV6_DESTOPT_LEN (sizeof(ipv6_dest_opt_header_t)) - - -/* Definition of ICMP header */ -typedef struct icmp_v4_s { - u8 type; - u8 code; - u16 checksum; - u16 identifier; - u16 sequence; -} icmp_v4_t; - -#define ICMPV4_HDR_SIZE (sizeof(icmp_v4_t)) -#define ICMPV4_ECHOREPLY 0 /* Type: echo reply */ -#define ICMPV4_ECHO 8 /* Type: echo request */ - -#define ICMPV4_UNREACHABLE 3 /* Type: destination unreachable */ -#define ICMPV4_UNRNET 0 /* Code: Net unreachable */ -#define ICMPV4_UNRHOST 1 /* Code: host unreachable */ -#define ICMPV4_UNRPROT 2 /* Code: protocol unreachable */ -#define ICMPV4_UNRPORT 3 /* Code: port unreachable */ -#define ICMPV4_UNRFRAG 4 /* Code: frag req DF set */ -#define ICMPV4_UNRADMIN 13 /* Code: administratively prohib. */ -#define ICMPV4_SOURCEROUTE_FAILED 5 /* Code: administratively prohib. */ - -#define ICMPV4_SRC_ROUTE_FAIL 5 /* Code: Source Route Failed */ -#define ICMPV4_NO_ROUTE_DESTN_8 8 /* Code: No Route to Destn */ -#define ICMPV4_NO_ROUTE_DESTN_11 11 /* Code: No Route to Destn */ -#define ICMPV4_NO_ROUTE_DESTN_12 12 /* Code: No Route to Destn */ - -#define ICMPV4_ADMIN_PROH_9 9 /* Code: Administratively Prohibited */ -#define ICMPV4_ADMIN_PROH_10 10 /* Code: Administratively Prohibited */ -#define ICMPV4_PREC_CUTOFF 15 /* Code: Precedence Cutoff */ - - -#define ICMPV4_TIMEEXCEEDED 11 /* Type: time exceeded */ -#define ICMPV4_TIMTTL 0 /* Code: ttl in transit code */ - -#define ICMPV4_PARAMETER_PROBLEM 12 /* Type: Parameter Problem */ -#define ICMPV4_PARAM_ERROR 0 /* Code: Pointer to Error */ -#define ICMPV4_MISSING_OPTION_CODE 1 /* Code: Mission option */ -#define ICMPV4_PARAM_BAD_LEN 2 /* Code: Bad Length */ - -#define ICMPV4_CONVERSION_ERROR 31 -#define ICMPV4_SOURCE_QUENCH 4 -#define ICMPV4_REDIRECT 5 -#define ICMPV4_TIMESTAMP 13 -#define ICMPV4_TIMESTAMP_REPLY 14 -#define ICMPV4_INFO_REQUEST 15 -#define ICMPV4_INFO_REPLY 16 -#define ICMPV4_ADDR_MASK_REQUEST 17 -#define ICMPV4_ADDR_MASK_REPLY 18 - -typedef struct icmp_v6_s { - - u8 type; - u8 code; - u16 checksum; - - u32 data[0]; -} icmp_v6_t; - -typedef struct pseudo_v6_header { - u32 src_addr[4]; - u32 dst_addr[4]; - u16 payload_length; - u16 next_header; -} pseudo_v6_header_t; - - -#define ICMPV6_ECHO 128 -#define ICMPV6_ECHO_REPLY 129 -#define ICMPV6_PKT_TOO_BIG 2 -#define ICMPV6_TIMEEXCEEDED 3 -#define ICMPV6_TIMTTL 0 -#define ICMPV6_PARAMETER_PROBLEM 4 -#define ICMPV6_UNREACHABLE 1 -#define ICMPV6_NEIGHBOR_SOLICITAION 135 -#define ICMPV6_NEIGHBOR_ADVT 136 -/* ICMP V6 generated packet size */ -#define ICMPV6_ERR_SIZE 48 -#define ICMPV6_HDR_SIZE (sizeof(icmp_v6_t) +sizeof(u32)) - -/* Code for Type 1 */ -#define ICMPV6_UNRDESTN 0 /* Code: No route to Desnt */ -#define ICMPV6_ADM_PROH 1 /* Code: Adminitrative Prohibited */ -#define ICMPV6_SRC_ADD_SCOPE 2 /* Code: Source Address beyond scope */ -#define ICMPV6_UNRHOST 3 /* Code: Host Unreachable */ -#define ICMPV6_UNRPORT 4 /* Code: Port UnReachable */ - -#define ICMPV6_UNRPROT 1 /* type 4 - Code: No route to Desnt */ - -#define ICMPV6_PTB_CODE 0 /* Code: For PTB */ -#define ICMPV6_PARAM_CODE 0 /* Code: For Parameter Problem */ -#define ICMPV6_UNREC_HDR 1 /* Code: For Parameter Problem */ -#define ICMPV6_SRC_ADD_FAIL 5 /* Code: For Source address failed */ -#define ICMP_ECHO_REPLY_CODE 0 -#define DEFAULT_TTL_HOPLIMIT_VAL 64 - -typedef struct pptp_hdr_type { - - u16 flags_ver; - u16 proto_type; /* PPP = 0x880B */ - u16 payload_len; - u16 call_id; - u32 seq_no; - u32 ack_no; - -} pptp_hdr_type_t; - -/* - * NAME - * - * tcp_findoption - * - * SYNOPSIS - * u8* tcp_findoption (tcp_hdr_t *tcp, uchar option) - * - * PARAMETERS - * tcp - pointer to TCP header - * option - TCP option - * - * RETURNS - * This function returns a pointer to the option found, - * otherwise returns null. - * - * - * DESCRIPTION - * This function searches the option and returns a pointer to the - * matched option field containing option kind/length/data sub-fields. - * - */ -static inline u8* tcp_findoption (tcp_hdr_type *tcp, u8 option) -{ - u8*data; - u8 len, optlen; - - data = tcp->option_data; - len = ((tcp->hdr_len>>4) << 2) - sizeof(tcp_hdr_type); - -#define MAXTCPOPTIONBYTES 40 -#define MINTCPOPTIONLENGTH 2 - - while (len) { - if (PREDICT_TRUE(option == data[0])) { - return (data); - } else { - switch (data[0]) { - case TCP_END_OPTIONS_LIST: - return (NULL); - case TCP_OPTION_NOP: - len -= 1; - data += 1; - break; - default: - /* Sanity check the length. */ - optlen = data[1]; - if ((optlen < MINTCPOPTIONLENGTH) || - (optlen > MAXTCPOPTIONBYTES) || - (optlen > len)) { - return (NULL); - } - len -= optlen; - data += optlen; - break; - } - } - } - - return (NULL); -} - - -static inline u32 crc_calc (ipv4_header *ipv4) -{ - u16 *ipv4_word_ptr = (u16 *) ipv4; - u32 crc32; - /* - * Add all fields except the checksum field - */ - crc32 = (u32)clib_net_to_host_u16(*ipv4_word_ptr) + - (u32)clib_net_to_host_u16(*(ipv4_word_ptr + 1)) + - (u32)clib_net_to_host_u16(*(ipv4_word_ptr + 2)) + - (u32)clib_net_to_host_u16(*(ipv4_word_ptr + 3)) + - (u32)clib_net_to_host_u16(*(ipv4_word_ptr + 4)) + - (u32)clib_net_to_host_u16(*(ipv4_word_ptr + 6)) + - (u32)clib_net_to_host_u16(*(ipv4_word_ptr + 7)) + - (u32)clib_net_to_host_u16(*(ipv4_word_ptr + 8)) + - (u32)clib_net_to_host_u16(*(ipv4_word_ptr + 9)); - - /* Add in the carry of the original sum */ - crc32 = (crc32 & 0xFFFF) + (crc32 >> 16); - /* Add in the carry of the final sum */ - crc32 = (crc32 & 0xFFFF) + (crc32 >> 16); - - return crc32; -} - -#endif /* __TCP_HEADER_DEFINITIONS_H__ */ diff --git a/plugins/plugins/vcgn/vcgn_classify.c b/plugins/plugins/vcgn/vcgn_classify.c deleted file mode 100644 index 18cc4ba0..00000000 --- a/plugins/plugins/vcgn/vcgn_classify.c +++ /dev/null @@ -1,1508 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * 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 -#include -#include -#include -#include -#include - -#include -#include - -#include "cnat_db.h" -#include "cnat_global.h" -#include "cnat_cli.h" -#include "cnat_config.h" -#include "cnat_logging.h" -#include "cnat_config_api.h" -#include "cnat_show_api.h" -#include "cnat_show_response.h" -#include "cnat_ipv4_udp.h" -#include "cnat_common_api.h" - -#include - -typedef struct { - u32 cached_next_index; - - /* inside, outside interface handles */ - u32 * inside_sw_if_index_table; - u32 * outside_sw_if_index_table; - - /* convenience variables */ - vlib_main_t * vlib_main; - vnet_main_t * vnet_main; - u8 cnat_db_initalized; -} vcgn_classify_main_t; - -typedef struct { - /* $$$$ fill in with per-pkt trace data */ - u32 next_index; - u32 sw_if_index; - u32 orig_dst_address; - u16 orig_dst_port; -} vcgn_classify_trace_t; - -#define FIND_MY_VRF_USING_I_VRF_ID \ - my_vrfmap_found = 0; \ - pool_foreach (my_vrfmap, cnat_map_by_vrf, ({ \ - if (my_vrfmap->i_vrf_id == i_vrf_id) { \ - my_vrfmap_found = 1; \ - my_vrfmap_temp = my_vrfmap; \ - break; \ - } \ - })); - - -/* packet trace format function */ -static u8 * format_swap_trace (u8 * s, va_list * args) -{ - CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); - CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); - vcgn_classify_trace_t * t = va_arg (*args, vcgn_classify_trace_t *); - - s = format (s, "VCGN_CLASSIFY: dst %U dst_port %d sw_if_index %d next %d", - format_ip4_address, (ip4_header_t *) &t->orig_dst_address, - clib_net_to_host_u16(t->orig_dst_port), - t->sw_if_index, t->next_index); - return s; -} - -vcgn_classify_main_t vcgn_classify_main; - -vlib_node_registration_t vcgn_classify_node; - -#define foreach_vcgn_classify_error \ -_(PACKETS_RECEIVED, "total packets received") \ -_(V4_PACKETS_PROCESSED, "ipv4 packets processed for vCGN") \ -_(V4_PACKETS_PUNTED, "ipv4 packets punted") \ -_(V6_PACKETS_PUNTED, "ipv6 packets punted") \ -_(MPLS_PACKETS_PUNTED, "mpls unicast packets punted") \ -_(ETH_PACKETS_PUNTED, "ethernet packets punted") - - -typedef enum { -#define _(sym,str) VCGN_CLASSIFY_ERROR_##sym, - foreach_vcgn_classify_error -#undef _ - VCGN_CLASSIFY_N_ERROR, -} vcgn_classify_error_t; - -static char * vcgn_classify_error_strings[] = { -#define _(sym,string) string, - foreach_vcgn_classify_error -#undef _ -}; - -/* - * To drop a pkt and increment one of the previous counters: - * - * set b0->error = error_node->errors[VCGN_CLASSIFY_ERROR_EXAMPLE]; - * set next0 to a disposition index bound to "error-drop". - * - * To manually increment the specific counter VCGN_CLASSIFY_ERROR_EXAMPLE: - * - * vlib_node_t *n = vlib_get_node (vm, vcgn_classify.index); - * u32 node_counter_base_index = n->error_heap_index; - * vlib_error_main_t * em = &vm->error_main; - * em->counters[node_counter_base_index + VCGN_CLASSIFY_ERROR_EXAMPLE] += 1; - * - */ - -typedef enum { - VCGN_CLASSIFY_NEXT_IP4_INPUT, - VCGN_CLASSIFY_NEXT_IP6_INPUT, - VCGN_CLASSIFY_NEXT_MPLS_INPUT, - VCGN_CLASSIFY_NEXT_ETHERNET_INPUT, - VCGN_CLASSIFY_NEXT_UDP_INSIDE, - VCGN_CLASSIFY_NEXT_UDP_OUTSIDE, - VCGN_CLASSIFY_NEXT_TCP_INSIDE, - VCGN_CLASSIFY_NEXT_TCP_OUTSIDE, - VCGN_CLASSIFY_NEXT_ICMP_Q_INSIDE, - VCGN_CLASSIFY_NEXT_ICMP_Q_OUTSIDE, - VCGN_CLASSIFY_NEXT_ICMP_E_INSIDE, - VCGN_CLASSIFY_NEXT_ICMP_E_OUTSIDE, - VCGN_CLASSIFY_N_NEXT, -} vcgn_classify_next_t; - -static uword -vcgn_classify_node_fn (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - u32 n_left_from, * from, * to_next; - vcgn_classify_next_t next_index; - vcgn_classify_main_t * vcm = &vcgn_classify_main; - vlib_node_t *n = vlib_get_node (vm, vcgn_classify_node.index); - u32 node_counter_base_index = n->error_heap_index; - vlib_error_main_t * em = &vm->error_main; - u16 *l3_type; - int counter; - - from = vlib_frame_vector_args (frame); - n_left_from = frame->n_vectors; - next_index = node->cached_next_index; - - while (n_left_from > 0) - { - u32 n_left_to_next; - - vlib_get_next_frame (vm, node, next_index, - to_next, n_left_to_next); - - #if 0 - while (n_left_from >= 4 && n_left_to_next >= 2) - { - u32 bi0, bi1; - vlib_buffer_t * b0, * b1; - u32 next0, next1; - u32 sw_if_index0, sw_if_index1; - - /* Prefetch next iteration. */ - { - vlib_buffer_t * p2, * p3; - - p2 = vlib_get_buffer (vm, from[2]); - p3 = vlib_get_buffer (vm, from[3]); - - vlib_prefetch_buffer_header (p2, LOAD); - vlib_prefetch_buffer_header (p3, LOAD); - - CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, STORE); - CLIB_PREFETCH (p3->data, CLIB_CACHE_LINE_BYTES, STORE); - } - - /* speculatively enqueue b0 and b1 to the current next frame */ - to_next[0] = bi0 = from[0]; - to_next[1] = bi1 = from[1]; - from += 2; - to_next += 2; - n_left_from -= 2; - n_left_to_next -= 2; - - b0 = vlib_get_buffer (vm, bi0); - b1 = vlib_get_buffer (vm, bi1); - - sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX]; - next0 = vcm->cached_next_index; - sw_if_index1 = vnet_buffer(b1)->sw_if_index[VLIB_RX]; - next1 = vcm->cached_next_index; - - /* $$$$ your message in this space. Process 2 x pkts */ - em->counters[node_counter_base_index + VCGN_CLASSIFY_ERROR_PACKETS_RECEIVED] += 2; - - if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE))) - { - if (b0->flags & VLIB_BUFFER_IS_TRACED) - { - vcgn_classify_trace_t *t = - vlib_add_trace (vm, node, b0, sizeof (*t)); - t->sw_if_index = sw_if_index0; - t->next_index = next0; - } - if (b1->flags & VLIB_BUFFER_IS_TRACED) - { - vcgn_classify_trace_t *t = - vlib_add_trace (vm, node, b1, sizeof (*t)); - t->sw_if_index = sw_if_index1; - t->next_index = next1; - } - } - - /* verify speculative enqueues, maybe switch current next frame */ - vlib_validate_buffer_enqueue_x2 (vm, node, next_index, - to_next, n_left_to_next, - bi0, bi1, next0, next1); - } - #endif /* if 0 */ - - while (n_left_from > 0 && n_left_to_next > 0) - { - u32 bi0; - vlib_buffer_t * b0; - u32 next0; - u32 sw_if_index0; - ip4_header_t * h0; - //ipv4_header *h0; - ethernet_header_t *eth0; - icmp_v4_t *icmp; - u8 icmp_type; - u8 ipv4_hdr_len; - - /* speculatively enqueue b0 to the current next frame */ - bi0 = from[0]; - to_next[0] = bi0; - from += 1; - to_next += 1; - n_left_from -= 1; - n_left_to_next -= 1; - - b0 = vlib_get_buffer (vm, bi0); - - eth0 = (ethernet_header_t *) vlib_buffer_get_current(b0); - u16 *etype = ð0->type; - - /* vlan tag 0x8100 */ - if (*etype == clib_host_to_net_u16(ETHERNET_TYPE_VLAN)) { - l3_type = (etype + 1); /* Skip 2 bytes of vlan id */ - vlib_buffer_advance(b0, 18); - } else { - l3_type = etype; - vlib_buffer_advance(b0, 14); - } - /* Handling v4 pkts 0x800 */ - if (*l3_type == clib_host_to_net_u16(ETHERNET_TYPE_IP4)) { - - h0 = vlib_buffer_get_current (b0); - - u8 protocol_type = h0->protocol; - - sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX]; - next0 = VCGN_CLASSIFY_NEXT_IP4_INPUT; - counter = VCGN_CLASSIFY_ERROR_V4_PACKETS_PROCESSED; - - if (protocol_type == 0x11) { /* UDP# 17 */ - next0 = (sw_if_index0 < vec_len(vcm->inside_sw_if_index_table) && - vcm->inside_sw_if_index_table[sw_if_index0] != EMPTY) ? - VCGN_CLASSIFY_NEXT_UDP_INSIDE : next0; - - next0 = (sw_if_index0 < vec_len(vcm->outside_sw_if_index_table) && - vcm->outside_sw_if_index_table[sw_if_index0] != EMPTY) ? - VCGN_CLASSIFY_NEXT_UDP_OUTSIDE : next0; - - } else if (protocol_type == 0x06) { /* TCP# 6 */ - next0 = (sw_if_index0 < vec_len(vcm->inside_sw_if_index_table) && - vcm->inside_sw_if_index_table[sw_if_index0] != EMPTY) ? - VCGN_CLASSIFY_NEXT_TCP_INSIDE : next0; - - next0 = (sw_if_index0 < vec_len(vcm->outside_sw_if_index_table) && - vcm->outside_sw_if_index_table[sw_if_index0] != EMPTY) ? - VCGN_CLASSIFY_NEXT_TCP_OUTSIDE : next0; - - } else if (protocol_type == 0x01) { /* ICMP # 1 */ - - ipv4_hdr_len = (h0->ip_version_and_header_length & 0xf) << 2; - icmp = (icmp_v4_t *)((u8*)h0 + ipv4_hdr_len); - icmp_type = icmp->type; - - if ((icmp_type == ICMPV4_ECHO) || - (icmp_type == ICMPV4_ECHOREPLY)) { - next0 = (sw_if_index0 < vec_len(vcm->inside_sw_if_index_table) && - vcm->inside_sw_if_index_table[sw_if_index0] != EMPTY) ? - VCGN_CLASSIFY_NEXT_ICMP_Q_INSIDE : next0; - - next0 = (sw_if_index0 < vec_len(vcm->outside_sw_if_index_table) && - vcm->outside_sw_if_index_table[sw_if_index0] != EMPTY) ? - VCGN_CLASSIFY_NEXT_ICMP_Q_OUTSIDE : next0; - - } else { - next0 = (sw_if_index0 < vec_len(vcm->inside_sw_if_index_table) && - vcm->inside_sw_if_index_table[sw_if_index0] != EMPTY) ? - VCGN_CLASSIFY_NEXT_ICMP_E_INSIDE : next0; - - next0 = (sw_if_index0 < vec_len(vcm->outside_sw_if_index_table) && - vcm->outside_sw_if_index_table[sw_if_index0] != EMPTY) ? - VCGN_CLASSIFY_NEXT_ICMP_E_OUTSIDE : next0; - } - } else { - /* cannot do NATting with this L4 protocol */ - counter = VCGN_CLASSIFY_ERROR_V4_PACKETS_PUNTED; - } - - if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE) - && (b0->flags & VLIB_BUFFER_IS_TRACED))) { - udp_header_t * u0 = (udp_header_t *)(h0+1); - vcgn_classify_trace_t *t = - vlib_add_trace (vm, node, b0, sizeof (*t)); - t->sw_if_index = sw_if_index0; - t->next_index = next0; - t->orig_dst_address = h0->dst_address.as_u32; - t->orig_dst_port = u0->dst_port; - } - - } else if (*l3_type == clib_host_to_net_u16(ETHERNET_TYPE_IP6)) { - - /* IPv6 0x86DD */ - next0 = VCGN_CLASSIFY_NEXT_IP6_INPUT; - counter = VCGN_CLASSIFY_ERROR_V6_PACKETS_PUNTED; - - } else if (*l3_type == - clib_host_to_net_u16(ETHERNET_TYPE_MPLS_UNICAST)) { - - /* MPLS unicast 0x8847 */ - next0 = VCGN_CLASSIFY_NEXT_MPLS_INPUT; - counter = VCGN_CLASSIFY_ERROR_MPLS_PACKETS_PUNTED; - } else { /* Remaining all should be pushed to "ethernet-input" */ - - next0 = VCGN_CLASSIFY_NEXT_ETHERNET_INPUT; - counter = VCGN_CLASSIFY_ERROR_ETH_PACKETS_PUNTED; - } - - em->counters[node_counter_base_index + counter] += 1; - em->counters[node_counter_base_index + - VCGN_CLASSIFY_ERROR_PACKETS_RECEIVED] += 1; - - /* verify speculative enqueue, maybe switch current next frame */ - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, - to_next, n_left_to_next, - bi0, next0); - } - - vlib_put_next_frame (vm, node, next_index, n_left_to_next); - } - - return frame->n_vectors; -} - -VLIB_REGISTER_NODE (vcgn_classify_node) = { - .function = vcgn_classify_node_fn, - .name = "vcgn-classify", - .vector_size = sizeof (u32), - .format_trace = format_swap_trace, - .type = VLIB_NODE_TYPE_INTERNAL, - - .n_errors = ARRAY_LEN(vcgn_classify_error_strings), - .error_strings = vcgn_classify_error_strings, - - .n_next_nodes = VCGN_CLASSIFY_N_NEXT, - - /* edit / add dispositions here */ - .next_nodes = { - [VCGN_CLASSIFY_NEXT_IP4_INPUT] = "ip4-input", - [VCGN_CLASSIFY_NEXT_IP6_INPUT] = "ip6-input", - [VCGN_CLASSIFY_NEXT_MPLS_INPUT] = "mpls-gre-input", - [VCGN_CLASSIFY_NEXT_ETHERNET_INPUT] = "ethernet-input", - [VCGN_CLASSIFY_NEXT_UDP_INSIDE] = "vcgn-v4-udp-i2o", - [VCGN_CLASSIFY_NEXT_UDP_OUTSIDE] = "vcgn-v4-udp-o2i", - [VCGN_CLASSIFY_NEXT_TCP_INSIDE] = "vcgn-v4-tcp-i2o", - [VCGN_CLASSIFY_NEXT_TCP_OUTSIDE] = "vcgn-v4-tcp-o2i", - [VCGN_CLASSIFY_NEXT_ICMP_Q_INSIDE] = "vcgn-v4-icmp-q-i2o", - [VCGN_CLASSIFY_NEXT_ICMP_Q_OUTSIDE] = "vcgn-v4-icmp-q-o2i", - [VCGN_CLASSIFY_NEXT_ICMP_E_INSIDE] = "vcgn-v4-icmp-e-i2o", - [VCGN_CLASSIFY_NEXT_ICMP_E_OUTSIDE] = "vcgn-v4-icmp-e-o2i" - }, -}; - - -/* A test function to init the vrf map */ - -clib_error_t *vcgn_classify_init (vlib_main_t *vm) -{ - vcgn_classify_main_t * mp = &vcgn_classify_main; - - mp->vlib_main = vm; - mp->vnet_main = vnet_get_main(); - u32 inside_sw_if_index = 1; - u32 outside_sw_if_index = 0; - - vec_validate_init_empty (mp->inside_sw_if_index_table, - inside_sw_if_index + 1, EMPTY); - vec_validate_init_empty (mp->outside_sw_if_index_table, - outside_sw_if_index + 1, EMPTY); - - /* - * inside_sw_if_index cell of the table stores outside_sw_if_index - * and vice versa. This is ensurs pair of indices being remembered - * using one mem-location. - */ - mp->inside_sw_if_index_table[inside_sw_if_index] = outside_sw_if_index; - mp->outside_sw_if_index_table[outside_sw_if_index] = inside_sw_if_index; - -#if DPDK==1 - dpdk_set_next_node (DPDK_RX_NEXT_IP4_INPUT, "vcgn-classify"); -#endif - - { - pg_node_t * pn; - pn = pg_get_node (vcgn_classify_node.index); - pn->unformat_edit = unformat_pg_ip4_header; - } - return 0; -} - -VLIB_INIT_FUNCTION (vcgn_classify_init); - -/* Show command handlers */ -static clib_error_t * -show_vcgn_stats_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - if (cnat_db_init_done) { - cnat_nat44_handle_show_stats(vm); - } else { - vlib_cli_output(vm, "vCGN is not configured !!\n"); - } - return 0; -} - - -static clib_error_t * -show_vcgn_config_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - cnat_nat44_handle_show_config(vm); - return 0; -} - -static clib_error_t * -show_vcgn_inside_translation_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - vnet_main_t * vnm = vnet_get_main(); - vcgn_classify_main_t * vcm = &vcgn_classify_main; - spp_api_cnat_v4_show_inside_entry_req_t inside_req; - u8 *proto; - ip4_address_t inside_addr; - u32 start_port = 1; - u32 end_port = 65535; - u32 inside_sw_if_index = EMPTY; - - inside_req.start_port = start_port; - inside_req.end_port = end_port; - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { - if (unformat(input, "protocol %s", &proto)) { - if (!strncmp((char *) proto, "udp", 3)) { - inside_req.protocol = 1; - } else if (!strncmp((char *) proto, "tcp", 3)) { - inside_req.protocol = 2; - } else { - inside_req.protocol = 3; - } - } else if (unformat (input, "interface %U", - unformat_vnet_sw_interface, vnm, &inside_sw_if_index)) { - if (inside_sw_if_index > vec_len(vcm->inside_sw_if_index_table) || - vcm->inside_sw_if_index_table[inside_sw_if_index] == EMPTY) { - return clib_error_return (0, "Could not find the inside interface"); - } - } else if (unformat (input, "inside-addr %U", - unformat_ip4_address, &inside_addr)) { - inside_req.ipv4_addr = clib_net_to_host_u32(inside_addr.as_u32); - } else if (unformat(input, "start-port %u", &start_port)) { - inside_req.start_port = start_port; - } else if (unformat(input, "end-port %u", &end_port)) { - inside_req.end_port = end_port; - } else { break;} - } - inside_req.vrf_id = inside_sw_if_index; - inside_req.flags |= CNAT_TRANSLATION_ENTRY_DYNAMIC; /* as of now only dynamic */ - inside_req.all_entries = 0; /* we can see it later */ -#if DEBUG - vlib_cli_output(vm, "proto %d, inside-addr 0x%x, start_port %u, " - "end_port %u, vrf 0x%x\n", - inside_req.protocol, - inside_req.ipv4_addr, - inside_req.start_port, - inside_req.end_port, - inside_sw_if_index); -#endif - if (cnat_db_init_done) { - cnat_v4_show_inside_entry_req_t_handler(&inside_req, vm); - } else { - vlib_cli_output(vm, "vCGN is not configured !!\n"); - } - return 0; -} - - -static clib_error_t * -show_vcgn_outside_translation_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - void cnat_v4_show_outside_entry_req_t_handler - (spp_api_cnat_v4_show_outside_entry_req_t *mp, vlib_main_t *vm); - vnet_main_t * vnm = vnet_get_main(); - vcgn_classify_main_t * vcm = &vcgn_classify_main; - spp_api_cnat_v4_show_outside_entry_req_t outside_req; - u8 *proto; - ip4_address_t outside_addr; - u32 start_port = 1; - u32 end_port = 65535; - u32 outside_sw_if_index = EMPTY; - - - outside_req.start_port = start_port; - outside_req.end_port = end_port; - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { - if (unformat(input, "protocol %s", &proto)) { - if (!strncmp((char *) proto, "udp", 3)) { - outside_req.protocol = 1; - } else if (!strncmp((char *) proto, "tcp", 3)) { - outside_req.protocol = 2; - } else { - outside_req.protocol = 3; - } - } else if (unformat (input, "interface %U", - unformat_vnet_sw_interface, vnm, &outside_sw_if_index)) { - if (outside_sw_if_index > vec_len(vcm->outside_sw_if_index_table) || - vcm->outside_sw_if_index_table[outside_sw_if_index] == EMPTY) { - return clib_error_return (0, "Could not find the outside interface"); - } - } else if (unformat (input, "outside-addr %U", - unformat_ip4_address, &outside_addr)) { - outside_req.ipv4_addr = clib_net_to_host_u32(outside_addr.as_u32); - } else if (unformat(input, "start-port %u", &start_port)) { - outside_req.start_port = start_port; - } else if (unformat(input, "end-port %u", &end_port)) { - outside_req.end_port = end_port; - } else { break;} - } - outside_req.vrf_id = outside_sw_if_index; - outside_req.flags |= CNAT_TRANSLATION_ENTRY_DYNAMIC; /* as of now only dynamic */ -#if DEBUG - vlib_cli_output(vm, "proto %d, outside-addr 0x%x, start_port %u, " - "end_port %u, vrf 0x%x\n", - outside_req.protocol, - outside_req.ipv4_addr, - outside_req.start_port, - outside_req.end_port, - outside_sw_if_index); -#endif - if (cnat_db_init_done) { - cnat_v4_show_outside_entry_req_t_handler(&outside_req, vm); - } else { - vlib_cli_output(vm, "vCGN is not configured !!\n"); - } - return 0; -} - - -/* Config command handlers */ -static clib_error_t * -set_vcgn_inside_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - vnet_main_t * vnm = vnet_get_main(); - vcgn_classify_main_t * vcm = &vcgn_classify_main; - u32 inside_sw_if_index = 1; - u32 outside_sw_if_index = ~0; - void cnat_db_v2_init (void ); - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { - if (unformat(input, "%U", - unformat_vnet_sw_interface, vnm, &inside_sw_if_index)) - ; - else if (unformat(input, "outside %U", - unformat_vnet_sw_interface, vnm, &outside_sw_if_index)) - ; - else break; - } - if (inside_sw_if_index == ~0 || - outside_sw_if_index == ~0) - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); - - if (inside_sw_if_index == outside_sw_if_index) - return clib_error_return (0, "inside and outside interfaces can't be the same..."); - - /* - * Initialize in/out sw_if_index table. Could use - * non-indexed table to reduce memory. However, this - * is consulted in vcgn_classify for every packet. - * Therefore, table is indexed by sw_if_index. - */ - vec_validate_init_empty (vcm->inside_sw_if_index_table, - inside_sw_if_index + 1, EMPTY); - vec_validate_init_empty (vcm->outside_sw_if_index_table, - outside_sw_if_index + 1, EMPTY); - - /* - * inside_sw_if_index cell of the table stores outside_sw_if_index - * and vice versa. This is ensurs pair of indices being remembered - * using one mem-location. - */ - vcm->inside_sw_if_index_table[inside_sw_if_index] = outside_sw_if_index; - vcm->outside_sw_if_index_table[outside_sw_if_index] = inside_sw_if_index; - - if (! vcm->cnat_db_initalized) { - int i; - cnat_db_v2_init(); - - for (i = 0; i < CNAT_MAX_VRFMAP_ENTRIES; i++) { - vrf_map_array[i] = VRF_MAP_ENTRY_EMPTY; - } - /* Turn on the db scanner process */ - cnat_scanner_db_process_turn_on(vm); - vcm->cnat_db_initalized = 1; - } - return 0; -} - -static clib_error_t * -set_vcgn_map_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - vnet_main_t * vnm = vnet_get_main(); - vcgn_classify_main_t * vcm = &vcgn_classify_main; - ip4_address_t lo, hi; - spp_api_cnat_v4_add_vrf_map_t map; - u32 inside_sw_if_index = EMPTY; - u32 outside_sw_if_index; - - vnet_hw_interface_t *inside_hw_if_index = NULL; - vnet_hw_interface_t *outside_hw_if_index = NULL; - - if (! unformat(input, "inside %U", - unformat_vnet_sw_interface, vnm, &inside_sw_if_index)) - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); - - if (!unformat (input, "%U", unformat_ip4_address, &lo)) - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); - - if (unformat (input, "- %U", unformat_ip4_address, &hi)) - ; - - /* $$$$ remember to set i_vrf, i_vrf_id as needed */ - - /* Fill the structure spp_api_cnat_v4_add_vrf_map_t & let this API handle it */ - /* i_vrf_id & o_vrf_id are 32-bit & i_vrf, o_vrf are 16 bit */ - - if (inside_sw_if_index > vec_len(vcm->inside_sw_if_index_table) || - vcm->inside_sw_if_index_table[inside_sw_if_index] == EMPTY) { - return clib_error_return (0, "Could not find the inside interface"); - } - outside_sw_if_index = vcm->inside_sw_if_index_table[inside_sw_if_index]; - - map.i_vrf_id = inside_sw_if_index; - map.o_vrf_id = outside_sw_if_index; - map.i_vrf = inside_sw_if_index; - map.o_vrf = outside_sw_if_index; - - map.start_addr[0] = clib_net_to_host_u32(lo.as_u32); - map.end_addr[0] = clib_net_to_host_u32(hi.as_u32); - - cnat_nat44_add_vrf_map_t_handler(&map, vm); - -#if 1 - inside_hw_if_index = vnet_get_sup_hw_interface(vcm->vnet_main, inside_sw_if_index); - if (inside_hw_if_index) { - vnet_hw_interface_rx_redirect_to_node(vcm->vnet_main, - inside_hw_if_index->hw_if_index, vcgn_classify_node.index); - } - outside_hw_if_index = vnet_get_sup_hw_interface(vcm->vnet_main, outside_sw_if_index); - if (outside_hw_if_index) { - vnet_hw_interface_rx_redirect_to_node(vcm->vnet_main, - outside_hw_if_index->hw_if_index, vcgn_classify_node.index); - } -#endif - return 0; -} - -static clib_error_t * -set_vcgn_tcp_timeout_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - /* - vnet_main_t * vnm = vnet_get_main(); - vcgn_classify_main_t * vcm = &vcgn_classify_main; - */ - u32 act_timeout = 0; - u32 init_timeout = 0; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { - if (unformat(input, "active %u", &act_timeout)) - tcp_active_timeout = act_timeout; - else if (unformat(input, "init %u", &init_timeout)) - tcp_initial_setup_timeout = init_timeout; - else break; - } - return 0; -} - -static clib_error_t * -set_vcgn_udp_timeout_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - /* - vnet_main_t * vnm = vnet_get_main(); - vcgn_classify_main_t * vcm = &vcgn_classify_main; - */ - u32 act_timeout = 0; - u32 init_timeout = 0; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { - if (unformat(input, "active %u", &act_timeout)) - udp_act_session_timeout = act_timeout; - else if (unformat(input, "init %u", &init_timeout)) - udp_init_session_timeout = init_timeout; - else break; - } - return 0; -} - - -static clib_error_t * -set_vcgn_icmp_timeout_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - /* - * vnet_main_t * vnm = vnet_get_main(); - * vcgn_classify_main_t * vcm = &vcgn_classify_main; - */ - u32 timeout = 0; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { - if (unformat(input, "%u", &timeout)) - ; - else break; - } - icmp_session_timeout = timeout; - return 0; -} - - -static clib_error_t * -set_vcgn_protocol_default_timeout_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - /* - vnet_main_t * vnm = vnet_get_main(); - vcgn_classify_main_t * vcm = &vcgn_classify_main; - */ - u8 *protocol; - u8 reset = 1; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { - if (unformat(input, "%s", &protocol)) - ; - else break; - } - cnat_nat44_set_protocol_timeout_value(0, 0, protocol, reset, vm); - return 0; -} - -static clib_error_t * -set_vcgn_dynamic_port_start_range_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - /* - vnet_main_t * vnm = vnet_get_main(); - vcgn_classify_main_t * vcm = &vcgn_classify_main; - */ - u32 port = 0; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { - if (unformat(input, "%u", &port)) - ; - else break; - } - if (port != 0 && port > 65535) { - vlib_cli_output(vm, "Error !! Invalid port\n"); - } else { - cnat_static_port_range = port; - vlib_cli_output(vm, "Dynamic Port Range Config Successful !!\n"); - } - return 0; -} - -static clib_error_t * -set_vcgn_port_limit_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - /* - vnet_main_t * vnm = vnet_get_main(); - vcgn_classify_main_t * vcm = &vcgn_classify_main; - */ - u32 port = 0; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { - if (unformat(input, "%u", &port)) - ; - else break; - } - if (port != 0 && port > 65535) { - vlib_cli_output(vm, "Error !! Invalid port\n"); - } else { - cnat_main_db_max_ports_per_user = port; - vlib_cli_output(vm, "Port Limit Config Successful !!\n"); - } - return 0; -} - -static inline void nfv9_init_pkt_sent_data(cnat_nfv9_logging_info_t *nfv9_info) -{ - nfv9_server_info_t *server = nfv9_server_info_pool + - nfv9_info->server_index; - - /* - * Reset the pkts_since_last_template and sent_time - * so that template will be sent next time - */ - server->last_template_sent_time = 0; - server->pkts_since_last_template = 0xffffffff; -} - -static inline u16 nfv9_get_max_length_minus_max_record_size(u16 path_mtu) -{ - u16 max_length_minus_max_record_size; - if(!path_mtu) /* Use default */ - path_mtu = NFV9_DEF_PATH_MTU; - - max_length_minus_max_record_size = path_mtu - - CNAT_NFV9_DATAFLOW_RECORD_HEADER_LENGTH - - NFV9_PAD_VALUE - - CNAT_NFV9_MAX_SINGLE_RECORD_LENGTH; /* Note.. as of now this record - * requires max number of bytes. If you add more records, - * this needs to be re-checked */ - if (max_length_minus_max_record_size < CNAT_NFV9_MIN_RECORD_SIZE) { - max_length_minus_max_record_size = CNAT_NFV9_MIN_RECORD_SIZE; - } - return max_length_minus_max_record_size; -} - -/* This function finds if the netflow server indicated by - * new_server_info is already configured for some other instance - * if yes, it returns the same pointer so that, info sent to the - * server is consistent. If the server is not found, a new instance - * is created and returned. If an existing server is used, its refernce - * count is incrimented (indicating the number of instances using the - * same server - */ - /* #define DEBUG_NF_SERVER_CONFIG 1 */ -static u16 nfv9_get_server_instance( - cnat_nfv9_logging_info_t *nfv9_info, nfv9_server_info_t *new_server_info) -{ - - /* Check if the instance has a server already and if yes, does it match */ - nfv9_server_info_t *server; - if(nfv9_info->server_index != EMPTY) { - server = nfv9_server_info_pool + nfv9_info->server_index; - - if((server->ipv4_address == new_server_info->ipv4_address) && - (server->port == new_server_info->port)) { - /* Same server.. just check if refresh rate/timeouts are reduced */ -#ifdef DEBUG_NF_SERVER_CONFIG - if(my_instance_number == 1) { - printf("\n Server match for %x and port %d\n", - new_server_info->ipv4_address, new_server_info->port); - } -#endif /* #ifdef DEBUG_NF_SERVER_CONFIG */ - goto adjust_refresh_rate; - } else { /* The server is being changed */ - server->ref_count--; -#ifdef DEBUG_NF_SERVER_CONFIG - if(my_instance_number == 1) { - printf("\n Server change from %x, %d to %x, %d" - "Ref count %d\n", - server->ipv4_address, - server->port, - new_server_info->ipv4_address, new_server_info->port, - server->ref_count); - } -#endif /* #ifdef DEBUG_NF_SERVER_CONFIG */ - if(!server->ref_count) { - /* Return this server to pool */ -#ifdef DEBUG_NF_SERVER_CONFIG - if(my_instance_number == 1) { - PLATFORM_DEBUG_PRINT("Deleting Server %x, %d at %d\n", - server->ipv4_address, - server->port, - nfv9_info->server_index); - } -#endif /* #ifdef DEBUG_NF_SERVER_CONFIG */ - pool_put(nfv9_server_info_pool, server); - } - } - } - - /* Now check if the server is already present in the pool */ - u8 found = 0; - server = 0; - pool_foreach (server, nfv9_server_info_pool, ({ - if ((server->ipv4_address == new_server_info->ipv4_address) && - (server->port == new_server_info->port)) { - server->ref_count++; - nfv9_info->server_index = server - nfv9_server_info_pool; - found = 1; -#ifdef DEBUG_NF_SERVER_CONFIG - if(my_instance_number == 1) { - printf("Re-using server %x, %d Ref count %d\n", - server->ipv4_address, server->port, server->ref_count); - } -#endif /* #ifdef DEBUG_NF_SERVER_CONFIG */ - break; - } - })); - - if(!found) { - /* Create a new one, initialize and return */ - server = 0; - pool_get(nfv9_server_info_pool, server); - clib_memcpy(server, new_server_info, sizeof(nfv9_server_info_t)); - server->ref_count = 1; - nfv9_info->server_index = server - nfv9_server_info_pool; -#ifdef DEBUG_NF_SERVER_CONFIG - if(my_instance_number == 1) { - printf("Create new server for at %d %x and port %d\n", - nfv9_info->server_index, - new_server_info->ipv4_address, new_server_info->port); - } -#endif /* #ifdef DEBUG_NF_SERVER_CONFIG */ - return CNAT_SUCCESS; - } - -adjust_refresh_rate: - if(server->refresh_rate > - new_server_info->refresh_rate) { - server->refresh_rate = - new_server_info->refresh_rate; -#ifdef DEBUG_NF_SERVER_CONFIG - if(my_instance_number == 1) { - printf("Reset refresh rate to %d\n", - server->refresh_rate); - } -#endif /* #ifdef DEBUG_NF_SERVER_CONFIG */ - } - - if(server->timeout_rate > - new_server_info->timeout_rate) { - server->timeout_rate = - new_server_info->timeout_rate; -#ifdef DEBUG_NF_SERVER_CONFIG - if(my_instance_number == 1) { - printf("Reset timeout rate to %d\n", - server->timeout_rate); - } -#endif /* #ifdef DEBUG_NF_SERVER_CONFIG */ - } - - return CNAT_SUCCESS; -} -static clib_error_t * -set_vcgn_nfv9_logging_cofig_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - vcgn_classify_main_t * vcm = &vcgn_classify_main; - spp_api_cnat_v4_config_nfv9_logging_t nfv9_conf; - ip4_address_t server_addr; - u32 ip_addr = 0; - u32 port; - u32 refresh_rate = 0; - u32 timeout = 0; - u32 pmtu = 0; - u8 enable = 1; -/* vcgn changes start*/ - cnat_nfv9_logging_info_t *my_nfv9_logging_info = NULL; - cnat_nfv9_logging_info_t *my_nfv9_logging_info_tmp = NULL; - cnat_vrfmap_t *my_vrfmap = 0, *my_vrfmap_temp = 0; - u16 i_vrf = ~0; - u32 i_vrf_id = ~0; - u8 found; - u32 inside_sw_if_index = EMPTY; - /* - * Init NFv9 logging info as needed, this will be done only once - */ - cnat_nfv9_logging_init(); - - found = 0; - -/* vcgn changes end*/ - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { - if (unformat (input, "inside %U", - unformat_vnet_sw_interface, &inside_sw_if_index)) { - /* Do nothing */ - } else if (unformat (input, "server %U", unformat_ip4_address, &server_addr)) - ip_addr = clib_net_to_host_u32(server_addr.as_u32); - else if (unformat(input, "port %u", &port)) - ; - else if (unformat(input, "refresh-rate %u", &refresh_rate)) - ; - else if (unformat(input, "timeout %u", &timeout)) - ; - else if (unformat(input, "pmtu %u", &pmtu)) - ; - else if (unformat(input, "del")) - enable = 0; - else break; - } - - if (inside_sw_if_index > vec_len(vcm->inside_sw_if_index_table) || - vcm->inside_sw_if_index_table[inside_sw_if_index] == EMPTY) { - return clib_error_return (0, "Could not find the inside interface"); - } - i_vrf = inside_sw_if_index; - i_vrf_id = inside_sw_if_index; - - #if 0 - vlib_cli_output(vm, "ip 0x%x, port %u, refresh %u, " - "timeout %u, pmtu %u enable %u\n", - ip_addr, port, refresh_rate, - timeout, pmtu, enable); - #endif - if (refresh_rate == 0) refresh_rate = 500; /* num of pkts */ - if (timeout == 0) timeout = 30; /* in mins */ - - nfv9_conf.enable = enable; - nfv9_conf.ipv4_address = ip_addr; - nfv9_conf.i_vrf_id = inside_sw_if_index; - nfv9_conf.i_vrf = inside_sw_if_index; - nfv9_conf.port = port; - nfv9_conf.refresh_rate = refresh_rate; - nfv9_conf.timeout_rate = timeout; - nfv9_conf.path_mtu = pmtu; - nfv9_conf.nfv9_global_collector = 0; - nfv9_conf.session_logging = 0; - - /* - * At this point the NFv9 global information should already be - * inited as we have called cnat_nfv9_logging_init() - */ - - if (nfv9_conf.nfv9_global_collector) { - if (cnat_nfv9_global_info.cnat_nfv9_global_collector_index != EMPTY) { - found = 1; - my_nfv9_logging_info = cnat_nfv9_logging_info_pool + - cnat_nfv9_global_info.cnat_nfv9_global_collector_index; - } - } else { - /* Do we already have a map for this VRF? */ - pool_foreach (my_nfv9_logging_info, cnat_nfv9_logging_info_pool, ({ - if (my_nfv9_logging_info->i_vrf_id == i_vrf_id) { - nfv9_server_info_t *server = nfv9_server_info_pool + - my_nfv9_logging_info->server_index; - if((server->ipv4_address == (nfv9_conf.ipv4_address)) && (server->port == (nfv9_conf.port))) { - found = 1; - my_nfv9_logging_info_tmp = my_nfv9_logging_info; - break; - } - } - })); - } - - if ((nfv9_conf.ipv4_address == 0) || - (nfv9_conf.port == 0)) { - vlib_cli_output(vm, - "Add NFv9 ivrf %d Logging Invalid values [IPv4 0x%x, PORT %d]\n", - i_vrf, - (nfv9_conf.ipv4_address), - (nfv9_conf.port)); - goto done; - } - - if (nfv9_conf.enable) { - if ((nfv9_conf.ipv4_address == 0) || - (nfv9_conf.port == 0)) { - nfv9_conf.rc = CNAT_ERR_PARSER; - vlib_cli_output(vm, - "NFV9_logging i_vrf %d, Invalid [v4_addr 0x%x port %d]\n", - i_vrf, - (nfv9_conf.ipv4_address), - (nfv9_conf.port)); - goto done; - } - - nfv9_server_info_t new_server_info; - memset(&new_server_info, 0, sizeof(nfv9_server_info_t)); - new_server_info.ipv4_address = - nfv9_conf.ipv4_address; - new_server_info.port = - (nfv9_conf.port); - new_server_info.refresh_rate = - (nfv9_conf.refresh_rate); - /* - * Store the timeout in seconds. User configures it in minutes - */ - new_server_info.timeout_rate = - 60*(nfv9_conf.timeout_rate); - if (found && my_nfv9_logging_info) { - /* - * Entry already present, change it - */ - my_nfv9_logging_info->max_length_minus_max_record_size = - nfv9_get_max_length_minus_max_record_size( - ((nfv9_conf.path_mtu))); - } else { - pool_get(cnat_nfv9_logging_info_pool, my_nfv9_logging_info); - memset(my_nfv9_logging_info, 0, sizeof(*my_nfv9_logging_info)); - my_nfv9_logging_info->server_index = EMPTY; - my_nfv9_logging_info->nfv9_logging_next_index = EMPTY; - /* - * Make the current and head logging context indeices as EMPTY. - * When first logging happens, these get set correctly - */ - my_nfv9_logging_info->current_logging_context = NULL; - my_nfv9_logging_info->queued_logging_context = NULL; -#if 0 - my_nfv9_logging_info->f = NULL; - my_nfv9_logging_info->to_next = NULL; - output_node = vlib_get_node_by_name (vm, (u8 *) "ip4-input"); - my_nfv9_logging_info->ip4_input_node_index = output_node->index; - printf("ip4_input_node_index %d\n", my_nfv9_logging_info->ip4_input_node_index); -#endif - my_nfv9_logging_info->i_vrf = i_vrf; - my_nfv9_logging_info->i_vrf_id = i_vrf_id; - my_nfv9_logging_info->max_length_minus_max_record_size = - nfv9_get_max_length_minus_max_record_size( - nfv9_conf.path_mtu); - - /* my_nfv9_logging_info will have a copy of logging_policy - * because, it is quite possible that nfv9 config arrives before - * the corresponding vrfmap is initialized. In such cases - * this copy will be used to update the vrfmap entry - */ - my_nfv9_logging_info->logging_policy = nfv9_conf.session_logging; - - if (nfv9_conf.nfv9_global_collector) { - cnat_nfv9_global_info.cnat_nfv9_global_collector_index = - my_nfv9_logging_info - cnat_nfv9_logging_info_pool; - - pool_foreach (my_vrfmap, cnat_map_by_vrf, ({ - if (my_vrfmap->nfv9_logging_index == EMPTY) { - my_vrfmap->nfv9_logging_index = - cnat_nfv9_global_info.cnat_nfv9_global_collector_index; - } - })); - } else { - u32 my_vrfmap_found = 0; - - FIND_MY_VRF_USING_I_VRF_ID - my_vrfmap = my_vrfmap_temp; - if (my_vrfmap_found) { - if(my_vrfmap->nfv9_logging_index == EMPTY) { - my_vrfmap->nfv9_logging_index = - my_nfv9_logging_info - cnat_nfv9_logging_info_pool; - // my_vrfmap->nf_logging_policy = mp->session_logging; - } else { - cnat_nfv9_logging_info_t *my_nfv9_logging_info_temp = cnat_nfv9_logging_info_pool + my_vrfmap->nfv9_logging_index; - while(my_nfv9_logging_info_temp->nfv9_logging_next_index != EMPTY){ - my_nfv9_logging_info_temp = cnat_nfv9_logging_info_pool + my_nfv9_logging_info_temp->nfv9_logging_next_index; - } - my_nfv9_logging_info_temp->nfv9_logging_next_index = my_nfv9_logging_info - cnat_nfv9_logging_info_pool; - } - } - } - } - - /* Update logging policy */ - my_nfv9_logging_info->logging_policy = nfv9_conf.session_logging; - if (nfv9_conf.nfv9_global_collector) { - if(PLATFORM_DBL_SUPPORT) { - pool_foreach (my_vrfmap, cnat_map_by_vrf, ({ - if (my_vrfmap->nfv9_logging_index == - cnat_nfv9_global_info.cnat_nfv9_global_collector_index) { - my_vrfmap->nf_logging_policy = nfv9_conf.session_logging; - } - })); - } else { - nfv9_conf.rc = CNAT_ERR_NO_SESSION_DB; - } - } else { - if(PLATFORM_DBL_SUPPORT) { - u32 my_vrfmap_found = 0; - my_vrfmap_temp = NULL; - FIND_MY_VRF_USING_I_VRF_ID - my_vrfmap = my_vrfmap_temp; - if (my_vrfmap_found) { - // my_vrfmap->nf_logging_policy = mp->session_logging; - } - } else { - nfv9_conf.rc = CNAT_ERR_NO_SESSION_DB; - } - } - u8 nfv9_logging_policy = 0; - u32 my_vrfmap_found = 0; - my_vrfmap_temp = NULL; - FIND_MY_VRF_USING_I_VRF_ID - my_vrfmap = my_vrfmap_temp; - if (my_vrfmap_found) { - u32 index_curr = my_vrfmap->nfv9_logging_index; - cnat_nfv9_logging_info_t *my_nfv9_logging_info_temp; - while(index_curr != EMPTY) { - my_nfv9_logging_info_temp = cnat_nfv9_logging_info_pool + index_curr; - nfv9_logging_policy = nfv9_logging_policy || my_nfv9_logging_info_temp->logging_policy; - index_curr = (cnat_nfv9_logging_info_pool + index_curr)->nfv9_logging_next_index; - } - my_vrfmap->nf_logging_policy = nfv9_logging_policy; - } - //vlib_cli_output(vm,"Netflow logging policy = %d\n", my_vrfmap->nf_logging_policy); - if(nfv9_get_server_instance(my_nfv9_logging_info, &new_server_info) - != CNAT_SUCCESS) { - vlib_cli_output(vm, "Error to get server instance"); - nfv9_conf.rc = CNAT_ERR_PARSER; - goto done; - } - nfv9_init_pkt_sent_data(my_nfv9_logging_info); - - vlib_cli_output(vm,"Adding NFv9 Logging Succeeded\n"); - nfv9_configured = 1; - - } else { - /*Delete path*/ - if (found) { - /* if found entry then we need to overwrite the my_nfv9_logging_info_tmp - * to my_nfv9_logging_info - */ - my_nfv9_logging_info = my_nfv9_logging_info_tmp; - if (i_vrf == INVALID_UIDX) { - /* - * We are deleting a global collector. Mark the collectors - * in those VRFs using the global collector - */ - pool_foreach (my_vrfmap, cnat_map_by_vrf, ({ - if (my_vrfmap->nfv9_logging_index == - cnat_nfv9_global_info.cnat_nfv9_global_collector_index) { - my_vrfmap->nfv9_logging_index = EMPTY; - } - })); - - cnat_nfv9_global_info.cnat_nfv9_global_collector_index = EMPTY; - } else { - u32 my_vrfmap_found = 0; - my_vrfmap_temp = NULL; - FIND_MY_VRF_USING_I_VRF_ID - my_vrfmap = my_vrfmap_temp; - if (my_vrfmap_found) { - // my_vrfmap->nfv9_logging_index = cnat_nfv9_global_info.cnat_nfv9_global_collector_index; - } - } - if (my_nfv9_logging_info->queued_logging_context || - my_nfv9_logging_info->current_logging_context) { - /* - * If there is a pending context: - * Set the deleted flag to 1. This will ensure - * that the logging info structure gets freed after any - * pending packet get sent - */ - my_nfv9_logging_info->deleted = 1; - } else { - /* - * No pending context, just free the logging info structure - */ - u32 index = my_nfv9_logging_info - cnat_nfv9_logging_info_pool; - if(index == my_vrfmap->nfv9_logging_index) { - /* Deleting the first sever */ - my_vrfmap->nfv9_logging_index = my_nfv9_logging_info->nfv9_logging_next_index; - /* if(my_nfv9_logging_info->nfv9_logging_next_index != EMPTY){ - my_vrfmap->nf_logging_policy = (cnat_nfv9_logging_info_pool + my_nfv9_logging_info->nfv9_logging_next_index)->logging_policy; - } else { - my_vrfmap->nf_logging_policy = EMPTY; - }*/ - } else { - u32 index_curr = my_vrfmap->nfv9_logging_index; - u32 index_prev = EMPTY; - while(index_curr != EMPTY) { - index_prev = index_curr; - index_curr = (cnat_nfv9_logging_info_pool + index_curr)->nfv9_logging_next_index; - if(index == index_curr) - { - (cnat_nfv9_logging_info_pool + index_prev)->nfv9_logging_next_index = (cnat_nfv9_logging_info_pool + index_curr)->nfv9_logging_next_index; - break; - } - } - } - nfv9_delete_server_info(my_nfv9_logging_info); - pool_put(cnat_nfv9_logging_info_pool, my_nfv9_logging_info); - } - - vlib_cli_output(vm, "Deleting NFv9 Logging Succeeded\n"); - /* - * Search across all vrf and check if nfv9 logging is configured. - */ - nfv9_configured = 0; - pool_foreach (my_nfv9_logging_info, cnat_nfv9_logging_info_pool, ({ - nfv9_configured = 1; - break; - })); - } else { - nfv9_conf.rc = CNAT_NO_CONFIG; - vlib_cli_output(vm, "Add NFv9 Logging Failed (2) Non Existent vrf %d\n", - i_vrf); - - } - u8 nfv9_logging_policy = 0; - u32 my_vrfmap_found = 0; - my_vrfmap_temp = NULL; - FIND_MY_VRF_USING_I_VRF_ID - my_vrfmap = my_vrfmap_temp; - if (my_vrfmap_found) { - u32 index_curr = my_vrfmap->nfv9_logging_index; - cnat_nfv9_logging_info_t *my_nfv9_logging_info_temp; - while(index_curr != EMPTY) { - my_nfv9_logging_info_temp = cnat_nfv9_logging_info_pool + index_curr; - nfv9_logging_policy = nfv9_logging_policy || my_nfv9_logging_info_temp->logging_policy; - index_curr = (cnat_nfv9_logging_info_pool + index_curr)->nfv9_logging_next_index; - } - my_vrfmap->nf_logging_policy = nfv9_logging_policy; - } - } - -done: - return 0; -} - -/* config CLIs */ -VLIB_CLI_COMMAND (set_vcgn_map_command) = { - .path = "set vcgn map", - .short_help = "set vcgn map [- ]", - .function = set_vcgn_map_command_fn, -}; - -VLIB_CLI_COMMAND (set_vcgn_inside_command) = { - .path = "set vcgn inside", - .short_help = "set vcgn inside outside ", - .function = set_vcgn_inside_command_fn, -}; - -VLIB_CLI_COMMAND (set_vcgn_tcp_timeout_command) = { - .path = "set vcgn tcp timeout", - .short_help = "set vcgn tcp timeout active <1-65535> init <1-65535>", - .function = set_vcgn_tcp_timeout_command_fn, -}; - -VLIB_CLI_COMMAND (set_vcgn_udp_timeout_command) = { - .path = "set vcgn udp timeout", - .short_help = "set vcgn udp timeout active <1-65535> init <1-65535>", - .function = set_vcgn_udp_timeout_command_fn, -}; - -VLIB_CLI_COMMAND (set_vcgn_icmp_timeout_command) = { - .path = "set vcgn icmp timeout", - .short_help = "set vcgn icmp timeout <1-65535>", - .function = set_vcgn_icmp_timeout_command_fn, -}; - -VLIB_CLI_COMMAND (set_vcgn_protocol_default_timeout_command) = { - .path = "set vcgn default timeout", - .short_help = "set vcgn default timeout protocol ", - .function = set_vcgn_protocol_default_timeout_command_fn, -}; - -VLIB_CLI_COMMAND (set_vcgn_dynamic_port_start_range_command) = { - .path = "set vcgn dynamic port start", - .short_help = "set vcgn dynamic port start <1-65535>", - .function = set_vcgn_dynamic_port_start_range_command_fn, -}; - -VLIB_CLI_COMMAND (set_vcgn_port_limit_command) = { - .path = "set vcgn port limit", - .short_help = "set vcgn port limit <1-65535>", - .function = set_vcgn_port_limit_command_fn, -}; - -VLIB_CLI_COMMAND (set_vcgn_nfv9_logging_cofig_command) = { - .path = "set vcgn nfv9", - .short_help = "set vcgn nfv9 [del] inside " - "server port [refresh-rate ] " - "[timeout ] [pmtu ]", - .function = set_vcgn_nfv9_logging_cofig_command_fn, -}; - - -/* show CLIs */ -VLIB_CLI_COMMAND (show_vcgn_config_command) = { - .path = "show vcgn config", - .short_help = "show vcgn config", - .function = show_vcgn_config_command_fn, -}; - -VLIB_CLI_COMMAND (show_vcgn_stat_command) = { - .path = "show vcgn statistics", - .short_help = "show vcgn statistics", - .function = show_vcgn_stats_command_fn, -}; - -VLIB_CLI_COMMAND (show_vcgn_inside_translation_command) = { - .path = "show vcgn inside-translation", - .short_help = "show vcgn inside-translation protocol " - "interface inside-addr " - "[start-port ] [end-port ]", - .function = show_vcgn_inside_translation_command_fn, -}; - -VLIB_CLI_COMMAND (show_vcgn_outside_translation_command) = { - .path = "show vcgn outside-translation", - .short_help = "show vcgn outside-translation protocol " - "interface outside-addr " - "[start-port ] [end-port ]", - .function = show_vcgn_outside_translation_command_fn, -}; - -static clib_error_t * -vcgn_init (vlib_main_t * vm) -{ - clib_error_t * error = 0; - - if ((error = vlib_call_init_function - (vm, vcgn_classify_init))) - return error; - if ((error = vlib_call_init_function - (vm, cnat_ipv4_udp_inside_input_init))) - return error; - if ((error = vlib_call_init_function - (vm, cnat_ipv4_udp_outside_input_init))) - return error; - if ((error = vlib_call_init_function - (vm, cnat_ipv4_udp_inside_input_exc_init))) - return error; - if ((error = vlib_call_init_function - (vm, cnat_db_scanner_init))) - return error; - if ((error = vlib_call_init_function - (vm, cnat_ipv4_tcp_inside_input_init))) - return error; - if ((error = vlib_call_init_function - (vm, cnat_ipv4_tcp_inside_input_exc_init))) - return error; - if ((error = vlib_call_init_function - (vm, cnat_ipv4_tcp_outside_input_init))) - return error; - if ((error = vlib_call_init_function - (vm, cnat_ipv4_icmp_q_inside_input_init))) - return error; - if ((error = vlib_call_init_function - (vm, cnat_ipv4_icmp_q_inside_input_exc_init))) - return error; - if ((error = vlib_call_init_function - (vm, cnat_ipv4_icmp_q_outside_input_init))) - return error; - if ((error = vlib_call_init_function - (vm, cnat_ipv4_icmp_e_inside_input_init))) - return error; - if ((error = vlib_call_init_function - (vm, cnat_ipv4_icmp_e_outside_input_init))) - return error; - - return error; -} - -/* - * This routine exists to convince the vlib plugin framework that - * we haven't accidentally copied a random .dll into the plugin - * directory. This is used in lieu of VLIB_INIT_FUNCTION(vcgn_init). - * - * Also collects global variable pointers passed from the vpp engine - */ -clib_error_t * -vlib_plugin_register (vlib_main_t * vm, vnet_plugin_handoff_t * h, - int from_early_init) -{ - return vcgn_init(vm); -} diff --git a/plugins/plugins/vcgn/vcgn_db.h b/plugins/plugins/vcgn/vcgn_db.h deleted file mode 100644 index cd7d835c..00000000 --- a/plugins/plugins/vcgn/vcgn_db.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - *------------------------------------------------------------------ - * vcgn_db.h - translation database definitions - * - * Copyright (c) 2007-2014 Cisco and/or its affiliates. - * 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 __VCGN_DB_H__ -#define __VCGN_DB_H__ - -#include "index_list.h" - -/* - * The key structure. All fields are in NETWORK byte order! - */ -typedef struct { - u32 ipv4; - u16 port; - u16 vrf; //bit0-12:vrf, bit13:unused, bit14-15:protocol -} cnat_db_key_t; - -/* bit14-15:protocol in cnat_db_key_t */ -#define CNAT_INVALID_PROTO 0x0000 -#define CNAT_UDP 0x4000 -#define CNAT_TCP 0x8000 -#define CNAT_ICMP 0xc000 -#define CNAT_VRF_MASK 0x3fff -#define CNAT_PRO_MASK 0xc000 -#define CNAT_PRO_SHIFT 14 - -/* - * Maximum number of VRF entries supported - */ -#define CNAT_MAX_VRFMAP_ENTRIES (CNAT_VRF_MASK + 1) -/* - * for hashing purposes, fetch the key in one instr. - */ -typedef union { - cnat_db_key_t k; - u64 key64; -} cnat_key_t; - -/* - * Main translation database entries. Currently 0x50 = 80 bytes in length. - * Given 20,000,000 entries, it saves nearly 1gb of SDRAM to pack the entries - * and pay the extra prefetch. So, that's what we do. - */ - -typedef struct { - /* 0x00 */ - index_slist_t out2in_hash; /* hash-and-chain, x2 */ - index_slist_t in2out_hash; - - /* 0x08 */ - cnat_key_t out2in_key; /* network-to-user, outside-to-inside key */ - - /* 0x10 */ - cnat_key_t in2out_key; /* user-to-network, inside-to-outside key */ - - /* 0x18 */ - index_dlist_t user_ports; /* per-user translation list */ - - /* 0x20 */ - u32 user_index; /* index of user that owns this entry */ - - /* 0x24 */ - u16 vrfmap_index; /* index of vrfmap */ - - /* 0x26 */ - u16 flags; /* Always need flags... */ -#define CNAT_DB_FLAG_PORT_PAIR (1<<0) -#define CNAT_DB_FLAG_TCP_ACTIVE (1<<1) -#define CNAT_DB_FLAG_ENTRY_FREE (1<<2) -#define CNAT_DB_FLAG_UDP_ACTIVE (1<<3) -#define CNAT_DB_FLAG_STATIC_PORT (1<<4) -#define CNAT_DB_FLAG_ALG_ENTRY (1<<5) - - /* 0x28 */ - u32 dst_ipv4; /* pointer to ipv4 dst list, used in evil mode */ - - /* 0x2C */ - u32 out2in_pkts; /* pkt counters */ - - /* 0x30 */ - u32 in2out_pkts; - - /* 0x34 */ - u32 entry_expires; /* timestamp used to expire translations */ - - /* 0x38 */ - union { /* used by FTP ALG, pkt len delta due to FTP PORT cmd */ - u16 delta; - i8 alg_dlt[2]; /* two delta values, 0 for previous, 1 for current */ - u16 il; /* Used to indicate if interleaved mode is used - in case of RTSP ALG */ - } alg; - - /* 0x 48 */ - u32 tcp_seq_num; /* last tcp (FTP) seq # that has pkt len change due to PORT */ - - cnat_timeout_t destn_key; - - /* 0x4C... last byte -- 72 total */ -} cnat_main_db_entry_t; -#endif diff --git a/plugins/sample-plugin/Makefile.am b/plugins/sample-plugin/Makefile.am index 2b47717b..30b17194 100644 --- a/plugins/sample-plugin/Makefile.am +++ b/plugins/sample-plugin/Makefile.am @@ -41,7 +41,6 @@ if WITH_PLUGIN_TOOLKIT install-data-hook: mkdir /usr/lib/vpp_plugins || true mkdir /usr/lib/vpp_api_test_plugins || true - cp $(prefix)/lib/sample_plugin.so.*.*.* /usr/lib/vpp_plugins - cp $(prefix)/lib/sample_test_plugin.so.*.*.* \ - /usr/lib/vpp_api_test_plugins + cp -L $(prefix)/lib/sample_plugin.so /usr/lib/vpp_plugins + cp -L $(prefix)/lib/sample_test_plugin.so /usr/lib/vpp_api_test_plugins endif diff --git a/plugins/sixrd-plugin/Makefile.am b/plugins/sixrd-plugin/Makefile.am new file mode 100644 index 00000000..c2fae798 --- /dev/null +++ b/plugins/sixrd-plugin/Makefile.am @@ -0,0 +1,37 @@ +# Copyright (c) 2015 Cisco and/or its affiliates. +# 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. + +AUTOMAKE_OPTIONS = foreign subdir-objects + +AM_CFLAGS = -Wall -I@TOOLKIT_INCLUDE@ + +libsixrd_plugin_la_SOURCES = \ + sixrd/sixrd.c \ + sixrd/ip4_sixrd.c \ + sixrd/ip6_sixrd.c + +nobase_include_HEADERS = \ + sixrd/sixrd.h + +libsixrd_plugin_la_LDFLAGS = -module + +BUILT_SOURCES = + +lib_LTLIBRARIES = libsixrd_plugin.la + +if WITH_PLUGIN_TOOLKIT +install-data-hook: + mkdir /usr/lib/vpp_plugins || true + mkdir /usr/lib/vpp_api_test_plugins || true + cp -L $(prefix)/lib/libsixrd_plugin.so /usr/lib/vpp_plugins +endif diff --git a/plugins/sixrd-plugin/configure.ac b/plugins/sixrd-plugin/configure.ac new file mode 100644 index 00000000..c00a23bb --- /dev/null +++ b/plugins/sixrd-plugin/configure.ac @@ -0,0 +1,17 @@ +AC_INIT(sixrd_plugin, 1.0) +LT_INIT +AM_INIT_AUTOMAKE + +AM_PROG_AS +AC_PROG_CC +AM_PROG_CC_C_O + +AC_ARG_WITH(plugin-toolkit, + AC_HELP_STRING([--with-plugin-toolkit], + [build using the vpp toolkit]), + [with_plugin_toolkit=${prefix}/include], + [with_plugin_toolkit=.]) + +AC_SUBST(TOOLKIT_INCLUDE,[${with_plugin_toolkit}]) +AM_CONDITIONAL(WITH_PLUGIN_TOOLKIT, test "$with_plugin_toolkit" != ".") +AC_OUTPUT([Makefile]) diff --git a/plugins/sixrd-plugin/sixrd/ip4_sixrd.c b/plugins/sixrd-plugin/sixrd/ip4_sixrd.c new file mode 100644 index 00000000..2fb8015d --- /dev/null +++ b/plugins/sixrd-plugin/sixrd/ip4_sixrd.c @@ -0,0 +1,127 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2009-2014 Cisco and/or its affiliates. + * 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 "sixrd.h" + +static vlib_node_registration_t ip4_sixrd_node; + +typedef enum { + IP4_SIXRD_NEXT_IP6_LOOKUP, + IP4_SIXRD_NEXT_DROP, + IP4_SIXRD_N_NEXT, +} ip4_sixrd_next_t; + +/* + * ip4_sixrd_sec_check + */ +static_always_inline void +ip4_sixrd_sec_check (sixrd_domain_t *d, ip4_address_t sa4, ip6_address_t sa6, u8 *error) +{ + u32 a = sixrd_get_addr(d, sa6.as_u64[0]); + clib_warning("Security check: %U %U", format_ip4_address, &a, format_ip4_address, &sa4); + if (PREDICT_FALSE(sixrd_get_addr(d, sa6.as_u64[0]) != sa4.as_u32)) + *error = SIXRD_ERROR_SEC_CHECK; +} + +/* + * ip4_sixrd + */ +static uword +ip4_sixrd (vlib_main_t *vm, + vlib_node_runtime_t *node, + vlib_frame_t *frame) +{ + u32 n_left_from, *from, next_index, *to_next, n_left_to_next; + vlib_node_runtime_t *error_node = vlib_node_get_runtime(vm, ip4_sixrd_node.index); + u32 decap = 0; + + from = vlib_frame_vector_args(frame); + n_left_from = frame->n_vectors; + next_index = node->cached_next_index; + while (n_left_from > 0) { + vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next); + + /* Single loop */ + while (n_left_from > 0 && n_left_to_next > 0) { + u32 pi0; + vlib_buffer_t *p0; + u8 error0 = SIXRD_ERROR_NONE; + sixrd_domain_t *d0 = 0; + ip4_header_t *ip40; + ip6_header_t *ip60; + u32 sixrd_domain_index0 = ~0; + u32 next0; + + pi0 = to_next[0] = from[0]; + from += 1; + n_left_from -= 1; + to_next +=1; + n_left_to_next -= 1; + + p0 = vlib_get_buffer(vm, pi0); + ip40 = vlib_buffer_get_current(p0); + + /* Throw away anything that isn't IP in IP. */ + if (PREDICT_TRUE(ip40->protocol == IP_PROTOCOL_IPV6 && clib_net_to_host_u16(ip40->length) >= 60)) { + vlib_buffer_advance(p0, sizeof(ip4_header_t)); + ip60 = vlib_buffer_get_current(p0); + d0 = ip4_sixrd_get_domain(vnet_buffer(p0)->ip.adj_index[VLIB_TX], (ip6_address_t *)&ip60->src_address, + &sixrd_domain_index0, &error0); + } else { + error0 = SIXRD_ERROR_BAD_PROTOCOL; + } + if (d0) { + /* SIXRD inbound security check */ + ip4_sixrd_sec_check(d0, ip40->src_address, ip60->src_address, &error0); + } + + next0 = error0 == SIXRD_ERROR_NONE ? IP4_SIXRD_NEXT_IP6_LOOKUP : IP4_SIXRD_NEXT_DROP; + + if (PREDICT_FALSE(p0->flags & VLIB_BUFFER_IS_TRACED)) { + sixrd_trace_t *tr = vlib_add_trace(vm, node, p0, sizeof(*tr)); + tr->sixrd_domain_index = sixrd_domain_index0; + } + + p0->error = error_node->errors[error0]; + if (PREDICT_TRUE(error0 == SIXRD_ERROR_NONE)) decap++; + vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, pi0, next0); + + } + vlib_put_next_frame(vm, node, next_index, n_left_to_next); + } + vlib_node_increment_counter(vm, ip4_sixrd_node.index, SIXRD_ERROR_DECAPSULATED, decap); + + return frame->n_vectors; +} + +static char *sixrd_error_strings[] = { +#define _(sym,string) string, + foreach_sixrd_error +#undef _ +}; + +VLIB_REGISTER_NODE(ip4_sixrd_node,static) = { + .function = ip4_sixrd, + .name = "ip4-sixrd", + .vector_size = sizeof(u32), + .format_trace = format_sixrd_trace, + .n_errors = SIXRD_N_ERROR, + .error_strings = sixrd_error_strings, + .n_next_nodes = IP4_SIXRD_N_NEXT, + .next_nodes = { + [IP4_SIXRD_NEXT_IP6_LOOKUP] = "ip6-lookup", + [IP4_SIXRD_NEXT_DROP] = "error-drop", + }, +}; diff --git a/plugins/sixrd-plugin/sixrd/ip6_sixrd.c b/plugins/sixrd-plugin/sixrd/ip6_sixrd.c new file mode 100644 index 00000000..36f3fab3 --- /dev/null +++ b/plugins/sixrd-plugin/sixrd/ip6_sixrd.c @@ -0,0 +1,129 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2009-2014 Cisco and/or its affiliates. + * 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. + *--------------------------------------------------------------------------- + */ +/* + * Defines used for testing various optimisation schemes + */ +#define SIXRD_ENCAP_DUAL 0 + +#include "sixrd.h" + +static vlib_node_registration_t ip6_sixrd_node; + +typedef enum { + IP6_SIXRD_NEXT_IP4_LOOKUP, + IP6_SIXRD_NEXT_DROP, + IP6_SIXRD_N_NEXT, +} ip6_sixrd_next_t; + +/* + * ip6_sixrd + */ +static uword +ip6_sixrd (vlib_main_t *vm, + vlib_node_runtime_t *node, + vlib_frame_t *frame) +{ + u32 n_left_from, *from, next_index, *to_next, n_left_to_next; + vlib_node_runtime_t *error_node = vlib_node_get_runtime(vm, ip6_sixrd_node.index); + u32 encap = 0; + from = vlib_frame_vector_args(frame); + n_left_from = frame->n_vectors; + next_index = node->cached_next_index; + + while (n_left_from > 0) { + vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next); + + while (n_left_from > 0 && n_left_to_next > 0) { + u32 pi0; + vlib_buffer_t *p0; + sixrd_domain_t *d0; + u8 error0 = SIXRD_ERROR_NONE; + ip6_header_t *ip60; + ip4_header_t *ip4h0; + u32 next0 = IP6_SIXRD_NEXT_IP4_LOOKUP; + u32 sixrd_domain_index0 = ~0; + + pi0 = to_next[0] = from[0]; + from += 1; + n_left_from -= 1; + to_next +=1; + n_left_to_next -= 1; + + p0 = vlib_get_buffer(vm, pi0); + ip60 = vlib_buffer_get_current(p0); + // p0->current_length = clib_net_to_host_u16(ip40->length); + d0 = ip6_sixrd_get_domain(vnet_buffer(p0)->ip.adj_index[VLIB_TX], &sixrd_domain_index0); + ASSERT(d0); + + /* SIXRD calc */ + u64 dal60 = clib_net_to_host_u64(ip60->dst_address.as_u64[0]); + u32 da40 = sixrd_get_addr(d0, dal60); + u16 len = clib_net_to_host_u16(ip60->payload_length) + 60; + if (da40 == 0) error0 = SIXRD_ERROR_UNKNOWN; + + /* construct ipv4 header */ + vlib_buffer_advance(p0, - (sizeof(ip4_header_t))); + ip4h0 = vlib_buffer_get_current(p0); + vnet_buffer(p0)->sw_if_index[VLIB_TX] = (u32)~0; + ip4h0->ip_version_and_header_length = 0x45; + ip4h0->tos = 0; + ip4h0->length = clib_host_to_net_u16(len); + ip4h0->fragment_id = 0; + ip4h0->flags_and_fragment_offset = 0; + ip4h0->ttl = 0x40; + ip4h0->protocol = IP_PROTOCOL_IPV6; + ip4h0->src_address = d0->ip4_src; + ip4h0->dst_address.as_u32 = clib_host_to_net_u32(da40); + ip4h0->checksum = ip4_header_checksum(ip4h0); + + next0 = error0 == SIXRD_ERROR_NONE ? IP6_SIXRD_NEXT_IP4_LOOKUP : IP6_SIXRD_NEXT_DROP; + + if (PREDICT_FALSE(p0->flags & VLIB_BUFFER_IS_TRACED)) { + sixrd_trace_t *tr = vlib_add_trace(vm, node, p0, sizeof(*tr)); + tr->sixrd_domain_index = sixrd_domain_index0; + } + + p0->error = error_node->errors[error0]; + if (PREDICT_TRUE(error0 == SIXRD_ERROR_NONE)) encap++; + + vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, pi0, next0); + } + vlib_put_next_frame(vm, node, next_index, n_left_to_next); + } + vlib_node_increment_counter(vm, ip6_sixrd_node.index, SIXRD_ERROR_ENCAPSULATED, encap); + + return frame->n_vectors; +} + +static char *sixrd_error_strings[] = { +#define _(sym,string) string, + foreach_sixrd_error +#undef _ +}; + +VLIB_REGISTER_NODE(ip6_sixrd_node,static) = { + .function = ip6_sixrd, + .name = "ip6-sixrd", + .vector_size = sizeof(u32), + .format_trace = format_sixrd_trace, + .n_errors = SIXRD_N_ERROR, + .error_strings = sixrd_error_strings, + .n_next_nodes = IP6_SIXRD_N_NEXT, + .next_nodes = { + [IP6_SIXRD_NEXT_IP4_LOOKUP] = "ip4-lookup", + [IP6_SIXRD_NEXT_DROP] = "error-drop", + }, +}; diff --git a/plugins/sixrd-plugin/sixrd/sixrd.c b/plugins/sixrd-plugin/sixrd/sixrd.c new file mode 100644 index 00000000..8ebdb32b --- /dev/null +++ b/plugins/sixrd-plugin/sixrd/sixrd.c @@ -0,0 +1,379 @@ +/* + * Copyright (c) 2015 Cisco and/or its affiliates. + * 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 "sixrd.h" +#include + +/* + * This code supports the following sixrd modes: + * + * 32 EA bits (Complete IPv4 address is embedded): + * ea_bits_len = 32 + * IPv4 suffix is embedded: + * ea_bits_len = < 32 + * No embedded address bits (1:1 mode): + * ea_bits_len = 0 + */ + +int +sixrd_create_domain (ip6_address_t *ip6_prefix, + u8 ip6_prefix_len, + ip4_address_t *ip4_prefix, + u8 ip4_prefix_len, + ip4_address_t *ip4_src, + u32 *sixrd_domain_index, + u16 mtu) +{ + sixrd_main_t *mm = &sixrd_main; + ip4_main_t *im4 = &ip4_main; + ip6_main_t *im6 = &ip6_main; + sixrd_domain_t *d; + ip_adjacency_t adj; + ip4_add_del_route_args_t args4; + ip6_add_del_route_args_t args6; + u32 *p; + + /* Get domain index */ + pool_get_aligned(mm->domains, d, CLIB_CACHE_LINE_BYTES); + memset(d, 0, sizeof (*d)); + *sixrd_domain_index = d - mm->domains; + + /* Init domain struct */ + d->ip4_prefix.as_u32 = ip4_prefix->as_u32; + d->ip4_prefix_len = ip4_prefix_len; + d->ip6_prefix = *ip6_prefix; + d->ip6_prefix_len = ip6_prefix_len; + d->ip4_src = *ip4_src; + d->mtu = mtu; + + if (ip4_prefix_len < 32) + d->shift = 64 - ip6_prefix_len + (32 - ip4_prefix_len); + + /* Init IP adjacency */ + memset(&adj, 0, sizeof(adj)); + adj.explicit_fib_index = ~0; + p = (u32 *)&adj.rewrite_data[0]; + *p = (u32) (*sixrd_domain_index); + + /* Create ip6 adjacency */ + memset(&args6, 0, sizeof(args6)); + args6.table_index_or_table_id = 0; + args6.flags = IP6_ROUTE_FLAG_ADD; + args6.dst_address.as_u64[0] = ip6_prefix->as_u64[0]; + args6.dst_address.as_u64[1] = ip6_prefix->as_u64[1]; + args6.dst_address_length = ip6_prefix_len; + args6.adj_index = ~0; + args6.add_adj = &adj; + args6.n_add_adj = 1; + adj.lookup_next_index = mm->ip6_lookup_next_index; + ip6_add_del_route(im6, &args6); + + /* Multiple SIXRD domains may share same source IPv4 TEP */ + uword *q = ip4_get_route(im4, 0, 0, (u8 *)ip4_src, 32); + if (q) { + u32 ai = q[0]; + ip_lookup_main_t *lm4 = &ip4_main.lookup_main; + ip_adjacency_t *adj4 = ip_get_adjacency(lm4, ai); + if (adj4->lookup_next_index != mm->ip4_lookup_next_index) { + clib_warning("BR source address already assigned: %U", format_ip4_address, ip4_src); + pool_put(mm->domains, d); + return -1; + } + /* Shared source */ + p = (u32 *)&adj4->rewrite_data[0]; + p[0] = ~0; + + /* Add refcount, so we don't accidentially delete the route underneath someone */ + p[1]++; + } else { + /* Create ip4 adjacency. */ + memset(&args4, 0, sizeof(args4)); + args4.table_index_or_table_id = 0; + args4.flags = IP4_ROUTE_FLAG_ADD; + args4.dst_address.as_u32 = ip4_src->as_u32; + args4.dst_address_length = 32; + args4.adj_index = ~0; + args4.add_adj = &adj; + args4.n_add_adj = 1; + adj.lookup_next_index = mm->ip4_lookup_next_index; + ip4_add_del_route(im4, &args4); + } + + return 0; +} + +/* + * sixrd_delete_domain + */ +int +sixrd_delete_domain (u32 sixrd_domain_index) +{ + sixrd_main_t *mm = &sixrd_main; + ip4_main_t *im4 = &ip4_main; + ip6_main_t *im6 = &ip6_main; + sixrd_domain_t *d; + ip_adjacency_t adj; + ip4_add_del_route_args_t args4; + ip6_add_del_route_args_t args6; + + if (pool_is_free_index(mm->domains, sixrd_domain_index)) { + clib_warning("SIXRD domain delete: domain does not exist: %d", sixrd_domain_index); + return -1; + } + + d = pool_elt_at_index(mm->domains, sixrd_domain_index); + + memset(&adj, 0, sizeof(adj)); + adj.explicit_fib_index = ~0; + + /* Delete ip6 adjacency */ + memset(&args6, 0, sizeof (args6)); + args6.table_index_or_table_id = 0; + args6.flags = IP6_ROUTE_FLAG_DEL; + args6.dst_address.as_u64[0] = d->ip6_prefix.as_u64[0]; + args6.dst_address.as_u64[1] = d->ip6_prefix.as_u64[1]; + args6.dst_address_length = d->ip6_prefix_len; + args6.adj_index = 0; + args6.add_adj = &adj; + args6.n_add_adj = 0; + ip6_add_del_route(im6, &args6); + + /* Delete ip4 adjacency */ + uword *q = ip4_get_route(im4, 0, 0, (u8 *)&d->ip4_src, 32); + if (q) { + u32 ai = q[0]; + ip_lookup_main_t *lm4 = &ip4_main.lookup_main; + ip_adjacency_t *adj4 = ip_get_adjacency(lm4, ai); + + u32 *p = (u32 *)&adj4->rewrite_data[0]; + /* Delete route when no other domains use this source */ + if (p[1] == 0) { + memset(&args4, 0, sizeof(args4)); + args4.table_index_or_table_id = 0; + args4.flags = IP4_ROUTE_FLAG_DEL; + args4.dst_address.as_u32 = d->ip4_prefix.as_u32; + args4.dst_address_length = d->ip4_prefix_len; + args4.adj_index = 0; + args4.add_adj = &adj; + args4.n_add_adj = 0; + ip4_add_del_route(im4, &args4); + } + p[1]--; + } + + pool_put(mm->domains, d); + + return 0; +} + +static clib_error_t * +sixrd_add_domain_command_fn (vlib_main_t *vm, + unformat_input_t *input, + vlib_cli_command_t *cmd) +{ + unformat_input_t _line_input, *line_input = &_line_input; + ip4_address_t ip4_prefix; + ip6_address_t ip6_prefix; + ip4_address_t ip4_src; + u32 ip6_prefix_len, ip4_prefix_len, sixrd_domain_index; + u32 num_m_args = 0; + /* Optional arguments */ + u32 mtu = 0; + + /* Get a line of input. */ + if (!unformat_user(input, unformat_line_input, line_input)) + return 0; + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { + if (unformat(line_input, "ip6-pfx %U/%d", unformat_ip6_address, &ip6_prefix, &ip6_prefix_len)) + num_m_args++; + else if (unformat(line_input, "ip4-pfx %U/%d", unformat_ip4_address, &ip4_prefix, &ip4_prefix_len)) + num_m_args++; + else if (unformat(line_input, "ip4-src %U", unformat_ip4_address, &ip4_src)) + num_m_args++; + else if (unformat(line_input, "mtu %d", &mtu)) + num_m_args++; + else + return clib_error_return(0, "unknown input `%U'", + format_unformat_error, input); + } + unformat_free(line_input); + + if (num_m_args < 3) + return clib_error_return(0, "mandatory argument(s) missing"); + + sixrd_create_domain(&ip6_prefix, ip6_prefix_len, &ip4_prefix, ip4_prefix_len, + &ip4_src, &sixrd_domain_index, mtu); + + return 0; +} + +static clib_error_t * +sixrd_del_domain_command_fn (vlib_main_t *vm, + unformat_input_t *input, + vlib_cli_command_t *cmd) +{ + unformat_input_t _line_input, *line_input = &_line_input; + u32 num_m_args = 0; + u32 sixrd_domain_index; + + /* Get a line of input. */ + if (! unformat_user(input, unformat_line_input, line_input)) + return 0; + + while (unformat_check_input(line_input) != UNFORMAT_END_OF_INPUT) { + if (unformat(line_input, "index %d", &sixrd_domain_index)) + num_m_args++; + else + return clib_error_return(0, "unknown input `%U'", + format_unformat_error, input); + } + unformat_free(line_input); + + if (num_m_args != 1) + return clib_error_return(0, "mandatory argument(s) missing"); + + sixrd_delete_domain(sixrd_domain_index); + + return 0; +} + +static u8 * +format_sixrd_domain (u8 *s, va_list *args) +{ + sixrd_domain_t *d = va_arg(*args, sixrd_domain_t *); + sixrd_main_t *mm = &sixrd_main; + + s = format(s, + "[%d] ip6-pfx %U/%d ip4-pfx %U/%d ip4-src %U mtu %d", + d - mm->domains, + format_ip6_address, &d->ip6_prefix, d->ip6_prefix_len, + format_ip4_address, &d->ip4_prefix, d->ip4_prefix_len, + format_ip4_address, &d->ip4_src, d->mtu); + + return s; +} + +static clib_error_t * +show_sixrd_domain_command_fn (vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd) +{ + sixrd_main_t *mm = &sixrd_main; + sixrd_domain_t *d; + + if (pool_elts(mm->domains) == 0) + vlib_cli_output(vm, "No SIXRD domains are configured..."); + + pool_foreach(d, mm->domains, ({vlib_cli_output(vm, "%U", format_sixrd_domain, d);})); + + return 0; + +} + +static clib_error_t * +show_sixrd_stats_command_fn (vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd) +{ + sixrd_main_t *mm = &sixrd_main; + sixrd_domain_t *d; + int domains = 0, domaincount = 0; + if (pool_elts (mm->domains) == 0) + vlib_cli_output (vm, "No SIXRD domains are configured..."); + + pool_foreach(d, mm->domains, ({ + domains += sizeof(*d); + domaincount++; + })); + + vlib_cli_output(vm, "SIXRD domains structure: %d\n", sizeof (sixrd_domain_t)); + vlib_cli_output(vm, "SIXRD domains: %d (%d bytes)\n", domaincount, domains); + + return 0; +} + +/* + * packet trace format function + */ +u8 * +format_sixrd_trace (u8 *s, va_list *args) +{ + CLIB_UNUSED(vlib_main_t *vm) = va_arg (*args, vlib_main_t *); + CLIB_UNUSED(vlib_node_t *node) = va_arg (*args, vlib_node_t *); + sixrd_trace_t *t = va_arg (*args, sixrd_trace_t *); + u32 sixrd_domain_index = t->sixrd_domain_index; + + s = format(s, "SIXRD domain index: %d", sixrd_domain_index); + + return s; +} + +VLIB_CLI_COMMAND(sixrd_add_domain_command, static) = { + .path = "sixrd add domain", + .short_help = + "sixrd add domain ip6-pfx ip4-pfx ip4-src ", + .function = sixrd_add_domain_command_fn, +}; + +VLIB_CLI_COMMAND(sixrd_del_command, static) = { + .path = "sixrd del domain", + .short_help = + "sixrd del domain index ", + .function = sixrd_del_domain_command_fn, +}; + +VLIB_CLI_COMMAND(show_sixrd_domain_command, static) = { + .path = "show sixrd domain", + .function = show_sixrd_domain_command_fn, +}; + +VLIB_CLI_COMMAND(show_sixrd_stats_command, static) = { + .path = "show sixrd stats", + .function = show_sixrd_stats_command_fn, +}; + +/* + * This routine exists to convince the vlib plugin framework that + * we haven't accidentally copied a random .dll into the plugin directory. + * + * Also collects global variable pointers passed from the vpp engine + */ +clib_error_t * +vlib_plugin_register (vlib_main_t * vm, vnet_plugin_handoff_t * h, + int from_early_init) +{ + clib_error_t * error = 0; + sixrd_main_t *mm = &sixrd_main; + + mm->vnet_main = vnet_get_main(); + mm->vlib_main = vm; + + return error; +} + +static clib_error_t * sixrd_init (vlib_main_t * vm) +{ + clib_error_t * error = 0; + sixrd_main_t *mm = &sixrd_main; + + vlib_node_t * ip6_lookup_node = vlib_get_node_by_name(vm, (u8 *)"ip6-lookup"); + vlib_node_t * ip4_lookup_node = vlib_get_node_by_name(vm, (u8 *)"ip4-lookup"); + vlib_node_t * ip6_sixrd_node = vlib_get_node_by_name(vm, (u8 *)"ip6-sixrd"); + vlib_node_t * ip4_sixrd_node = vlib_get_node_by_name(vm, (u8 *)"ip4-sixrd"); + ASSERT(ip6_lookup_node && ip4_lookup_node && ip6_sixrd_node && ip4_sixrd_node); + + mm->ip6_lookup_next_index = vlib_node_add_next(vm, ip6_lookup_node->index, ip6_sixrd_node->index); + mm->ip4_lookup_next_index = vlib_node_add_next(vm, ip4_lookup_node->index, ip4_sixrd_node->index); + + return error; +} + +VLIB_INIT_FUNCTION (sixrd_init); diff --git a/plugins/sixrd-plugin/sixrd/sixrd.h b/plugins/sixrd-plugin/sixrd/sixrd.h new file mode 100644 index 00000000..2f0912f0 --- /dev/null +++ b/plugins/sixrd-plugin/sixrd/sixrd.h @@ -0,0 +1,144 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2009-2014 Cisco and/or its affiliates. + * 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 +#include +#include +#include + +int sixrd_create_domain(ip6_address_t *ip6_prefix, u8 ip6_prefix_len, + ip4_address_t *ip4_prefix, u8 ip4_prefix_len, + ip4_address_t *ip4_src, u32 *sixrd_domain_index, u16 mtu); +int sixrd_delete_domain(u32 sixrd_domain_index); +u8 *format_sixrd_trace(u8 *s, va_list *args); + +typedef struct { + ip6_address_t ip6_prefix; + ip4_address_t ip4_prefix; + ip4_address_t ip4_src; + u8 ip6_prefix_len; + u8 ip4_prefix_len; + + /* helpers */ + u8 shift; + + u16 mtu; +} sixrd_domain_t; + +typedef struct { + /* pool of SIXRD domains */ + sixrd_domain_t *domains; + + /* convenience */ + vlib_main_t *vlib_main; + vnet_main_t *vnet_main; + + u32 ip4_lookup_next_index; + u32 ip6_lookup_next_index; +} sixrd_main_t; + +#define foreach_sixrd_error \ + /* Must be first. */ \ + _(NONE, "valid SIXRD packets") \ + _(BAD_PROTOCOL, "bad protocol") \ + _(WRONG_ICMP_TYPE, "wrong icmp type") \ + _(SEC_CHECK, "security check failed") \ + _(ICMP, "unable to translate ICMP") \ + _(UNKNOWN, "unknown") \ + _(NO_DOMAIN, "no domain") \ + _(ENCAPSULATED, "encapsulated") \ + _(DECAPSULATED, "decapsulated") \ + _(TRANSLATED_4TO6, "translated 4 to 6") \ + _(TRANSLATED_6TO4, "translated 6 to 4") \ + _(FRAGMENT, "fragment handling error") \ + _(FRAGMENT_QUEUED, "dropped, missing first fragment") \ + _(FRAGMENTED, "packets requiring fragmentation") \ + _(FRAGMENT_PARTS, "fragment parts") \ + _(MALFORMED, "malformed packet") + +typedef enum { +#define _(sym,str) SIXRD_ERROR_##sym, + foreach_sixrd_error +#undef _ + SIXRD_N_ERROR, + } sixrd_error_t; + +typedef struct { + u32 sixrd_domain_index; +} sixrd_trace_t; + +sixrd_main_t sixrd_main; + +/* + * sixrd_get_addr + */ +static_always_inline u32 +sixrd_get_addr (sixrd_domain_t *d, u64 dal) +{ + + /* 1:1 mode */ + if (d->ip4_prefix_len == 32) return (d->ip4_prefix.as_u32); + + /* Grab 32 - ip4_prefix_len bits out of IPv6 address from offset ip6_prefix_len */ + return (d->ip4_prefix.as_u32 | (u32)(dal >> d->shift)); +} + +/* + * Get the SIXRD domain from an IPv6 lookup adjacency. + */ +static_always_inline sixrd_domain_t * +ip6_sixrd_get_domain (u32 adj_index, u32 *sixrd_domain_index) +{ + sixrd_main_t *mm = &sixrd_main; + ip_lookup_main_t *lm = &ip6_main.lookup_main; + ip_adjacency_t *adj = ip_get_adjacency(lm, adj_index); + ASSERT(adj); + uword *p = (uword *)adj->rewrite_data; + ASSERT(p); + *sixrd_domain_index = p[0]; + return pool_elt_at_index(mm->domains, p[0]); +} + +/* + * Get the SIXRD domain from an IPv4 lookup adjacency. + * If the IPv4 address is not shared, no lookup is required. + * The IPv6 address is used otherwise. + */ +static_always_inline sixrd_domain_t * +ip4_sixrd_get_domain (u32 adj_index, ip6_address_t *addr, + u32 *sixrd_domain_index, u8 *error) +{ + sixrd_main_t *mm = &sixrd_main; + ip6_main_t *im6 = &ip6_main; + ip_lookup_main_t *lm4 = &ip4_main.lookup_main; + ip_lookup_main_t *lm6 = &ip6_main.lookup_main; + ip_adjacency_t *adj = ip_get_adjacency(lm4, adj_index); + ASSERT(adj); + uword *p = (uword *)adj->rewrite_data; + ASSERT(p); + *sixrd_domain_index = p[0]; + if (p[0] != ~0) + return pool_elt_at_index(mm->domains, p[0]); + + u32 ai = ip6_fib_lookup_with_table(im6, 0, addr); + ip_adjacency_t *adj6 = ip_get_adjacency (lm6, ai); + if (PREDICT_TRUE(adj6->lookup_next_index == mm->ip6_lookup_next_index)) { + uword *p = (uword *)adj6->rewrite_data; + *sixrd_domain_index = p[0]; + return pool_elt_at_index(mm->domains, *sixrd_domain_index); + } + *error = SIXRD_ERROR_NO_DOMAIN; + return NULL; +} diff --git a/plugins/vcgn-plugin/Makefile.am b/plugins/vcgn-plugin/Makefile.am new file mode 100644 index 00000000..f9705d05 --- /dev/null +++ b/plugins/vcgn-plugin/Makefile.am @@ -0,0 +1,99 @@ +# Copyright (c) 2015 Cisco and/or its affiliates. +# 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. + +AUTOMAKE_OPTIONS = foreign subdir-objects + +AM_CFLAGS = -Wall -I@TOOLKIT_INCLUDE@ + +######################################## +# Virtual Carrier Grade NAT +######################################## + +libvcgn_plugin_la_SOURCES = \ + vcgn/cnat_bulk_port.c \ + vcgn/cnat_config.c \ + vcgn/cnat_db_scanner.c \ + vcgn/cnat_db_v2.c \ + vcgn/cnat_debug_msg_handler.c \ + vcgn/cnat_cli_handler.c \ + vcgn/cnat_global.c \ + vcgn/cnat_ipv4_udp_inside_input.c \ + vcgn/cnat_ipv4_udp_inside_input_exceptions.c \ + vcgn/cnat_ipv4_udp_outside_input.c \ + vcgn/cnat_ipv4_tcp_inside_input.c \ + vcgn/cnat_ipv4_tcp_inside_input_exceptions.c \ + vcgn/cnat_ipv4_tcp_outside_input.c \ + vcgn/cnat_ipv4_icmp_query_inside_input.c \ + vcgn/cnat_ipv4_icmp_query_inside_input_exception.c \ + vcgn/cnat_ipv4_icmp_query_outside_input.c \ + vcgn/cnat_ipv4_icmp_error_inside_input.c \ + vcgn/cnat_ipv4_icmp_error_outside_input.c \ + vcgn/cnat_logging.c \ + vcgn/cnat_ports.c \ + vcgn/cnat_util.c \ + vcgn/cnat_show.c \ + vcgn/cnat_syslog.c \ + vcgn/cnat_v4_functions.c \ + vcgn/index_list.c \ + vcgn/spp_platform_trace_log.c \ + vcgn/vcgn_classify.c + +nobase_include_HEADERS = \ + vcgn/cgn_bitmap.h \ + vcgn/cgse_defs.h \ + vcgn/cnat_bulk_port_defs.h \ + vcgn/cnat_bulk_port.h \ + vcgn/cnat_cli.h \ + vcgn/cnat_common_api.h \ + vcgn/cnat_config_api.h \ + vcgn/cnat_config.h \ + vcgn/cnat_db.h \ + vcgn/cnat_global.h \ + vcgn/cnat_ipv4_icmp.h \ + vcgn/cnat_ipv4_udp.h \ + vcgn/cnat_log_api.h \ + vcgn/cnat_log_common.h \ + vcgn/cnat_logging.h \ + vcgn/cnat_pcp_server.h \ + vcgn/cnat_ports.h \ + vcgn/cnat_show_api.h \ + vcgn/cnat_show_response.h \ + vcgn/cnat_syslog.h \ + vcgn/cnat_v4_ftp_alg.h \ + vcgn/cnat_v4_functions.h \ + vcgn/cnat_v4_pptp_alg.h \ + vcgn/cnat_va_db.h \ + vcgn/dslite_db.h \ + vcgn/dslite_defs.h \ + vcgn/index_list.h \ + vcgn/nat64_db.h \ + vcgn/nat64_defs.h \ + vcgn/nat64_tcp_sm.h \ + vcgn/platform_common.h \ + vcgn/platform_common_override.h \ + vcgn/spp_ctx.h \ + vcgn/spp_platform_trace_log.h \ + vcgn/spp_timers.h \ + vcgn/tcp_header_definitions.h \ + vcgn/vcgn_db.h + +libvcgn_plugin_la_LDFLAGS = -module + +lib_LTLIBRARIES = libvcgn_plugin.la + +if WITH_PLUGIN_TOOLKIT +install-data-hook: + mkdir /usr/lib/vpp_plugins || true + mkdir /usr/lib/vpp_api_test_plugins || true + cp -L $(prefix)/lib/libvcgn_plugin.so /usr/lib/vpp_plugins +endif diff --git a/plugins/vcgn-plugin/configure.ac b/plugins/vcgn-plugin/configure.ac new file mode 100644 index 00000000..ced22669 --- /dev/null +++ b/plugins/vcgn-plugin/configure.ac @@ -0,0 +1,17 @@ +AC_INIT(vcgn_plugin, 1.0) +LT_INIT +AM_INIT_AUTOMAKE + +AM_PROG_AS +AC_PROG_CC +AM_PROG_CC_C_O + +AC_ARG_WITH(plugin-toolkit, + AC_HELP_STRING([--with-plugin-toolkit], + [build using the vpp toolkit]), + [with_plugin_toolkit=${prefix}/include], + [with_plugin_toolkit=.]) + +AC_SUBST(TOOLKIT_INCLUDE,[${with_plugin_toolkit}]) +AM_CONDITIONAL(WITH_PLUGIN_TOOLKIT, test "$with_plugin_toolkit" != ".") +AC_OUTPUT([Makefile]) diff --git a/plugins/vcgn-plugin/vcgn/README b/plugins/vcgn-plugin/vcgn/README new file mode 100644 index 00000000..9b903967 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/README @@ -0,0 +1,100 @@ + ================================= + CARRIER GRADE NAT - NAT44 README + ================================= + +What is implemented: +==================== +* NAT44 UDP, TCP, ICMP protocols +* Show and config commands for various parameters for the same +* NF9 logging is implemented but is not tested + +What is not implemented: +========================= +* TCP MSS +* TCP refresh direction +* Static port forwarding +* Syslog support +* Destination based logging or session logging +* None of the ALGs +* Performance optimization +* Binary APIs, suitable for configuring the feature from netconf/restconf/yang +* Support for VLANs + +Setup +===== + + +--------------+ ++------------+ GEb/0/0 | | +| Tester +-------------->+ vCGN/vPE-f | +| +<--------------+ VM in UCS | ++------------+ GE13/0/0 | | + +--------------+ + +Configure Interfaces and add routes in vPE-f +============================================= +set int ip address GigabitEthernetb/0/0 10.4.5.2/24 +set int state GigabitEthernetb/0/0 up +set int ip address GigabitEthernet13/0/0 20.4.5.2/24 +set int state GigabitEthernet13/0/0 up +ip route add 4.4.4.0/24 via GigabitEthernet13/0/0 +ip route add 1.2.3.0/24 via GigabitEthernetb/0/0 show ip fib + +Configure vCGN NAT44 for UDP/TCP/ICMP +======================================= +set vcgn inside GigabitEthernetb/0/0 outside GigabitEthernet13/0/0 +set vcgn port limit 65535 set vcgn dynamic port start 5641 +set vcgn map 10.1.1.0 - 10.1.1.31 set vcgn tcp timeout active 65535 init 65535 +set vcgn udp timeout active 65535 init 65535 set vcgn icmp timeout 65535 + +Set ARP entries for CGN to Tester +================================== +set ip arp GigabitEthernet13/0/0 4.4.4.4 11:22:33:44:55:00 +set ip arp GigabitEthernetb/0/0 1.2.3.0 11:22:33:44:55:10 +set ip arp GigabitEthernetb/0/0 1.2.3.1 11:22:33:44:55:12 +set ip arp GigabitEthernetb/0/0 1.2.3.2 11:22:33:44:55:13 +set ip arp GigabitEthernetb/0/0 1.2.3.3 11:22:33:44:55:14 +set ip arp GigabitEthernetb/0/0 1.2.3.4 11:22:33:4e:55:11 +set ip arp GigabitEthernetb/0/0 1.2.3.5 11:22:33:44:55:15 +set ip arp GigabitEthernetb/0/0 1.2.3.6 11:22:33:44:55:16 +set ip arp GigabitEthernetb/0/0 1.2.3.7 11:22:33:44:55:17 +set ip arp GigabitEthernetb/0/0 1.2.3.8 11:22:33:44:55:18 +set ip arp GigabitEthernetb/0/0 1.2.3.9 11:22:33:44:55:19 +set ip arp GigabitEthernetb/0/0 1.2.3.10 11:22:33:44:55:1a +set ip arp GigabitEthernetb/0/0 1.2.3.11 11:22:33:44:55:1b +set ip arp GigabitEthernetb/0/0 1.2.3.12 11:22:33:44:55:1c +set ip arp GigabitEthernetb/0/0 1.2.3.13 11:22:33:44:55:1d +set ip arp GigabitEthernetb/0/0 1.2.3.14 11:22:33:44:55:1e +set ip arp GigabitEthernetb/0/0 1.2.3.15 11:22:33:44:55:1f +set ip arp GigabitEthernetb/0/0 1.2.3.16 11:22:33:44:50:01 +set ip arp GigabitEthernetb/0/0 1.2.3.17 11:22:33:44:51:01 +set ip arp GigabitEthernetb/0/0 1.2.3.18 11:22:33:44:52:01 +set ip arp GigabitEthernetb/0/0 1.2.3.19 11:22:33:44:53:01 +set ip arp GigabitEthernetb/0/0 1.2.3.20 11:22:33:44:54:02 +set ip arp GigabitEthernetb/0/0 1.2.3.21 11:22:33:44:55:01 +set ip arp GigabitEthernetb/0/0 1.2.3.22 11:22:33:44:56:02 +set ip arp GigabitEthernetb/0/0 1.2.3.23 11:22:33:44:57:00 +set ip arp GigabitEthernetb/0/0 1.2.3.24 11:22:33:44:58:02 +set ip arp GigabitEthernetb/0/0 1.2.3.25 11:22:33:44:59:03 +set ip arp GigabitEthernetb/0/0 1.2.3.26 11:22:33:44:5a:01 +set ip arp GigabitEthernetb/0/0 1.2.3.27 11:22:33:44:5b:02 +set ip arp GigabitEthernetb/0/0 1.2.3.28 11:22:33:44:5c:03 +set ip arp GigabitEthernetb/0/0 1.2.3.29 11:22:33:44:5d:04 +set ip arp GigabitEthernetb/0/0 1.2.3.30 11:22:33:44:5e:05 +set ip arp GigabitEthernetb/0/0 1.2.3.31 11:22:33:44:5f:06 + + +Show commands +============= +show vcgn config +show vcgn statistics +show node counters +show interface + +Show commands to show translations +================================== +show vcgn inside-translation protocol tcp inside-addr 1.2.3.4 start-port 5641 end-port 5645 +show vcgn outside-translation protocol tcp outside-addr 10.1.1.31 start-port 7000 end-port 8000 +show vcgn inside-translation protocol icmp inside-addr 1.2.3.4 start-port 7000 end-port 8000 +show vcgn outside-translation protocol icmp outside-addr 10.1.1.31 start-port 7000 end-port 8000 + + diff --git a/plugins/vcgn-plugin/vcgn/cgn_bitmap.h b/plugins/vcgn-plugin/vcgn/cgn_bitmap.h new file mode 100644 index 00000000..6c46b75a --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cgn_bitmap.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2015 Cisco and/or its affiliates. + * 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. + */ +/* + * Modifications to this file + * Copyright (c) 2006-2009 by cisco Systems, Inc. + * All rights reserved. + */ + +/* + Copyright (c) 2001, 2002, 2003, 2005 Eliot Dresselhaus + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef __CGN_BITMAP_H__ +#define __CGN_BITMAP_H__ + +/* Bitmaps built as vectors of machine words. */ + +#include +#include +#include +#include +#include + +#define clib_bitmap_dup(v) vec_dup(v) +#define clib_bitmap_free(v) vec_free(v) +#define clib_bitmap_bytes(v) vec_bytes(v) +#define clib_bitmap_zero(v) vec_zero(v) + +/* Allocate bitmap with given number of bits. */ +#define clib_bitmap_alloc(v,n_bits) \ + v = vec_new (uword, ((n_bits) + BITS (uword) - 1) / BITS (uword)) + +/* Sets given bit. Returns old value. */ +static inline uword +cgn_clib_bitmap_set_no_check (uword * a, uword i) +{ + uword i0 = i / BITS (a[0]); + uword bit = (uword) 1 << (i % BITS (a[0])); + uword ai; + +/* ASSERT (i0 < vec_len (a)); */ + ai = a[i0]; + a[i0] = ai | bit; + + return (ai & bit) != 0; +} + +/* Clears given bit. Returns old value. */ +static inline +uword cgn_clib_bitmap_clear_no_check (uword * a, uword i) +{ + uword i0 = i / BITS (a[0]); + uword bit = (uword) 1 << (i % BITS (a[0])); + uword ai; + +/* ASSERT (i0 < vec_len (a)); */ + ai = a[i0]; + a[i0] = ai & ~bit; + + return (ai & bit) != 0; +} + +/* Gets num_bits from ai start at start. assume that all bits are + * in the same uword. + */ +static inline uword cgn_clib_bitmap_get_bits (uword *ai, u16 start, + unsigned char num_bits) +{ + uword i0 = start / BITS (ai[0]); + uword i1 = start % BITS (ai[0]); + uword result = ai[i0] >> i1; + if(num_bits >= BITS(ai[0])) return result; + /* Else, we have to trim the bits */ + result = result & (((uword)1 << num_bits) - 1); + return result; +} + +/* Check if all of the bits from start to numb_bits are avaiable */ +static inline uword cgn_clib_bitmap_check_if_all (uword *ai, u16 start, + i16 num_bits) +{ + /* Now check if any bits are zero.. if yes, return false */ + uword bitmask; + if(num_bits >= BITS(ai[0])) { + /* assume that its going to be multiples of BUTS(ai[0]) */ + uword i0 = start / BITS (ai[0]); + bitmask = ~0; /* set all bits to 1 */ + do { + if(ai[i0] ^ bitmask) return 0; + num_bits = num_bits - BITS (ai[0]); + i0++; + } while (num_bits > 0); + return 1; + } + else { + uword result = cgn_clib_bitmap_get_bits (ai, start, num_bits); + bitmask = ((uword)1 << num_bits) -1; /* set only num_bits */ + return (!(result ^ bitmask)); + } +} + +#endif diff --git a/plugins/vcgn-plugin/vcgn/cgse_defs.h b/plugins/vcgn-plugin/vcgn/cgse_defs.h new file mode 100644 index 00000000..08255875 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cgse_defs.h @@ -0,0 +1,88 @@ +/* + *------------------------------------------------------------------ + * cgse_defs.h - CGSE specific definiitions + * + * Copyright (c) 2007-2013 Cisco and/or its affiliates. + * 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 __CGSE_DEFS_H__ +#define __CGSE_DEFS_H__ + +#include "spp_platform_common.h" +#include + + +#define CGSE_SVI_TYPE_CNAT 1 +#define CGSE_SVI_TYPE_XLAT 2 +#define CGSE_SVI_TYPE_NAT64_STATEFUL 3 +#define CGSE_SVI_TYPE_V6RD 4 +#define CGSE_SVI_TYPE_INFRA 5 +#define CGSE_SVI_TYPE_DS_LITE 7 +#define CGSE_SVI_TYPE_MAPE 9 + +#define CGSE_SET_TX_PKT_TYPE(type) PLATFORM_SET_CTX_RU_TX_PKT_TYPE(ctx, type) + +#define CGSE_INVALID_UIDX 0xffff /*invalid svi app uidb index */ +#define CGSE_INVALID_VRFID 0xffffffff /*invalid vrf id */ + +#define CGSE_VRF_MASK 0x3fff +#define CGSE_MAX_VRFMAP_ENTRIES (CGSE_VRF_MASK + 1) + +#define CGSE_VRFMAP_ENTRY_INVALID 0xffff + + +#define CGSE_INVALID_CGSE_ID (0) + +#define CGSE_TABLE_ENTRY_DELETED 0 +#define CGSE_TABLE_ENTRY_ACTIVE 1 +#define CGSE_TABLE_ENTRY_DORMANT 2 +#define CGSE_TABLE_ENTRY_INVALID_UIDB 3 + + +#define CGSE_CONFIG_HANDLER_DEBUG_PRINTF1(level, a) \ + if (cgse_config_debug_level > level) printf(a); + +#define CGSE_CONFIG_HANDLER_DEBUG_PRINTF2(level, a, b) \ + if (cgse_config_debug_level > level) printf(a, b); + +#define CGSE_CONFIG_HANDLER_DEBUG_PRINTF3(level, a, b, c) \ + if (cgse_config_debug_level > level) printf(a, b, c); + +#define CGSE_CONFIG_HANDLER_DEBUG_PRINTF4(level, a, b, c, d) \ + if (cgse_config_debug_level > level) printf(a, b, c, d); + +#define CGSE_CONFIG_HANDLER_DEBUG_PRINTF5(level, a, b, c, d, e) \ + if (cgse_config_debug_level > level) printf(a, b, c, d, e); + +#define CGSE_CONFIG_HANDLER_DEBUG_PRINTF6(level, a, b, c, d, e, f) \ + if (cgse_config_debug_level > level) printf(a, b, c, d, e, f); + +#define CGSE_CONFIG_HANDLER_DEBUG_PRINTF7(level, a, b, c, d, e, f, g) \ + if (cgse_config_debug_level > level) printf(a, b, c, d, e, f, g); + +#define CGSE_CONFIG_HANDLER_DEBUG_PRINTF8(level, a, b, c, d, e, f, g, h) \ + if (cgse_config_debug_level > level) printf(a, b, c, d, e, f, g, h); + +#define CGSE_CONFIG_HANDLER_DEBUG_PRINTF9(level, a, b, c, d, e, f, g, h, i) \ + if (cgse_config_debug_level > level) printf(a, b, c, d, e, f, g, h, i); + +extern u16 *cgse_uidb_index_cgse_id_mapping_ptr; + +#define CGSE_ADD_UIDB_INDEX_CGSE_ID_MAPPING(uidb_index, cgse_id) \ + *(cgse_uidb_index_cgse_id_mapping_ptr + uidb_index) = cgse_id; + +extern u8 my_instance_number; + +#endif diff --git a/plugins/vcgn-plugin/vcgn/cnat_bulk_port.c b/plugins/vcgn-plugin/vcgn/cnat_bulk_port.c new file mode 100644 index 00000000..d8894eb8 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_bulk_port.c @@ -0,0 +1,964 @@ +/* + *------------------------------------------------------------------ + * cnat_bulk_ports.c - wrappers for bulk port allocation + * + * Copyright (c) 2011-2013 Cisco and/or its affiliates. + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include "cnat_db.h" +#include "cnat_config.h" +#include "cnat_global.h" +#include "cnat_logging.h" +#include "spp_timers.h" +#include "platform_common.h" +#include "cgn_bitmap.h" +#include "spp_platform_trace_log.h" +#include "cnat_ports.h" + +#ifndef NO_BULK_LOGGING + +#define PORT_TO_CACHE(y, z) ((y)/(z)) +/* The last bit (MSB) is used to indicate whether the cache entry is full */ +#define CACHE_TO_PORT(x, z) (((x)& 0x7FFF) * (z)) +#define IS_CACHE_ENTRY_FULL(x) ((x) & 0x8000) +#define MARK_CACHE_ENTRY_AS_FULL(x) ((x) = ((x) | 0x8000)) +#define UNMARK_CACHE_ENTRY_AS_FULL(x) ((x) = ((x) & 0x7FFF)) +#define CACHE_ENTRY_WITHOUT_FULL_STAT(x) ((x) & 0x7FFF) + + +#define NUM_BULK_CHECK 128 /* max number of previous chache to check. + * somewhat orbirtrary.. assume 64 as bulk size.. can handle up + * to 128*64 ports allocated by a single subscriber */ + +/* #define DEBUG_BULK_PORT 1 */ +/* #define DEBUG_BULK_PORT_DETAIL 1 */ +#define HAVE_BULK_PORT_STATS 1 + +#ifdef HAVE_BULK_PORT_STATS +static uword bulk_cache_hit_count; +static uword bulk_port_use_count; +static uword bulk_port_alloc_count; +static uword mapped_port_alloc_count; +#endif /* HAVE_BULK_PORT_STATS */ + +static u32 bulk_port_rand_across; + +void show_bulk_port_allocation(u16 in_vrfid, u32 inside_ip) +{ + cnat_db_key_bucket_t u_ki; + cnat_user_db_entry_t *udb; + int i; + u32 head; + cnat_main_db_entry_t *db = NULL; + i16 printed_so_far = 0; /* entries printed so far */ + u16 prev_bulks[NUM_BULK_CHECK]; + cnat_vrfmap_t *my_vrfmap = 0; + cnat_vrfmap_t *vrfmap = 0; + bulk_alloc_size_t bulk_size; + + u_ki.k.k.vrf = in_vrfid; + u_ki.k.k.ipv4 = inside_ip; + u_ki.k.k.port = 0; + + PLATFORM_DEBUG_PRINT("Searching for user %x in invrf %d\n", + inside_ip, in_vrfid); + udb = cnat_user_db_lookup_entry(&u_ki); + if(!udb) { + PLATFORM_DEBUG_PRINT("No such user\n"); return; + } + + pool_foreach (vrfmap, cnat_map_by_vrf, ({ + if(vrfmap->i_vrf == in_vrfid) { + my_vrfmap = vrfmap; + break; + }})); + + if(!my_vrfmap) { + PLATFORM_DEBUG_PRINT("Vrf map not found\n"); + return; + } + bulk_size = BULKSIZE_FROM_VRFMAP(my_vrfmap); + + if(bulk_size == BULK_ALLOC_SIZE_NONE) { + PLATFORM_DEBUG_PRINT("Bulk allocation not enabled\n"); + return; + } + + PLATFORM_DEBUG_PRINT("\nBulk cache for subscriber 0x%x: ", inside_ip); + for(i=0; i < BULK_RANGE_CACHE_SIZE; i++) { + PLATFORM_DEBUG_PRINT("%d , ", + CACHE_TO_PORT(udb->bulk_port_range_cache[i], bulk_size)); + } + PLATFORM_DEBUG_PRINT("\nNon cached bulk allocation for subscriber 0x%x:\n", + inside_ip); + ASSERT(udb); + memset(prev_bulks, 0,sizeof(prev_bulks)); + + head = udb->translation_list_head_index; + if(PREDICT_FALSE(head == EMPTY)) { + return; + } + db = cnat_main_db + head; + while (1) { + /* skip static ports - static ports may not belong to bulk pool*/ + if(db->out2in_key.k.port < cnat_static_port_range) goto next_entry; + + u16 bm_index = PORT_TO_CACHE(db->out2in_key.k.port, bulk_size); + + /*Check if we have already tested this bulk */ + for(i=0; i < printed_so_far; i++) { + if(prev_bulks[i] == bm_index) goto next_entry; + } + + /*Check if this base port is already part of cache */ + for(i=0; i < BULK_RANGE_CACHE_SIZE; i++) { + if(CACHE_ENTRY_WITHOUT_FULL_STAT(udb->bulk_port_range_cache[i]) + == bm_index) { + goto next_entry; + } + } + /* this is not in chache already */ + PLATFORM_DEBUG_PRINT("%d ", CACHE_TO_PORT(bm_index, bulk_size)); + if(printed_so_far < NUM_BULK_CHECK) { + prev_bulks[printed_so_far] = bm_index; + printed_so_far++; + } + +next_entry: + db = cnat_main_db + db->user_ports.next; + /* + * its a circular list, so if we have reached the head again + * all the entries for that user have been read + */ + if (db == (cnat_main_db + head)) { + break; + } + } /* while loop for db entries */ + + PLATFORM_DEBUG_PRINT("\n"); + return; +} + +void show_bulk_port_stats() +{ + + cnat_vrfmap_t *my_vrfmap = 0; + PLATFORM_DEBUG_PRINT("Bulk size settings of each inside vrf ...\n"); + pool_foreach (my_vrfmap, cnat_map_by_vrf, ({ + PLATFORM_DEBUG_PRINT("vrf id %d, bulk size %d\n", my_vrfmap->i_vrf, + BULKSIZE_FROM_VRFMAP(my_vrfmap)); + })); + +#ifdef HAVE_BULK_PORT_STATS + PLATFORM_DEBUG_PRINT("\nBulk port allocation, use and cache hit statistics\n"); + PLATFORM_DEBUG_PRINT("Number of times bulk ports allocated %lld\n", + bulk_port_alloc_count); + PLATFORM_DEBUG_PRINT("Number of times pre-allocated ports used %lld\n", + bulk_port_use_count); + PLATFORM_DEBUG_PRINT( + "Number of times pre-allocated bulk port found from cache %lld\n", + bulk_cache_hit_count); + PLATFORM_DEBUG_PRINT( + "Number of times mapped port (static) allocations made %lld\n", + mapped_port_alloc_count); +#else + PLATFORM_DEBUG_PRINT("\nNat44 bulk port statistics not turned on\n"); +#endif /* HAVE_BULK_PORT_STATS */ +} + +void clear_bulk_port_stats() +{ +#ifdef HAVE_BULK_PORT_STATS + bulk_port_alloc_count = 0; + bulk_port_use_count = 0; + bulk_cache_hit_count = 0; + mapped_port_alloc_count = 0; +#endif /* HAVE_BULK_PORT_STATS */ + return; +} + +void cnat_update_bulk_range_cache(cnat_user_db_entry_t *udb, u16 o_port, + bulk_alloc_size_t bulk_size) +{ + i16 i; + if(!udb) { +#ifdef DEBUG_BULK_PORT + PLATFORM_DEBUG_PRINT("%s, null udb!\n", __func__); +#endif + return; + } + if(BULK_ALLOC_SIZE_NONE == bulk_size) { /* no bulk logging */ + return; + } + + /* Take care of caching */ + if(o_port & 0x1) { + o_port--; + } + if(PREDICT_FALSE(o_port <= 0)) { +#ifdef DEBUG_BULK_PORT + PLATFORM_DEBUG_PRINT("%s invalid port: %d\n", __func__, o_port); +#endif + return; + } + + /* First preference is for the cache entry's that are not used yet */ + for(i=0; i < BULK_RANGE_CACHE_SIZE; i++) { + if(PREDICT_FALSE( + udb->bulk_port_range_cache[i] == (i16)BULK_RANGE_INVALID)) { + udb->bulk_port_range_cache[i] = PORT_TO_CACHE(o_port, bulk_size); + return; + } + } + + /* Now check if any cache entry is full and if it can be replaced */ + for(i=0; i < BULK_RANGE_CACHE_SIZE; i++) { + if(PREDICT_FALSE(IS_CACHE_ENTRY_FULL(udb->bulk_port_range_cache[i]))) { + udb->bulk_port_range_cache[i] = PORT_TO_CACHE(o_port, bulk_size); + return; + } + } + + return; +} + + +void cnat_port_free_v2_bulk ( + cnat_portmap_v2_t *pm, + int index, + port_pair_t ptype, + u16 base_port, + cnat_user_db_entry_t *udb, + u16 static_port_range, + bulk_alloc_size_t bulk_size, + int *nfv9_log_req) +{ + cnat_portmap_v2_t *my_pm; + i16 bm_index; + i16 i; + int unmark_full_status = 0; + + *nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED; + + /* First free up the port */ + cnat_port_free_v2(pm, index, ptype, base_port, static_port_range); + if(BULK_ALLOC_SIZE_NONE == bulk_size) /* no bulk logging */ + return; + if(PREDICT_FALSE(!udb)) { +#ifdef DEBUG_BULK_PORT + PLATFORM_DEBUG_PRINT("%s udb is null\n", __func__); +#endif + } + + if(PREDICT_FALSE(base_port < static_port_range)) { + return; + } + /* Now check if cache needs to be removed */ + my_pm = pm + index; + base_port = base_port/bulk_size; + base_port = base_port * bulk_size; /*Align it to multiples of bulk_size */ + if(PREDICT_TRUE(!cgn_clib_bitmap_check_if_all( + my_pm->bm, base_port, bulk_size))) { + *nfv9_log_req = CACHE_ALLOC_NO_LOG_REQUIRED; + unmark_full_status = 1; + /* One or more ports are still in use */ + } else { + *nfv9_log_req = base_port; /* logging required now. indicate base port*/ + } + bm_index = PORT_TO_CACHE(base_port, bulk_size); + /* Now check if this is in the cache */ + for(i=0; i < BULK_RANGE_CACHE_SIZE; i++) { + if(PREDICT_FALSE( + CACHE_ENTRY_WITHOUT_FULL_STAT(udb->bulk_port_range_cache[i])) + == bm_index) { + if(unmark_full_status) { + /* Unmark full stat.. if it was marked so..*/ + UNMARK_CACHE_ENTRY_AS_FULL(udb->bulk_port_range_cache[i]); + } else { + udb->bulk_port_range_cache[i] = (i16)BULK_RANGE_INVALID; +#ifdef DEBUG_BULK_PORT + PLATFORM_DEBUG_PRINT( + "Clearing cache for client 0x%x, bulk port %d\n", + my_pm->ipv4_address, base_port); +#endif + } + break; + } + } + return; +} + + +/* Get suitable port from range */ +static i16 get_suiting_port_pos_from_range(cnat_portmap_v2_t *my_pm, + u16 bulk_start, i16 bulk_size, port_pair_t pair_type) +{ + i16 num_pos = 0, num_bits, iterations; + uword bulk_ports; + i16 inc = 0; + i16 num_uwords = bulk_size/BITS(my_pm->bm[0]); + + if(PREDICT_FALSE(!num_uwords)) { + iterations = 0; + num_bits = bulk_size; + bulk_size = 0; + } else { + bulk_port_rand_across = randq1(bulk_port_rand_across); + iterations = bulk_port_rand_across % num_uwords; + num_bits = BITS(my_pm->bm[0]); + } + + do { + bulk_ports = cgn_clib_bitmap_get_bits(my_pm->bm, + (bulk_start + iterations * BITS(my_pm->bm[0])), num_bits); +#ifdef DEBUG_BULK_PORT_DETAIL + PLATFORM_DEBUG_PRINT("%s %d, bulk start %d, num_bits %d, ports %lld \n", + __func__, __LINE__, bulk_start, num_bits, bulk_ports); +#endif /* DEBUG_BULK_PORT_DETAIL */ + if(PREDICT_FALSE(!bulk_ports)) goto next_uword; + if(PREDICT_TRUE((pair_type == PORT_SINGLE) + || (pair_type == PORT_PAIR))) { + num_pos =0; + inc = 1; + } else if(pair_type == PORT_S_ODD) { + num_pos = 1; + inc = 2; + } else if(pair_type == PORT_S_EVEN) { + num_pos =0; + inc = 2; + } + + for(; num_pos < num_bits; num_pos = num_pos + inc) { + if(!((bulk_ports >> num_pos) & 1)) + continue; /* In use */ + /* Check if the available port meets our + * criteria such as add, even, pair etc */ + else if(PREDICT_FALSE( + (pair_type == PORT_PAIR) && ((num_pos & 0x1) || + (!((bulk_ports >> (num_pos + 1)) & 1))))) + continue; + else break; /* Found one that meets the criteria */ + } + if(num_pos < num_bits) + return (num_pos + iterations * BITS(my_pm->bm[0])); +next_uword: + num_bits = BITS(my_pm->bm[0]); + bulk_size -= BITS(my_pm->bm[0]); + iterations++; + if(iterations >= num_uwords) iterations = 0; + } while (bulk_size > 0); + + return -2; /* nothing found */ +} + +static cnat_errno_t try_bulk_port_from_non_cache( + cnat_user_db_entry_t *udb, + cnat_portmap_v2_t *my_pm, + port_pair_t pair_type, + bulk_alloc_size_t bulk_size, + u16 *port_available, + u16 static_port_range + ) +{ + /**** + 1. user should have existing translations.. otherwise, we wouldn't get here. + 2. For each, get the outside port. get the base port. + check if it is already in cache + 3. if not, we stand chance. + 4. Check for availability from this non cached pool. + 5. if found, repalce this with one of the cache that is invalid or full?? + 6. if we are replacing the cache.. it has to be governed by user + preference on prefer oldest pool or prefer newest pool + ********/ + u32 head; + cnat_main_db_entry_t *db = NULL; + u16 bulk_start; /* start point in 64 bitmap array to search for port */ + i16 port_pos; /* indicates the position of available port in bulk */ + i16 i; /* just a counter */ + i16 attempts_so_far = 0; /* (futile-;) attemps so far..*/ + u16 prev_bulks[NUM_BULK_CHECK]; + ASSERT(udb); + memset(prev_bulks, 0,sizeof(prev_bulks)); + + head = udb->translation_list_head_index; + if(PREDICT_FALSE(head == EMPTY)) return CNAT_NO_PRE_ALLOCATED_BULK_PORTS; + + db = cnat_main_db + head; + while (1) { //what should be the limit?? + + /* skip static ports - static ports may not belong to bulk pool*/ + if(db->out2in_key.k.port < static_port_range) goto next_entry; + + u16 bm_index = PORT_TO_CACHE(db->out2in_key.k.port, bulk_size); + + /*Check if we have already tested this bulk */ + for(i=0; i < attempts_so_far; i++) { + if(prev_bulks[i] == bm_index) { + goto next_entry; + } + } + + /*Check if this base port is already part of cache */ + for(i=0; i < BULK_RANGE_CACHE_SIZE; i++) { + if(CACHE_ENTRY_WITHOUT_FULL_STAT(udb->bulk_port_range_cache[i]) + == bm_index) + goto next_entry; + } + + /* this is not in chache already */ + bulk_start = CACHE_TO_PORT(bm_index, bulk_size); + port_pos = get_suiting_port_pos_from_range(my_pm, + bulk_start, bulk_size, pair_type); + + if(port_pos < 0) { /* no port available in this range */ + /* Mark this bulk so that we don't have to try this again */ + if(attempts_so_far < NUM_BULK_CHECK) { + prev_bulks[attempts_so_far] = bm_index; + attempts_so_far++; + } + goto next_entry; + } + + /* Got one...Get the port number */ + *port_available = bulk_start + port_pos; + + /* Check to see if we shoud replace one of the cache */ + for(i=0; i < BULK_RANGE_CACHE_SIZE; i++) { + if(PREDICT_FALSE((udb->bulk_port_range_cache[i] + == (i16)BULK_RANGE_INVALID) || ( + IS_CACHE_ENTRY_FULL(udb->bulk_port_range_cache[i])))) { + udb->bulk_port_range_cache[i] = bm_index; + return CNAT_SUCCESS; + } + } + /* Check to replace an existing (in use) entry */ + /* TODO: enforce policy */ + /* order of looping should depend on policy */ + + return CNAT_SUCCESS; + +next_entry: + db = cnat_main_db + db->user_ports.next; + /* + * its a circular list, so if we have reached the head again + * all the entries for that user have been read + */ + if (db == (cnat_main_db + head)) { + break; + } + } /* while loop for db entries */ + /* no ports available from pre allocated bulk pool */ + return CNAT_NO_PORT_FROM_BULK; +} + +cnat_errno_t +cnat_dynamic_port_alloc_v2_bulk ( + cnat_portmap_v2_t *pm, + port_alloc_t atype, + port_pair_t pair_type, + u32 *index, + u32 *o_ipv4_address, + u16 *o_port, + u16 static_port_range, + cnat_user_db_entry_t *udb, + bulk_alloc_size_t bulk_size, + int *nfv9_log_req, + u16 ip_n_to_1, + u32 *rseed_ip + ) +{ + + cnat_errno_t rv; + u16 port_available = 0; + i16 i; + cnat_portmap_v2_t *my_pm; + + if((BULK_ALLOC_SIZE_NONE != bulk_size) /* bulk logging enabled */ + && (udb)) { /* This user does have translations already */ + u16 bulk_start; + i16 port_pos; + + my_pm = pm + *index; + /* We have a case to check if bulk allocated ports can be used */ + /* TODO: order of looping to be based on policy + * like prefer older or prefer newer ?? + * For now, start with most recent cache entry + * so that we stand a better chance of + * finding a port + */ + for(i= 0; i < BULK_RANGE_CACHE_SIZE; i++) { + if(PREDICT_TRUE((udb->bulk_port_range_cache[i] == + (i16)BULK_RANGE_INVALID) || + IS_CACHE_ENTRY_FULL(udb->bulk_port_range_cache[i]))) { + continue; /* This range is not initialized yet or it is full */ + } + bulk_start = CACHE_TO_PORT(udb->bulk_port_range_cache[i], + bulk_size); + port_pos = get_suiting_port_pos_from_range(my_pm, + bulk_start, bulk_size, pair_type); + if(PREDICT_FALSE(port_pos < 0)) { + /* Mark this cache entry as full so that we do not + * waste time on this entry again */ + MARK_CACHE_ENTRY_AS_FULL(udb->bulk_port_range_cache[i]); +#ifdef DEBUG_BULK_PORT + PLATFORM_DEBUG_PRINT("Marked bulk cache entry %d as full for %x \n", + i, my_pm->ipv4_address); +#endif /* #ifdef DEBUG_BULK_PORT */ + continue; + } + /* Get the port number */ + port_available = bulk_start+ port_pos; +#ifdef DEBUG_BULK_PORT + PLATFORM_DEBUG_PRINT( + "Found port from cache : IP 0x%x, port %d %d iterations\n", + my_pm->ipv4_address, port_available, i) +#endif +#ifdef HAVE_BULK_PORT_STATS + bulk_cache_hit_count++; +#endif /* HAVE_BULK_PORT_STATS */ + break; + } /* end of for loop for cache check */ + /* If we have not found a port yet, check if we can have + * pre allocated bulk port from non-cache */ + if(PREDICT_FALSE(i == BULK_RANGE_CACHE_SIZE)) { + if( try_bulk_port_from_non_cache(udb, my_pm, pair_type, + bulk_size, &port_available, + static_port_range) != CNAT_SUCCESS ) { + goto ALLCOATE_NEW_BULK; + } +#ifdef DEBUG_BULK_PORT + PLATFORM_DEBUG_PRINT("Found port from non-cache : IP 0x%x, port %d\n", + my_pm->ipv4_address, port_available); +#endif + } + /* Assign the port, mark it as in use */ + cgn_clib_bitmap_clear_no_check(my_pm->bm, port_available); + (my_pm->inuse)++; + if(PREDICT_FALSE(pair_type == PORT_PAIR)) {/* Mark the next one too */ + cgn_clib_bitmap_clear_no_check(my_pm->bm, port_available + 1); + (my_pm->inuse)++; + } + *o_ipv4_address = my_pm->ipv4_address; + *o_port = port_available; + *nfv9_log_req = CACHE_ALLOC_NO_LOG_REQUIRED; +#ifdef HAVE_BULK_PORT_STATS + bulk_port_use_count++; +#endif /* HAVE_BULK_PORT_STATS */ + return (CNAT_SUCCESS); + } +ALLCOATE_NEW_BULK: +#ifdef DEBUG_BULK_PORT + if(BULK_ALLOC_SIZE_NONE != bulk_size) { + PLATFORM_DEBUG_PRINT( + "No port available from bulk cache, bulk size %d\n", bulk_size); + } +#endif + /* For whatever reason, we have not got a port yet */ + rv = cnat_dynamic_port_alloc_v2(pm, atype, pair_type, index, + o_ipv4_address, o_port, static_port_range, bulk_size, nfv9_log_req, + ip_n_to_1, rseed_ip); + if (PREDICT_FALSE(rv != CNAT_SUCCESS)) { + return rv; + } + /* Take care of caching */ + if(PREDICT_FALSE(udb != NULL)) { + /* Predict false because, we usually allocate for new users */ + cnat_update_bulk_range_cache(udb, *o_port, bulk_size); + } +#ifdef HAVE_BULK_PORT_STATS + bulk_port_alloc_count++; +#endif /* HAVE_BULK_PORT_STATS */ + return (CNAT_SUCCESS); +} + + +cnat_errno_t +cnat_static_port_alloc_v2_bulk ( + cnat_portmap_v2_t *pm, + port_alloc_t atype, + port_pair_t pair_type, + u32 i_ipv4_address, + u16 i_port, + u32 *index, + u32 *o_ipv4_address, + u16 *o_port, + u16 static_port_range, + cnat_user_db_entry_t *udb, + bulk_alloc_size_t bulk_size, + int *nfv9_log_req, + u16 ip_n_to_1 + ) +{ + + /*** + * Requirements - + * 1. If the port allocated is below dyn start, it should be individual + * port (not bulk) + * 2. If NOT, it should be bulk allocated + * 3. Try and keep the inside port same as outside port in both the + * cases (best effort) + + * Algorithm + * 1. Check if it is below stat port start or user is new or bulk is + * disabled. If yes, call existing function + * 2. If not, see if we can pick from bulk and yet try to keep the port + * same - difficult thing - check if the port is free - then check if the + * entire bulk is free - if not check if bulk is owned by the user already. + * If all of these fail, call existing function to allocate a new bulk + * 3. Update cache, etc return log requirements + *****/ + + cnat_errno_t rv; + i16 i; + u32 head; + cnat_portmap_v2_t *my_pm; + uword bit_test_result, start_bit; + cnat_main_db_entry_t *db = NULL; + + if((BULK_ALLOC_SIZE_NONE != bulk_size) /* bulk logging enabled */ + && (udb) && /* This user does have translations already */ + i_port >= static_port_range ) { /* It is outside stat port range*/ + + my_pm = pm + *index; + /* We have a case to check if bulk allocated ports can be used */ + + /* First check if the required port is available. */ + if(PREDICT_FALSE(clib_bitmap_get_no_check(my_pm->bm, i_port) == 0)) { + goto ALLOCATE_NEW_BULK_STATIC; + } + + /* Port is free.. check if the bulk is also free */ + start_bit= ((i_port/bulk_size) * bulk_size); + bit_test_result = cgn_clib_bitmap_check_if_all(my_pm->bm, + start_bit, bulk_size); + if(PREDICT_TRUE(bit_test_result)) { /* bulk is available, grab it */ + goto ALLOCATE_NEW_BULK_STATIC; + } + + /* else, bulk is taken by someone. check if it is me */ + /* Check if we own the bulk by any chance */ + for(i=0; i < BULK_RANGE_CACHE_SIZE; i++) { + if(udb->bulk_port_range_cache[i] == start_bit) break; + } + if(i == BULK_RANGE_CACHE_SIZE) { /* no luck with cache */ + head = udb->translation_list_head_index; + if(PREDICT_FALSE(head == EMPTY)) + goto ALLOCATE_NEW_BULK_STATIC; + db = cnat_main_db + head; + i = 0; + while(1) { + if((db->out2in_key.k.port/bulk_size) * bulk_size == start_bit) { + i = 1; /* Just to indicate it is found */ + break; + } + db = cnat_main_db + db->user_ports.next; + /* + * its a circular list, so if we have reached the head again + * all the entries for that user have been read + */ + if (db == (cnat_main_db + head)) break; + } /* while loop for db entries */ + if(!i) { + goto ALLOCATE_NEW_BULK_STATIC; + } + } + /* Assign the port, mark it as in use */ + cgn_clib_bitmap_clear_no_check(my_pm->bm, i_port); + (my_pm->inuse)++; + *o_ipv4_address = my_pm->ipv4_address; + *o_port = i_port; + *nfv9_log_req = CACHE_ALLOC_NO_LOG_REQUIRED; +#ifdef HAVE_BULK_PORT_STATS + bulk_port_use_count++; +#endif /* HAVE_BULK_PORT_STATS */ + +#ifdef DEBUG_BULK_PORT + PLATFORM_DEBUG_PRINT("%s, %d, found stat port from bulk: %x, %d\n", + __func__, + __LINE__, *o_ipv4_address, *o_port); +#endif /* DEBUG_BULK_PORT */ + return (CNAT_SUCCESS); + } + +ALLOCATE_NEW_BULK_STATIC: +#ifdef DEBUG_BULK_PORT + PLATFORM_DEBUG_PRINT("%s No port available from bulk cache, bulk size %d\n", + __func__,bulk_size); +#endif + /* For whatever reason, we have not got a port yet */ + rv = cnat_static_port_alloc_v2(pm, atype, pair_type, i_ipv4_address, + i_port, index, o_ipv4_address, o_port, static_port_range, + bulk_size, nfv9_log_req,ip_n_to_1); + if (PREDICT_FALSE(rv != CNAT_SUCCESS)) { + return rv; + } + /* Take care of caching only if it was a bulk alloc */ + if(PREDICT_FALSE(udb && (BULK_ALLOC_NOT_ATTEMPTED != *nfv9_log_req))) { + cnat_update_bulk_range_cache(udb, *o_port, bulk_size); + } +#ifdef HAVE_BULK_PORT_STATS + bulk_port_alloc_count++; +#endif /* HAVE_BULK_PORT_STATS */ + return (CNAT_SUCCESS); + +} + +cnat_errno_t +cnat_mapped_static_port_alloc_v2_bulk ( + cnat_portmap_v2_t *pm, + port_alloc_t atype, + u32 *index, + u32 ipv4_address, + u16 port, + cnat_user_db_entry_t *udb, + bulk_alloc_size_t bulk_size, + int *nfv9_log_req, + u16 ip_n_to_1 + ) +{ + /* Requirements : + * 1. Check if bulk allocation is required. + * 2. Call cnat_mapped_static_port_alloc_v2 to allocate + * 3. Decide if alloc has to be cached + * 4. Update nfv9_log_req + */ + cnat_errno_t rv; + rv = cnat_mapped_static_port_alloc_v2 (pm, + atype, index, ipv4_address, port, nfv9_log_req, bulk_size, ip_n_to_1); + if (PREDICT_FALSE(rv != CNAT_SUCCESS)) { + return rv; + } + /* Take care of caching only if it was a bulk alloc */ + if(PREDICT_FALSE(udb && (BULK_ALLOC_NOT_ATTEMPTED != *nfv9_log_req))) { + int i; + port = port*bulk_size; + port = port/bulk_size; /* align it to bulk size boundary */ + for(i=0; i < BULK_RANGE_CACHE_SIZE; i++) { + if(CACHE_ENTRY_WITHOUT_FULL_STAT(udb->bulk_port_range_cache[i]) + == PORT_TO_CACHE(port, bulk_size)) + break; + } + if( i == BULK_RANGE_CACHE_SIZE) { /* else, it is alredy in cache */ + cnat_update_bulk_range_cache(udb, port, bulk_size); + } + } +#ifdef HAVE_BULK_PORT_STATS + mapped_port_alloc_count++; +#endif /* HAVE_BULK_PORT_STATS */ + return (CNAT_SUCCESS); +} + + +cnat_errno_t +cnat_dynamic_port_alloc_rtsp_bulk ( + cnat_portmap_v2_t *pm, + port_alloc_t atype, + port_pair_t pair_type, + u16 i_port, + u32 *index, + u32 *o_ipv4_address, + u16 *o_port, + u16 static_port_range, + cnat_user_db_entry_t *udb, + bulk_alloc_size_t bulk_size, + int *nfv9_log_req, + u32 *rseed_ip) +{ + + /*** + * Algorithm + * 1. Compute the range of ports required based on the number of digits + * in the port request made by the client. + * 2. Check if bulk logging is enabled. If not, use the existing method. + * 3. Check if there are 2 adjacent ports available that meet the above + * criteria in any of the bulk allocations made already. + * 4. If yes, mark them in use and return. + * 5. If not allocate a new bulk and pick 2 ports in it + ***/ + + i16 i; + cnat_portmap_v2_t *my_pm = 0; + u32 start_port1, end_port1, start_port2, end_port2; + int range_loop; + u16 bulk_start; + i16 port_pos; + u16 port_available = 0; + + ASSERT(index); + ASSERT(o_ipv4_address); + ASSERT(o_port); + + /* + * Check if the port is 4 digit or 5 digit. I am assuming we are + * not getting 3 (or 2 or 1) digit ports, which we cannot anyway + * allocate same sized outside ports - as outside ports start from 1024 + * + * Static Port has its own reserved range. Ensure that the range is + * such that atleast few 4 digit ports are available for RTSP. If + * not it does not make sense to do special allocation for RTSP. + */ + if (PREDICT_TRUE(static_port_range < MIN_STATIC_PORT_RANGE_FOR_RTSP)) { + /* + * 4 digit port or less + */ + if (i_port <= 9999) { + start_port1 = static_port_range; + end_port1 = 9999; + + start_port2 = 10000; + end_port2 = PORTS_PER_ADDR - 1; + } else { /* 5 digit port */ + start_port1 = 10000; + end_port1 = PORTS_PER_ADDR - 1; + + start_port2 = static_port_range; + end_port2 = 9999; + } + } else { /* Static port range is too big */ + start_port1 = static_port_range; + end_port1 = PORTS_PER_ADDR - 1; + + /* + * PORTS_PER_ADDR is just a placeholder for + * INVALID_PORT, valid ports are b/w 1 and PORTS_PER_ADDR + */ + start_port2 = PORTS_PER_ADDR; + end_port2 = PORTS_PER_ADDR; + } + + + if(PREDICT_TRUE(udb != NULL)) { + my_pm = pm + *index; + } + + /* Now check if this user already owns a bulk range that is + * within start range 1 + */ + + u32 start_range = start_port1; + u32 end_range = end_port1; + for(range_loop = 0; range_loop < 2; range_loop++) { + if((BULK_ALLOC_SIZE_NONE == bulk_size) || (!udb)) { + goto ALLOCATE_NEW_RTSP_PORTS; + } + for(i= 0; i < BULK_RANGE_CACHE_SIZE; i++) { + if(PREDICT_TRUE((udb->bulk_port_range_cache[i] == + (i16)BULK_RANGE_INVALID) || + IS_CACHE_ENTRY_FULL(udb->bulk_port_range_cache[i]))) { + continue; /* This range is not initialized yet or it is full */ + } + + bulk_start = CACHE_TO_PORT(udb->bulk_port_range_cache[i], + bulk_size); + if(bulk_start < start_port1 || bulk_start >= end_port1) { + continue; /* Not in the range */ + } + + port_pos = get_suiting_port_pos_from_range(my_pm, + bulk_start, bulk_size, pair_type); + if(PREDICT_FALSE(port_pos < 0)) { + /* Not Marking this cache entry as full as it failed + * for pair type. It might have individual entries + */ + continue; + } + /* Get the port number */ + port_available = bulk_start+ port_pos; +#ifdef DEBUG_BULK_PORT + PLATFORM_DEBUG_PRINT( + "Found port from cache : IP 0x%x, port %d %d iterations\n", + my_pm->ipv4_address, port_available, i) +#endif +#ifdef HAVE_BULK_PORT_STATS + bulk_cache_hit_count += 2; +#endif /* HAVE_BULK_PORT_STATS */ + break; + } /* end of for loop for cache check */ + + if(PREDICT_FALSE(i == BULK_RANGE_CACHE_SIZE)) { + /* we have not found a port yet, but to do not want to try + * non-cache bulks.. because, it is a very low probability and + * do not want to tweak that code for this special case + * The impact of non checking the non-cache is, we give this + * user few extra ports .. which is OK + */ + goto ALLOCATE_NEW_RTSP_PORTS; + } +#ifdef DEBUG_BULK_PORT + PLATFORM_DEBUG_PRINT("RTSP: Found port from non-cache : IP 0x%x, port %d\n", + my_pm->ipv4_address, port_available); +#endif + + /* Assign the port, mark it as in use */ + cgn_clib_bitmap_clear_no_check(my_pm->bm, port_available); + (my_pm->inuse)++; + cgn_clib_bitmap_clear_no_check(my_pm->bm, port_available + 1); + (my_pm->inuse)++; + + *o_ipv4_address = my_pm->ipv4_address; + *o_port = port_available; + *nfv9_log_req = CACHE_ALLOC_NO_LOG_REQUIRED; +#ifdef HAVE_BULK_PORT_STATS + bulk_port_use_count += 2; +#endif /* HAVE_BULK_PORT_STATS */ + return (CNAT_SUCCESS); + +ALLOCATE_NEW_RTSP_PORTS: + /* No luck. Let's try allocating new bulk.. */ + if(PREDICT_TRUE(CNAT_SUCCESS == cnat_dynamic_port_alloc_rtsp + (pm, atype, pair_type, + start_range, end_range,index, o_ipv4_address, + o_port, bulk_size, nfv9_log_req,rseed_ip))) { + if(PREDICT_FALSE(udb && + (BULK_ALLOC_NOT_ATTEMPTED != *nfv9_log_req))) { + cnat_update_bulk_range_cache(udb, *o_port, bulk_size); + } +#ifdef HAVE_BULK_PORT_STATS + bulk_port_alloc_count++; +#endif /* HAVE_BULK_PORT_STATS */ + return CNAT_SUCCESS; + } + + /* Could not allocate in range 1.. so move to range 2. */ + start_range = start_port2; + end_range = end_port2; + + } + + return (CNAT_NOT_FOUND_DIRECT); /* if we are here, we could not get any ports */ + +} + +#else /* Dummy definitions */ +void show_bulk_port_stats() +{ + PLATFORM_DEBUG_PRINT("\nBulk logging feature not included\n"); +} + + void clear_bulk_port_stats() +{ + PLATFORM_DEBUG_PRINT("\nBulk logging feature not included\n"); +} +#endif /* NO_BULK_LOGGING */ diff --git a/plugins/vcgn-plugin/vcgn/cnat_bulk_port.h b/plugins/vcgn-plugin/vcgn/cnat_bulk_port.h new file mode 100644 index 00000000..3e48b9a7 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_bulk_port.h @@ -0,0 +1,157 @@ +/* + *------------------------------------------------------------------ + * cnat_bulk_port_defs.h bulk port alloc definitions + * + * Copyright (c) 2011-2013 Cisco and/or its affiliates. + * 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 __CNAT_BULK_PORT_H__ +#define __CNAT_BULK_PORT_H__ + +#ifndef NO_BULK_LOGGING +#include "cnat_bulk_port_defs.h" + +cnat_errno_t +cnat_dynamic_port_alloc_v2_bulk ( + cnat_portmap_v2_t *pm, + port_alloc_t atype, + port_pair_t pair_type, + u32 *index, + u32 *o_ipv4_address, + u16 *o_port, + u16 static_port_range, + cnat_user_db_entry_t *udb, + bulk_alloc_size_t bulk_size, + int *nfv9_log_req, + u16 ip_n_to_1, + u32 *rseed_ip); + +void cnat_update_bulk_range_cache(cnat_user_db_entry_t *udb, u16 o_port, + bulk_alloc_size_t bulk_size); + +void cnat_port_free_v2_bulk ( + cnat_portmap_v2_t *pm, + int index, + port_pair_t ptype, + u16 base_port, + cnat_user_db_entry_t *udb, + u16 static_port_range, + bulk_alloc_size_t bulk_size, + int *nfv9_log_req); + +cnat_errno_t cnat_static_port_alloc_v2_bulk ( + cnat_portmap_v2_t *pm, + port_alloc_t atype, + port_pair_t pair_type, + u32 i_ipv4_address, + u16 i_port, + u32 *index, + u32 *o_ipv4_address, + u16 *o_port, + u16 static_port_range, + cnat_user_db_entry_t *udb, + bulk_alloc_size_t bulk_size, + int *nfv9_log_req, + u16 ip_n_to_1 + ); + +cnat_errno_t cnat_dynamic_port_alloc_rtsp_bulk ( + cnat_portmap_v2_t *pm, + port_alloc_t atype, + port_pair_t pair_type, + u16 i_port, + u32 *index, + u32 *o_ipv4_address, + u16 *o_port, + u16 static_port_range, + cnat_user_db_entry_t *udb, + bulk_alloc_size_t bulk_size, + int *nfv9_log_req, + u32 *rseed_ip); + +cnat_errno_t +cnat_mapped_static_port_alloc_v2_bulk ( + cnat_portmap_v2_t *pm, + port_alloc_t atype, + u32 *index, + u32 ipv4_address, + u16 port, + cnat_user_db_entry_t *udb, + bulk_alloc_size_t bulk_size, + int *nfv9_log_req, + u16 ip_n_to_1 + ); + +#else /* NO_BULK_LOGGING */ +/* use older code */ +inline cnat_errno_t +cnat_dynamic_port_alloc_v2_bulk ( + cnat_vrfmap_t *vrf_map, + port_alloc_t atype, + port_pair_t pair_type, + u32 *index, + u32 *o_ipv4_address, + u16 *o_port, + u16 static_port_range, + u16 ip_n_to_1, + u32 *rseed_ip + ) +{ + return cnat_dynamic_port_alloc_v2(vrf_map->portmap_list, atype, + pair_type, index, o_ipv4_address, o_port, static_port_range, + ip_n_to_1, rseed_ip); +} + +inline void cnat_port_free_v2_bulk ( + cnat_portmap_v2_t *pm, + int index, + port_pair_t ptype, + u16 base_port, + cnat_user_db_entry_t *udb, + u16 static_port_range); +{ + return cnat_port_free_v2(pm, index, ptype, base_port, + static_port_range); +} + +inline cnat_errno_t cnat_static_port_alloc_v2_bulk ( + cnat_portmap_v2_t *pm, + port_alloc_t atype, + port_pair_t pair_type, + u32 i_ipv4_address, + u16 i_port, + u32 *index, + u32 *o_ipv4_address, + u16 *o_port, + u16 static_port_range) +{ + return cnat_static_port_alloc_v2 (pm, atype, pair_type, + i_ipv4_address, i_port, index, o_ipv4_address, o_port); +} + +inline cnat_errno_t +cnat_mapped_static_port_alloc_v2_bulk ( + cnat_portmap_v2_t *pm, + port_alloc_t atype, + u32 *index, + u32 ipv4_address, + u16 port) +{ + return cnat_mapped_static_port_alloc_v2(pm, atype, index + ipv4_address, port); +} + +#endif /* NO_BULK_LOGGING */ +#endif /* __CNAT_BULK_PORT_H__ */ diff --git a/plugins/vcgn-plugin/vcgn/cnat_bulk_port_defs.h b/plugins/vcgn-plugin/vcgn/cnat_bulk_port_defs.h new file mode 100644 index 00000000..edb47b0a --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_bulk_port_defs.h @@ -0,0 +1,57 @@ +/* + *------------------------------------------------------------------ + * cnat_bulk_port_defs.h bulk port alloc definitions + * + * Copyright (c) 2011 Cisco and/or its affiliates. + * 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 __CNAT_BULK_PORT_DEFS_H__ +#define __CNAT_BULK_PORT_DEFS_H__ + + +#ifndef NO_BULK_LOGGING + +typedef enum { + BULK_ALLOC_SIZE_NONE = 1, + BULK_ALLOC_SIZE_16 = 16, + BULK_ALLOC_SIZE_32 = 32, + BULK_ALLOC_SIZE_64 = 64, + BULK_ALLOC_SIZE_128 = 128, + BULK_ALLOC_SIZE_256 = 256, + BULK_ALLOC_SIZE_512 = 512, + BULK_ALLOC_SIZE_1024 = 1024, + BULK_ALLOC_SIZE_2048 = 2048, + BULK_ALLOC_SIZE_4096 = 4096 +} bulk_alloc_size_t; + +/* #define DEBUG_BULK_PORT 1 TODO: remove this later */ + +#define CACHE_ALLOC_NO_LOG_REQUIRED -1 +#define BULK_ALLOC_NOT_ATTEMPTED -2 + +#define BULK_RANGE_INVALID 0xFFFF +#define BULK_RANGE_CACHE_SIZE 4 + +#define BULKSIZE_FROM_VRFMAP(vrfmap) ((vrfmap)->bulk_size) + +#define INIT_BULK_CACHE(udb) \ + { \ + int i; \ + for(i =0; i < BULK_RANGE_CACHE_SIZE; i++) \ + (udb)->bulk_port_range_cache[i] = (i16)BULK_RANGE_INVALID; \ + } + +#endif /* NO_BULK_LOGGING */ +#endif /* __CNAT_BULK_PORT_DEFS_H__ */ diff --git a/plugins/vcgn-plugin/vcgn/cnat_cli.h b/plugins/vcgn-plugin/vcgn/cnat_cli.h new file mode 100644 index 00000000..e9d190a5 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_cli.h @@ -0,0 +1,206 @@ +/* *------------------------------------------------------------------ + * cnat_cli.h - CLI definitions + * + * Copyright (c) 2007-2013 Cisco and/or its affiliates. + * 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 __CNAT_CLI_H__ +#define __CNAT_CLI_H__ + +#include "cnat_config_api.h" +#include "cnat_show_api.h" + +/* from iox cli error */ +typedef enum { + CNAT_SUCCESS = 0, + CNAT_NO_CONFIG, + CNAT_NO_VRF_RUN, + CNAT_NO_POOL_ANY, + CNAT_NO_PORT_ANY, +#ifndef NO_BULK_LOGGING + CNAT_NO_PORT_FROM_BULK, + CNAT_NO_PRE_ALLOCATED_BULK_PORTS, +#endif /* NO_BULK_LOGGING */ + CNAT_BAD_INUSE_ANY, + CNAT_NOT_FOUND_ANY, + CNAT_INV_PORT_DIRECT, + CNAT_DEL_PORT_DIRECT, + CNAT_BAD_INUSE_DIRECT, + CNAT_NOT_FOUND_DIRECT, + CNAT_OUT_LIMIT, + CNAT_MAIN_DB_LIMIT, + CNAT_USER_DB_LIMIT, + CNAT_NOT_STATIC_PORT, + CNAT_BAD_STATIC_PORT_REQ, + CNAT_NOT_THIS_CORE, + CNAT_ERR_PARSER, + CNAT_ERR_INVALID_MSG_ID, + CNAT_ERR_INVALID_MSG_SIZE, + CNAT_ERR_INVALID_PAYLOAD_SIZE, + CNAT_ERR_BAD_TCP_UDP_PORT, + CNAT_ERR_BULK_SINGLE_FAILURE, + CNAT_ERR_XLAT_ID_INVALID, + CNAT_ERR_XLAT_V6_PREFIX_INVALID, + CNAT_ERR_XLAT_V4_PREFIX_INVALID, + CNAT_ERR_XLAT_TCP_MSS_INVALID, + CNAT_ERR_6RD_ID_INVALID, + CNAT_ERR_6RD_V4_TUNNEL_SRC_INVALID, + CNAT_ERR_6RD_V6_PREFIX_INVALID, + CNAT_ERR_6RD_V6_BR_UNICAST_INVALID, + CNAT_ERR_6RD_V4_PREFIX_MASK_LEN_INVALID, + CNAT_ERR_6RD_V4_SUFFIX_MASK_LEN_INVALID, + CNAT_ERR_6RD_V4_COMBO_MASK_LEN_INVALID, + CNAT_ERR_6RD_TUNNEL_MTU_INVALID, + CNAT_ERR_6RD_TUNNEL_TTL_INVALID, + CNAT_ERR_6RD_TUNNEL_TOS_INVALID, + CNAT_ERR_NAT64_NO_VRF_RUN, + CNAT_ERR_NAT64_ID_INVALID, + CNAT_ERR_NAT64_V6_PREFIX_INVALID, + CNAT_ERR_NAT64_V4_PREFIX_INVALID, + CNAT_ERR_NAT64_TCP_MSS_INVALID, +#ifdef CGSE_DS_LITE + CNAT_ERR_DS_LITE_ID_INVALID, +#endif /* CGSE_DS_LITE */ + CNAT_ERR_NO_SESSION_DB, + CNAT_ERR_MAPE_ID_INVALID, + CNAT_ERR_MAX +} cnat_errno_t; + +#define CNAT_TRUE 1 +#define CNAT_FALSE 0 + + +#define CNAT_DEBUG_NONE (0) +#define CNAT_DEBUG_GLOBAL_ERR (1 << 0) +#define CNAT_DEBUG_DROP_TCP (1 << 0) +#define CNAT_DEBUG_DROP_UDP (1 << 1) +#define CNAT_DEBUG_DROP_ICMP (1 << 2) +#define CNAT_DEBUG_ERR_TCP (1 << 3) +#define CNAT_DEBUG_ERR_UDP (1 << 4) +#define CNAT_DEBUG_ERR_ICMP (1 << 5) +#define CNAT_DEBUG_ERR_ALG (1 << 6) +#define CNAT_DEBUG_GLOBAL_ALL (1 << 7) +#define CNAT_DEBUG_FTP_ALG (1 << 8) + + + +#define CNAT_DEBUG_ALL 0x1FF /*all of above*/ +#define CNAT_DEBUG_ERR_ALL 0x38 + +#define CNAT_DB_CLEAR_SPECIFIC (0) +#define CNAT_DB_CLEAR_ALL (1 << 0) +#define CNAT_DB_CLEAR_VRF (1 << 1) +#define CNAT_DB_CLEAR_ADDR (1 << 2) +#define CNAT_DB_CLEAR_PROTO (1 << 3) +#define CNAT_DB_CLEAR_PORT (1 << 4) + + +#define MAX_UIDX 0x3fff /*the max svi app uidb index */ +/* address mask per core */ +#define ADDR_MASK_PER_CORE PLATFORM_ADDR_MASK_PER_CORE +#define ADDR_MASK_PER_CORE_PER_PARTITION \ + PLATFORM_ADDR_MASK_PER_CORE_PER_PARTITION + +#define MAX_CORES PLATFORM_MAX_CORES +#define MAX_CORES_PER_PARTITION PLATFORM_MAX_CORES_PER_PARTITION + +/* + * Maximum pool size that is supported by platform + */ +#define CNAT_MAX_ADDR_POOL_SIZE PLATFORM_CNAT_MAX_ADDR_POOL_SIZE +#define CNAT_MAX_ADDR_POOL_SIZE_PER_CORE \ + (CNAT_MAX_ADDR_POOL_SIZE / MAX_CORES_PER_PARTITION) + +#define BOUNDARY_VALUE 256 + +#define BOUNDARY_VALUE_MASK 0xff + +#define NUM_ADDR_IN_RANGE(range, value, instance) \ + ((range / value) + ((instance % MAX_CORES_PER_PARTITION) < (range%value) ? 1 : 0)) + +typedef enum { + CNAT_DEBUG_FLAGS_DUMP = 0, + CNAT_DEBUG_FLAG_UDP_INSIDE_CHECKSUM_DISABLE, + CNAT_DEBUG_FLAG_UDP_OUTSIDE_CHECKSUM_DISABLE, + CNAT_DEBUG_FLAG_UDP_OUTSIDE_PKT_DUMP_ENABLE, + CNAT_DEBUG_FLAG_UDP_INSIDE_PKT_DUMP_ENABLE, + CNAT_DEBUG_FLAG_ICMP_PKT_DUMP_ENABLE, + CNAT_DEBUG_FLAG_FRAG_PKT_DUMP_ENABLE, + CNAT_DEBUG_FLAG_CONFIG_DEBUG_ENABLE, + CNAT_DEBUG_FLAG_GLOBAL_DEBUG_ALL_ENABLE, + CNAT_DEBUG_FLAG_SUMMARY_STATS_DEBUG_ENABLE, + CNAT_DEBUG_FLAG_SHOW_DEBUG_ENABLE, + CNAT_DEBUG_FLAG_XLAT_CONFIG_DEBUG_ENABLE, + CNAT_DEBUG_FLAG_XLAT_DATA_PATH_DEBUG_ENABLE, + CNAT_DEBUG_FLAG_TCP_LOGGING_ENABLE, + CNAT_DEBUG_FLAG_NFV9_LOGGING_DUMP_ENABLE, + CNAT_DEBUG_FLAG_SYSLOG_LOGGING_DUMP_ENABLE, + CNAT_DEBUG_SET_STATIC_PORT_RANGE, + CNAT_DEBUG_FLAG_V6RD_DATA_PATH_DEBUG_ENABLE, + CNAT_DEBUG_FLAG_V6RD_CONFIG_DEBUG_ENABLE, + CNAT_DEBUG_FLAG_V6RD_DEFRAG_DEBUG_ENABLE, + CNAT_DEBUG_FLAG_NAT64_CONFIG_DEBUG_ENABLE, + CNAT_DEBUG_FLAG_NAT64_DATA_PATH_DEBUG_ENABLE, + CNAT_DEBUG_FLAG_DSLITE_DP_ENABLE, + CNAT_DEBUG_FLAG_DSLITE_CONFIG_DEBUG_ENABLE, + CNAT_DEBUG_FLAG_CONFIG_PPTP_ENABLE = 24, + CNAT_DEBUG_FLAG_CONFIG_PCP_ENABLE = 25, + CNAT_DEBUG_FLAG_MAPE_CONFIG_DEBUG_ENABLE, + CNAT_DEBUG_FLAG_MAPE_DATA_PATH_DEBUG_ENABLE, + CNAT_DEBUG_FLAG_MAX, +} cnat_debug_variable_value; + +/* + * Don't use too small values for PATH MTU + */ +#define MIN_NFV9_PATH_MTU 100 + +extern u32 global_debug_flag; +extern u16 debug_i_vrf; +extern u32 debug_i_flag; +extern u32 debug_i_addr_start; +extern u32 debug_i_addr_end; +extern u16 debug_o_vrf; +extern u32 debug_o_flag; +extern u32 debug_o_addr_start; +extern u32 debug_o_addr_end; +extern u32 tcp_logging_enable_flag; +extern u32 nfv9_logging_debug_flag; + +extern u32 udp_inside_checksum_disable; +extern u32 udp_outside_checksum_disable; +extern u32 udp_inside_packet_dump_enable; +extern u32 udp_outside_packet_dump_enable; + +extern u32 icmp_debug_flag; +extern u32 frag_debug_flag; + +extern u32 summary_stats_debug_flag; + +extern u32 config_debug_level; +extern u32 show_debug_level; + + +/* CLI API prototypes called from vcgn_classify.c */ +extern void cnat_nat44_add_vrf_map_t_handler(spp_api_cnat_v4_add_vrf_map_t *mp, + vlib_main_t *vm); +extern void cnat_nat44_handle_show_stats(vlib_main_t *vm); +extern void cnat_nat44_handle_show_config(vlib_main_t *vm); +extern void cnat_nat44_set_protocol_timeout_value(u16 active, + u16 init, u8 *proto, u8 reset, vlib_main_t *vm); +extern void cnat_v4_show_inside_entry_req_t_handler +(spp_api_cnat_v4_show_inside_entry_req_t *mp, vlib_main_t *vm); + +#endif /* __CNAT_CLI_H__ */ diff --git a/plugins/vcgn-plugin/vcgn/cnat_cli_handler.c b/plugins/vcgn-plugin/vcgn/cnat_cli_handler.c new file mode 100644 index 00000000..a4010349 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_cli_handler.c @@ -0,0 +1,961 @@ +/* *------------------------------------------------------------------ + * cnat_cli_handler.c - CLI handler definitions + * + * Copyright (c) 2007-2015 Cisco and/or its affiliates. + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include "cnat_db.h" +#include "cnat_config.h" +#include "cnat_global.h" +#include "cnat_cli.h" +#include "cnat_logging.h" +#include "cnat_syslog.h" +#include "cnat_config_api.h" +#include "cnat_show_api.h" +#include "cnat_show_response.h" + +#include + +#if DPDK +#include +#endif + +u32 show_debug_level = 0; + +u32 +cnat_get_vrfmap_nfv9_logging_index (u32 i_vrf_id) +{ + cnat_nfv9_logging_info_t *my_nfv9_logging_info = 0; + u32 logging_index = EMPTY; + + /* + * Start with global logging index if available + */ + if (cnat_nfv9_global_info.cnat_nfv9_init_done) { + logging_index = cnat_nfv9_global_info.cnat_nfv9_global_collector_index; + + pool_foreach (my_nfv9_logging_info, cnat_nfv9_logging_info_pool, ({ + if (my_nfv9_logging_info->i_vrf_id == i_vrf_id) { + logging_index = my_nfv9_logging_info - + cnat_nfv9_logging_info_pool; + break; + } + })); + } + return (logging_index); +} + +u32 +cnat_get_vrfmap_syslog_logging_index (u32 i_vrf_id) +{ + cnat_syslog_logging_info_t *my_syslog_info = NULL; + u32 logging_index = EMPTY; + + /* + * Start with global logging index if available + */ + if(PREDICT_TRUE(cnat_syslog_global_info.cnat_syslog_init_done)) { + + pool_foreach (my_syslog_info, cnat_syslog_logging_info_pool, ({ + if (my_syslog_info->i_vrf_id == i_vrf_id) { + logging_index = my_syslog_info - + cnat_syslog_logging_info_pool; + break; + } + })); + } + return (logging_index); +} + +void +cnat_set_vrf_params_with_default(cnat_vrfmap_t *my_vrfmap, u32 i_vrf, u32 i_vrf_id) +{ + + my_vrfmap->status = S_WAO; + + my_vrfmap->i_vrf = i_vrf; + my_vrfmap->i_vrf_id = i_vrf_id; + + my_vrfmap->o_vrf = INVALID_UIDX; + my_vrfmap->o_vrf_id = INVALID_VRFID; + +#ifndef NO_BULK_LOGGING + BULKSIZE_FROM_VRFMAP(my_vrfmap) = BULK_ALLOC_SIZE_NONE; +#endif /* #ifndef NO_BULK_LOGGING */ + my_vrfmap->tcp_mss = V4_TCP_MSS_NOT_CONFIGURED_VALUE; + my_vrfmap->frag_tout = CNAT_IPV4_FRAG_TIMEOUT_DEF; + my_vrfmap->port_limit = V4_DEF_VRF_MAX_PORTS; + my_vrfmap->nfv9_logging_index = + cnat_get_vrfmap_nfv9_logging_index(i_vrf_id); + my_vrfmap->syslog_logging_index = + cnat_get_vrfmap_syslog_logging_index(i_vrf_id); + + /* Copy logging policy from nfv9 info. */ + if(my_vrfmap->nfv9_logging_index != EMPTY) { + cnat_nfv9_logging_info_t *nfv9_logging_info = + cnat_nfv9_logging_info_pool + my_vrfmap->nfv9_logging_index; + my_vrfmap->nf_logging_policy = nfv9_logging_info->logging_policy; + } + if(my_vrfmap->syslog_logging_index != EMPTY) { + cnat_syslog_logging_info_t *syslog_logging_info = + cnat_syslog_logging_info_pool + my_vrfmap->syslog_logging_index; + my_vrfmap->syslog_logging_policy = syslog_logging_info->logging_policy; + } + #if 0 + printf("Initializing params in cnat_set_vrf_params_with_default\n" + "my_vrfmap->status = %u\n" + "my_vrfmap->tcp_mss = %u\n" + "my_vrfmap->i_vrf = %u\n" + "my_vrfmap->i_vrf_id = %u\n" + "my_vrfmap->o_vrf = %u\n" + "my_vrfmap->o_vrf_id = %u\n" + "my_vrfmap->bulk_size = %u\n" + "my_vrfmap->nfv9_logging_index = %u\n" + "my_vrfmap->syslog_logging_index = %u\n" + "my_vrfmap->frag_tout = %u\n" + "my_vrfmap->port_limit = %u\n" + "my_vrfmap->nf_logging_policy = %u\n" + "my_vrfmap->syslog_logging_policy = %u\n", + my_vrfmap->status, + my_vrfmap->tcp_mss, + my_vrfmap->i_vrf, + my_vrfmap->i_vrf_id, + my_vrfmap->o_vrf, + my_vrfmap->o_vrf_id, + my_vrfmap->bulk_size, + my_vrfmap->nfv9_logging_index, + my_vrfmap->syslog_logging_index, + my_vrfmap->frag_tout, + my_vrfmap->port_limit, + my_vrfmap->nf_logging_policy, + my_vrfmap->syslog_logging_policy); + #endif /* if 0 */ +} + +/* config command handlers */ +void cnat_nat44_add_vrf_map_t_handler(spp_api_cnat_v4_add_vrf_map_t *mp, + vlib_main_t *vm) +{ + void cnat_table_entry_fill_map(u32 start_addr, u32 end_addr, + cnat_portmap_v2_t **port_map_holder); + u32 start_addr, end_addr; + u32 pm_len __attribute__((unused)); + cnat_vrfmap_t *my_vrfmap = 0; + cnat_portmap_v2_t *pm = 0; + u16 i_vrf, o_vrf; + u32 ivrf_id, ovrf_id; + u16 my_vrfmap_index; + u8 i = 0; + + start_addr = mp->start_addr[0]; + end_addr = mp->end_addr[0]; + i_vrf = mp->i_vrf; + o_vrf = mp->o_vrf; + ovrf_id = mp->o_vrf_id; + ivrf_id = mp->i_vrf_id; + +#if DEBUG_NOT_COMMENTED + vlib_cli_output(vm, "%s: saddr[0x%x], eaddr[0x%x], i_vrf[0x%x], o_vrf[0x%x], " + "ovrf_id[0x%x], ivrf_id[0x%x]\n", __func__, start_addr, end_addr, + i_vrf, o_vrf, ovrf_id, ivrf_id); +#endif + if (start_addr > end_addr) { + vlib_cli_output(vm, "Add VRF Map failed start addr 0x%x > end addr 0x%x\n", + start_addr, end_addr); + return; + } + if ((end_addr - start_addr) > CNAT_MAX_ADDR_POOL_SIZE) { + vlib_cli_output(vm, "Add VRF Map failed start addr 0x%x - end addr " + "0x%x range > 65536\n", start_addr, end_addr); + return; + } + my_vrfmap_index = vrf_map_array[i_vrf]; + + if (my_vrfmap_index != VRF_MAP_ENTRY_EMPTY) { + + my_vrfmap = cnat_map_by_vrf + my_vrfmap_index; + + my_vrfmap->o_vrf = o_vrf; + my_vrfmap->i_vrf_id = ivrf_id; + my_vrfmap->o_vrf_id = ovrf_id; + } else { + /* + * first time add + */ + pool_get(cnat_map_by_vrf, my_vrfmap); + memset(my_vrfmap, 0, sizeof(*my_vrfmap)); + /* waiting for outside vrf */ + cnat_set_vrf_params_with_default(my_vrfmap, i_vrf, ivrf_id); + my_vrfmap->i_vrf = i_vrf; + my_vrfmap->o_vrf = o_vrf; + my_vrfmap->i_vrf_id = ivrf_id; + my_vrfmap->o_vrf_id = ovrf_id; +#ifndef NO_BULK_LOGGING + BULKSIZE_FROM_VRFMAP(my_vrfmap) = BULK_ALLOC_SIZE_NONE; +#endif /* #ifndef NO_BULK_LOGGING */ + + my_vrfmap->tcp_mss = V4_TCP_MSS_NOT_CONFIGURED_VALUE; + my_vrfmap->status = S_WA; + my_vrfmap->frag_tout = 0; /* currently setting it to 0 */ + my_vrfmap->port_limit = V4_DEF_VRF_MAX_PORTS; + vrf_map_array[i_vrf] = (my_vrfmap - cnat_map_by_vrf); + } + pm = my_vrfmap->portmap_list; + pm_len = vec_len(pm); + for(i=0; i < 1 ; i++) { + start_addr = mp->start_addr[i]; + end_addr = mp->end_addr[i]; + if((start_addr == 0) || (end_addr == 0)) + break; + + cnat_table_entry_fill_map(start_addr, end_addr, + &(my_vrfmap->portmap_list)); + } + my_vrfmap->status = S_RUN; + vlib_cli_output(vm, "Address Pool Config Successful !!\n"); + return; +} + +void cnat_nat44_set_protocol_timeout_value(u16 active, + u16 init, u8 *proto, u8 reset, vlib_main_t *vm) +{ + if (!strncmp((char *) proto, "tcp", 3)) { + tcp_initial_setup_timeout = (reset) ? V4_DEF_TCP_IS_TO : init; + tcp_active_timeout = (reset) ? V4_DEF_TCP_AS_TO : active; + + } else if (!strncmp((char *) proto, "udp", 3)) { + udp_init_session_timeout = (reset) ? V4_DEF_UDP_IS_TO : init; + udp_act_session_timeout = (reset) ? V4_DEF_UDP_AS_TO : active; + + } else if (!strncmp((char *) proto, "icmp", 4)) { + icmp_session_timeout = (reset) ? V4_DEF_ICMP_S_TO : active; + + } else { + vlib_cli_output(vm, "Error !! Unsupported protocol %s\n", proto); + } + return; +} + + + + +/* Show command handlers */ +void cnat_nat44_handle_show_stats(vlib_main_t *vm) +{ + pool_header_t *h; + u32 used, free; + cnat_vrfmap_t *my_vrfmap =0; + cnat_portmap_v2_t *pm =0, *my_pm = 0; + u32 i, pm_len; + struct in_addr ip; + void cnat_nfv9_show_collector + (vlib_main_t *vm, cnat_nfv9_logging_info_t *my_nfv9_logging_info); + + /* active translations */ + h = pool_header(cnat_main_db); + free = vec_len(h->free_indices); + used = vec_len(cnat_main_db) - free; + + vlib_cli_output(vm, "vCGN NAT44 Statistics :\n"); + vlib_cli_output(vm, "\tActive Translations : %u\n", + NAT44_COMMON_STATS.active_translations); + vlib_cli_output(vm, "\tTotal free translation entries : %u\n", free); + vlib_cli_output(vm, "\tTotal used translation entries : %u\n", used); + vlib_cli_output(vm, "\ti2o drops due to port limit exceeded : %lu\n", + in2out_drops_port_limit_exceeded); + vlib_cli_output(vm, "\ti2o drops due to system limit reached : %lu\n", + in2out_drops_system_limit_reached); + vlib_cli_output(vm, "\ti2o drops due to resource depletion : %lu\n", + in2out_drops_resource_depletion); + vlib_cli_output(vm, "\to2i drops due to no translations : %lu\n", + NAT44_COMMON_STATS.no_translation_entry_drops); + + vlib_cli_output(vm, "\tPool address usage:\n"); + vlib_cli_output(vm, "\t-------------------------------------------------\n"); + vlib_cli_output(vm, "\tExternal Address \tPorts Used\n"); + vlib_cli_output(vm, "\t-------------------------------------------------\n"); + + used = 0; + pool_foreach (my_vrfmap, cnat_map_by_vrf, ({ + pm = my_vrfmap->portmap_list; + pm_len = vec_len(pm); + for (i = 0; i < pm_len; i++) { + my_pm = pm + i; + if (my_pm->inuse) { + used++; + /* maximum of 200 addresses to be returned */ + if (used <= 200) { + ip.s_addr = ntohl(my_pm->ipv4_address); + vlib_cli_output(vm, "\t%s \t\t%u\n", inet_ntoa(ip), my_pm->inuse); + } + } + } + })); + return; +} + +void cnat_nat44_handle_show_config(vlib_main_t *vm) +{ + cnat_vrfmap_t * my_vrfmap; + cnat_portmap_v2_t *pm = 0; + cnat_portmap_v2_t *my_pm = 0; + u32 pm_len; + struct in_addr ip_addr; + u8 status_str[20]; + cnat_nfv9_logging_info_t *my_nfv9_logging_info, + *global_nfv9_logging_info = 0; + + vnet_hw_interface_t * hw; + vnet_main_t * vnm = vnet_get_main(); + + void cnat_nfv9_show_collector + (vlib_main_t *vm, cnat_nfv9_logging_info_t *my_nfv9_logging_info); + + vlib_cli_output(vm, "vCGN NAT44 Config:\n"); + vlib_cli_output(vm, "\tPort Limit : %u\n", cnat_main_db_max_ports_per_user); + vlib_cli_output(vm, "\ttotal address pool : %u\n", total_address_pool_allocated); + vlib_cli_output(vm, "\tdynamic port start range : %u\n", cnat_static_port_range); + + pool_foreach(my_vrfmap, cnat_map_by_vrf, ({ + hw = vnet_get_hw_interface (vnm, my_vrfmap->i_vrf); + vlib_cli_output(vm, "\tInside Interface : %v\n", hw->name); + hw = vnet_get_hw_interface (vnm, my_vrfmap->o_vrf); + vlib_cli_output(vm, "\tOutside Interface : %v\n", hw->name); + + memset(status_str, 0x00, sizeof(status_str)); + switch(my_vrfmap->status) { + case S_WAO: clib_memcpy(status_str, "S_WAO", 5); break; + case S_WA: clib_memcpy(status_str, "S_WA", 4); break; + case S_WO: clib_memcpy(status_str, "S_WO", 4); break; + case S_RUN: clib_memcpy(status_str, "ONLINE", 6); break; + case S_DEL: clib_memcpy(status_str, "S_DEL", 5); break; + default: clib_memcpy(status_str, "Invalid state", 13); + + } + vlib_cli_output(vm, + "\tAddress pool map table status : %s\n", status_str); + + pm = my_vrfmap->portmap_list; + pm_len = vec_len(pm); + my_pm = pm; + ip_addr.s_addr = clib_net_to_host_u32(my_pm->ipv4_address); + vlib_cli_output(vm, + "\tStart Address : %s\n", inet_ntoa(ip_addr)); + my_pm = pm + (pm_len - 1); + ip_addr.s_addr = clib_net_to_host_u32(my_pm->ipv4_address); + vlib_cli_output(vm, + "\tEnd Address : %s\n", inet_ntoa(ip_addr)); + + })); + vlib_cli_output(vm, + "\ttcp init timeout : %u sec\n", tcp_initial_setup_timeout); + vlib_cli_output(vm, + "\ttcp active timeout : %u sec\n", tcp_active_timeout); + vlib_cli_output(vm, + "\tudp init timeout : %u sec\n", udp_init_session_timeout); + vlib_cli_output(vm, + "\tudp active timeout : %u sec\n", udp_act_session_timeout); + vlib_cli_output(vm, + "\ticmp session timeout: %u sec\n", icmp_session_timeout); + +#if 0 + if (cnat_nfv9_global_info.cnat_nfv9_global_collector_index != EMPTY) { + vlib_cli_output(vm,"\nGloabal NFV9 Collector :"); + global_nfv9_logging_info = cnat_nfv9_logging_info_pool + + cnat_nfv9_global_info.cnat_nfv9_global_collector_index; + cnat_nfv9_show_collector(vm, global_nfv9_logging_info); + } +#endif + + vlib_cli_output(vm, "\nNFV9 Collector :"); + if (cnat_nfv9_logging_info_pool !=NULL) { + pool_foreach (my_nfv9_logging_info, cnat_nfv9_logging_info_pool, ({ + if (my_nfv9_logging_info != global_nfv9_logging_info) { + cnat_nfv9_show_collector(vm, my_nfv9_logging_info); + vlib_cli_output(vm, "\n"); + } + })); + } else { + vlib_cli_output(vm, "\n"); + } + + return; +} + +/* + * Check if the request flag matches the entry flags and + * if so return "1" + * + * entry_flag_ptr is an output parameter - it returns the flags + * corresponding to the translation entry + */ +static u8 cnat_v4_show_verify_display_entry ( + u16 request_flag, + cnat_main_db_entry_t *db, + u16 *entry_flag_ptr) +{ + u8 display_entry = 0; + + /* + * This should never happen + */ + if (!entry_flag_ptr) { + return (display_entry); + } + + *entry_flag_ptr = 0; + + if ((db->flags & CNAT_DB_FLAG_STATIC_PORT) + &&(db->flags & CNAT_DB_FLAG_ALG_ENTRY)) { + *entry_flag_ptr |= CNAT_TRANSLATION_ENTRY_STATIC; + *entry_flag_ptr |= CNAT_TRANSLATION_ENTRY_ALG; + } else if (db->flags & CNAT_DB_FLAG_STATIC_PORT) { + *entry_flag_ptr |= CNAT_TRANSLATION_ENTRY_STATIC; + } else if ((db->flags & CNAT_DB_FLAG_ALG_ENTRY) || + (db->flags & CNAT_DB_FLAG_PPTP_GRE_ENTRY)) { + *entry_flag_ptr |= CNAT_TRANSLATION_ENTRY_ALG; + } else if (db->flags & CNAT_DB_FLAG_PCPI) { + *entry_flag_ptr |= CNAT_TRANSLATION_ENTRY_PCPI_DYNAMIC; + } else if (db->flags & CNAT_DB_FLAG_PCPE) { + *entry_flag_ptr |= CNAT_TRANSLATION_ENTRY_PCPE_DYNAMIC; + } else { + *entry_flag_ptr |= CNAT_TRANSLATION_ENTRY_DYNAMIC; + } + + if (request_flag == CNAT_TRANSLATION_ENTRY_ALL) { + display_entry = 1; + } else { + /* + * Check if the request_flag is STATIC or ALG + * and the entry is STATIC or ALG as well + */ + if ((request_flag & CNAT_TRANSLATION_ENTRY_STATIC) && + (*entry_flag_ptr & CNAT_TRANSLATION_ENTRY_STATIC)) { + display_entry = 1; + } + + if ((request_flag & CNAT_TRANSLATION_ENTRY_ALG) && + (*entry_flag_ptr & CNAT_TRANSLATION_ENTRY_ALG)) { + display_entry = 1; + } + + if ((request_flag & CNAT_TRANSLATION_ENTRY_PCPI_DYNAMIC) && + (*entry_flag_ptr & CNAT_TRANSLATION_ENTRY_PCPI_DYNAMIC)) { + display_entry = 1; + } + + if ((request_flag & CNAT_TRANSLATION_ENTRY_PCPE_DYNAMIC) && + (*entry_flag_ptr & CNAT_TRANSLATION_ENTRY_PCPE_DYNAMIC)) { + display_entry = 1; + } + + /* + * For dynamic entry case, check if flags field is 0 + */ + if ((request_flag & CNAT_TRANSLATION_ENTRY_DYNAMIC) && + (*entry_flag_ptr & CNAT_TRANSLATION_ENTRY_DYNAMIC)) { + display_entry = 1; + } + } + + if (PREDICT_FALSE(show_debug_level > 2)) { + PLATFORM_DEBUG_PRINT("Entry (0x%x, %d) -> (0x%x, %d) request_flag 0x%x, entry_flag 0x%x, display_entry %d\n", db->in2out_key.k.ipv4, db->in2out_key.k.port, db->out2in_key.k.ipv4, db->out2in_key.k.port, request_flag, *entry_flag_ptr, display_entry); + } + + return (display_entry); +} +void cnat_v4_show_inside_entry_req_t_handler +(spp_api_cnat_v4_show_inside_entry_req_t *mp, vlib_main_t * vm) +{ + cnat_user_db_entry_t *udb = NULL; + cnat_main_db_entry_t *db = NULL; + cnat_db_key_bucket_t u_ki, ki; + u64 a, b, c; + u32 index; + u16 start_port, end_port, port; + u16 request_flag = 0; + u16 entry_flag = 0; + u8 num_entries = 0; + u8 proto, all; + u8 done = 0; + cnat_v4_show_translation_entry *entry_list; + cnat_v4_show_translation_entry entry[PLATFORM_MAX_TRANSLATION_ENTRIES]; + u8 display_entry; + u8 flag_str[11]; + vnet_hw_interface_t * hw; + vnet_main_t * vnm = vnet_get_main(); + + ki.k.k.ipv4 = mp->ipv4_addr; + ki.k.k.vrf = mp->vrf_id; + start_port = mp->start_port; + end_port = mp->end_port; +#if DEBUG + vlib_cli_output(vm, "## proto %d, inside-addr 0x%x, start_port %u, " + "end_port %u, vrf 0x%x, flag 0x%x\n", + mp->protocol, + mp->ipv4_addr, + mp->start_port, + mp->end_port, + mp->vrf_id, + mp->flags); +#endif + + proto = mp->protocol; + ki.k.k.vrf |= ((u16)proto << CNAT_PRO_SHIFT); + + all = mp->all_entries; /* for no port range case */ + request_flag = mp->flags; /* for all, alg, static entries case */ + entry_list = entry; + + /* + * check if the address is belonging to this core + */ + + + /* + * first we check if the user exists in the udb, if he is not then + * it does not make sense to check the main db for translations + */ + u_ki.k.k.vrf = ki.k.k.vrf & CNAT_VRF_MASK; + u_ki.k.k.ipv4 = ki.k.k.ipv4; + u_ki.k.k.port = 0; + + if (PREDICT_FALSE(show_debug_level > 0)) { + vlib_cli_output(vm, "\nI_TRANS_CORE %d: IPv4 0x%x, VRF 0x%x, " + "start_port %d, end_port %d", + my_instance_number, ki.k.k.ipv4, + ki.k.k.vrf, start_port, end_port); + } + + udb = cnat_user_db_lookup_entry(&u_ki); + if (!udb) { + if (PREDICT_FALSE(show_debug_level > 0)) { + vlib_cli_output(vm, "\nReturning %d entries", + num_entries); + } + return; + } + + if (all) { + #if 0 + if (PREDICT_FALSE(show_debug_level > 0)) { + PLATFORM_DEBUG_PRINT("\nI_TRANS: Printing ALL\n"); + } + + /* + * get the head of list of translation entries for that user + * from the user db + */ + head = udb->translation_list_head_index; + db = cnat_main_db + head; + + while (num_entries < PLATFORM_MAX_TRANSLATION_ENTRIES) { + + if (((db->in2out_key.k.vrf & CNAT_PRO_MASK) >> CNAT_PRO_SHIFT) + != proto) { + goto next_entry; + } + + display_entry = + spp_api_cnat_v4_show_verify_display_entry(request_flag, db, + &entry_flag); + + if (display_entry) { + entry_list->ipv4_addr = + spp_host_to_net_byte_order_32(db->out2in_key.k.ipv4); + entry_list->cnat_port = + spp_host_to_net_byte_order_16(db->out2in_key.k.port); + entry_list->src_port = + spp_host_to_net_byte_order_16(db->in2out_key.k.port); + + entry_list->protocol = proto; + + /* incase of gre - in2out is not accounted */ + if(proto != CNAT_PPTP) { + + entry_list->in2out_packets = + spp_host_to_net_byte_order_32(db->in2out_pkts); + } else { + entry_list->in2out_packets = 0; + } + entry_list->out2in_packets = + spp_host_to_net_byte_order_32(db->out2in_pkts); + + entry_list->flags = + spp_host_to_net_byte_order_16(entry_flag); + + num_entries++; + entry_list = entry_list + 1; + } +next_entry: + db = cnat_main_db + db->user_ports.next; + /* + * its a circular list, so if we have reached the head again + * all the entries for that user have been read + */ + if (db == (cnat_main_db + head)) { + break; + } + } + resp->num_entries = num_entries; + #endif /* if 0 */ + } else { + if (PREDICT_FALSE(show_debug_level > 0)) { + vlib_cli_output(vm, "\nI_TRANS: Printing range %d .. %d\n", + start_port, end_port); + } + /* + * port range is specified so for each port calculate the hash and + * check if the entry is present in main db + */ + port = start_port; + done = 0; + while ((!done) && (num_entries < PLATFORM_MAX_TRANSLATION_ENTRIES)) { + + ki.k.k.port = port; + if (port >= end_port) { + done = 1; + } else { + port++; + } + CNAT_V4_GET_HASH(ki.k.key64, + ki.bucket, + CNAT_MAIN_HASH_MASK); + index = cnat_in2out_hash[ki.bucket].next; + if (PREDICT_TRUE(index == EMPTY)) { + continue; + } + + do { + db = cnat_main_db + index; + if (db->in2out_key.key64 == ki.k.key64) { + break; + } + index = db->in2out_hash.next; + } while (index != EMPTY); + + if (index == EMPTY) { + continue; + } else { + + display_entry = + cnat_v4_show_verify_display_entry(request_flag, db, + &entry_flag); + if (display_entry) { + + entry_list->ipv4_addr = + clib_host_to_net_u32(db->out2in_key.k.ipv4); + entry_list->cnat_port = + clib_host_to_net_u16(db->out2in_key.k.port); + entry_list->src_port = + clib_host_to_net_u16(db->in2out_key.k.port); + + entry_list->protocol = proto; + entry_list->nsessions = db->nsessions; + entry_list->flags = ((db->flags & CNAT_DB_FLAG_TCP_ACTIVE) || + (db->flags & CNAT_DB_FLAG_UDP_ACTIVE)) ? 1:0; + /* incase of gre - in2out is not accounted */ + if(proto != CNAT_PPTP) { + entry_list->in2out_packets = + clib_host_to_net_u32(db->in2out_pkts); + } else { + entry_list->in2out_packets = 0; + } + + entry_list->out2in_packets = + clib_host_to_net_u32(db->out2in_pkts); + + if (PREDICT_FALSE(show_debug_level > 3)) { + vlib_cli_output(vm, "\n1. Entry: Addr 0x%x, port %d, num_entries %d", + clib_net_to_host_u32(entry_list->ipv4_addr), + clib_net_to_host_u16(entry_list->cnat_port), + num_entries); + } + + entry_list = entry_list + 1; + num_entries++; + } + } /* if (index == EMPTY) */ + } /* while() */ + } + + if (PREDICT_FALSE(show_debug_level > 0)) { + if (num_entries) { + vlib_cli_output(vm, "\nReturning %d entries\n", + num_entries); + } + } + + entry_list = entry; + u8 i = 0; + struct in_addr ip; + u8 proto_str[10]; + u8 transl_str[10]; + memset(proto_str, 0x00, 10); + memset(transl_str, 0x00, 10); + + if (proto == 1) strncpy((char *)proto_str, "udp", 3); + else if (proto == 2) strncpy((char *)proto_str, "tcp", 3); + else if (proto == 3) strncpy((char *)proto_str, "icmp", 4); + else strncpy((char *)proto_str, "unknown", 7); + + if (request_flag == 0x04) strncpy((char *)transl_str, "Dynamic", 7); + else strncpy((char *)transl_str, "Unknown", 7); /* currently we are not supporting static/alg entries */ + + ip.s_addr = clib_net_to_host_u32(u_ki.k.k.ipv4); + hw = vnet_get_hw_interface (vnm, u_ki.k.k.vrf); + + vlib_cli_output (vm, "Inside-translation details\n"); + vlib_cli_output (vm, "--------------------------\n"); + + vlib_cli_output (vm, "Inside interface : %s\n", hw->name); + vlib_cli_output (vm, "Inside address : %s\n", inet_ntoa(ip)); + vlib_cli_output (vm, "Start port : %u\n", start_port); + vlib_cli_output (vm, "End port : %u\n", end_port); + + vlib_cli_output (vm, "--------------------------------------------------------------------------------------" + "-----------------------\n"); + vlib_cli_output (vm, "Outside Protocol Inside Outside Translation" + " I2O O2I Flag Num\n"); + vlib_cli_output (vm, "Address Src Port Src Port Type " + " Pkts Pkts Sessions\n"); + vlib_cli_output (vm, "--------------------------------------------------------------------------------------" + "-----------------------\n"); + + while ((num_entries) && (entry_list) && (i < 50)) { + + ip.s_addr = entry_list->ipv4_addr; + memset(flag_str,0x00,11); + if((proto == 1) || (proto == 2)) { + if(entry_list->flags == 1) { + strncpy((char *)flag_str,"Active",6); + } + else { + strncpy((char *) flag_str,"Non Active",10); + } + } else { + strncpy((char *) flag_str, "NA", 2); + } + vlib_cli_output(vm, "%s %10s %11u %12u %13s %10u %10u %14s %6u\n", + inet_ntoa(ip), proto_str, + clib_net_to_host_u16(entry_list->src_port), + clib_net_to_host_u16(entry_list->cnat_port), + transl_str, + clib_net_to_host_u32(entry_list->in2out_packets), + clib_net_to_host_u32(entry_list->out2in_packets), + flag_str, + entry_list->nsessions); + entry_list++; + num_entries--; i++; + } + + return; +} + +void cnat_v4_show_outside_entry_req_t_handler +(spp_api_cnat_v4_show_outside_entry_req_t *mp, vlib_main_t *vm) +{ + cnat_main_db_entry_t *db = NULL; + cnat_db_key_bucket_t ko; + u64 a, b, c; + u32 index; + u16 start_port, end_port, port; + u16 request_flag = 0; + u16 entry_flag = 0; + u8 num_entries = 0; + u8 proto; + cnat_v4_show_translation_entry *entry_list; + cnat_v4_show_translation_entry entry[PLATFORM_MAX_TRANSLATION_ENTRIES]; + u8 done = 0; + u8 display_entry; + u8 flag_str[11]; + vnet_hw_interface_t * hw; + vnet_main_t * vnm = vnet_get_main(); + + ko.k.k.ipv4 = mp->ipv4_addr; + ko.k.k.vrf = mp->vrf_id; + start_port = mp->start_port; + end_port = mp->end_port; + + proto = mp->protocol; + request_flag = mp->flags; + + ko.k.k.vrf |= ((u16)proto << CNAT_PRO_SHIFT); + + entry_list = entry; + + if (PREDICT_FALSE(show_debug_level > 0)) { + vlib_cli_output(vm, "\nO_TRANS_CORE %d: IPv4 0x%x, VRF 0x%x, " + "start_port %d, end_port %d", my_instance_number, + ko.k.k.ipv4, ko.k.k.vrf, start_port, end_port); + } + + /* + * for each ip and port combination we need to scan the main db + * and check if the entry is present in main db + */ + port = start_port; + done = 0; + while ((!done) && (num_entries < PLATFORM_MAX_TRANSLATION_ENTRIES)) { + ko.k.k.port = port; + + /* + * If we have reached the end_port, we are DONE + */ + if (port >= end_port) { + done = 1; + } else { + port++; + } + + CNAT_V4_GET_HASH(ko.k.key64, + ko.bucket, + CNAT_MAIN_HASH_MASK); + + index = cnat_out2in_hash[ko.bucket].next; + if (PREDICT_TRUE(index == EMPTY)) { + continue; + } + + do { + db = cnat_main_db + index; + if (db->out2in_key.key64 == ko.k.key64) { + break; + } + index = db->out2in_hash.next; + } while (index != EMPTY); + + if (index == EMPTY) { + continue; + } else { + display_entry = + cnat_v4_show_verify_display_entry(request_flag, db, + &entry_flag); + + if (display_entry) { + entry_list->ipv4_addr = + clib_host_to_net_u32(db->in2out_key.k.ipv4); + entry_list->cnat_port = + clib_host_to_net_u16(db->out2in_key.k.port); + entry_list->src_port = + clib_host_to_net_u16(db->in2out_key.k.port); + entry_list->protocol = proto; + entry_list->nsessions = db->nsessions; + entry_list->flags = ((db->flags & CNAT_DB_FLAG_TCP_ACTIVE) || + (db->flags & CNAT_DB_FLAG_UDP_ACTIVE)) ? 1:0; + /* incase of gre - in2out is not accounted */ + if(proto != CNAT_PPTP) { + entry_list->in2out_packets = + clib_host_to_net_u32(db->in2out_pkts); + } else { + entry_list->in2out_packets = 0 ; + } + entry_list->out2in_packets = + clib_host_to_net_u32(db->out2in_pkts); + #if 0 + entry_list->flags = + clib_host_to_net_u16(entry_flag); + #endif + entry_list = entry_list + 1; + num_entries++; + } + } + } + + if (num_entries == 0) { + /* No point proceeding further */ + return; + } + + if (PREDICT_FALSE(show_debug_level > 0)) { + if (num_entries) { + vlib_cli_output(vm, "\nO_TRANS: Core %d returning %d entries", + num_entries); + } + } + + entry_list = entry; + u8 i = 0; + struct in_addr ip; + u8 proto_str[10]; + u8 transl_str[10]; + memset(proto_str, 0x00, 10); + memset(transl_str, 0x00, 10); + + if (proto == 1) strncpy((char *) proto_str, "udp", 3); + else if (proto == 2) strncpy((char *) proto_str, "tcp", 3); + else if (proto == 3) strncpy((char *) proto_str, "icmp", 4); + else strncpy((char *) proto_str, "unknown", 7); + + if (request_flag == 0x04) strncpy((char *) transl_str, "Dynamic", 7); + else strncpy((char *)transl_str, "Unknown", 7); /* currently we are not supporting static/alg entries */ + + ip.s_addr = clib_net_to_host_u32(ko.k.k.ipv4); + hw = vnet_get_hw_interface (vnm, (ko.k.k.vrf & CNAT_VRF_MASK)); + + vlib_cli_output (vm, "Outside-translation details\n"); + vlib_cli_output (vm, "--------------------------\n"); + + vlib_cli_output (vm, "Outside interface : %s\n", hw->name); + vlib_cli_output (vm, "Outside address : %s\n", inet_ntoa(ip)); + vlib_cli_output (vm, "Start port : %u\n", start_port); + vlib_cli_output (vm, "End port : %u\n", end_port); + + vlib_cli_output (vm, "--------------------------------------------------------------------------------------" + "-----------------------\n"); + vlib_cli_output (vm, "Inside Protocol Outside Inside Translation" + " I2O O2I Flag Num\n"); + vlib_cli_output (vm, "Address Dst Port Dst Port Type " + " Pkts Pkts Sessions\n"); + vlib_cli_output (vm, "--------------------------------------------------------------------------------------" + "-----------------------\n"); + + while ((num_entries) && (entry_list) && (i < 50)) { + ip.s_addr = entry_list->ipv4_addr; + memset(flag_str,0x00,11); + if((proto == 1) || (proto == 2)) { + if(entry_list->flags == 1) { + strncpy((char *) flag_str,"Active",6); + } + else { + strncpy((char *) flag_str,"Non Active",10); + } + } else { + strncpy((char *) flag_str, "NA", 2); + } + vlib_cli_output(vm, "%s %10s %11u %12u %13s %10u %10u %14s %6u\n", + inet_ntoa(ip), proto_str, + clib_net_to_host_u16(entry_list->cnat_port), + clib_net_to_host_u16(entry_list->src_port), + transl_str, + clib_net_to_host_u32(entry_list->in2out_packets), + clib_net_to_host_u32(entry_list->out2in_packets), + flag_str, + entry_list->nsessions); + entry_list++; + num_entries--; i++; + + } + return; +} diff --git a/plugins/vcgn-plugin/vcgn/cnat_common_api.h b/plugins/vcgn-plugin/vcgn/cnat_common_api.h new file mode 100644 index 00000000..a4eb7443 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_common_api.h @@ -0,0 +1,22 @@ +/*--------------------------------------------------------------------------- + * Copyright (c) 2009-2014 Cisco and/or its affiliates. + * 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 __CNAT_COMMON_API_H__ +#define __CNAT_COMMON_API_H__ + +/* All common API prototypes */ +void cnat_scanner_db_process_turn_on(vlib_main_t *vm); + +#endif diff --git a/plugins/vcgn-plugin/vcgn/cnat_config.c b/plugins/vcgn-plugin/vcgn/cnat_config.c new file mode 100644 index 00000000..87183dfa --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_config.c @@ -0,0 +1,77 @@ +/* + *------------------------------------------------------------------ + * cnat_config.c - configuration definitions + * + * Copyright (c) 2007-2012 Cisco and/or its affiliates. + * 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 "cnat_config.h" +#include "cnat_cli.h" +#include "cnat_v4_pptp_alg.h" +#include "platform_common.h" + +/* session timeout */ + +u16 tcp_initial_setup_timeout = V4_DEF_TCP_IS_TO; /* sec */ +u16 tcp_active_timeout = V4_DEF_TCP_AS_TO; /* sec */ +u16 udp_init_session_timeout = V4_DEF_UDP_IS_TO; /* 30 sec */ +u16 udp_act_session_timeout = V4_DEF_UDP_AS_TO; /* 2 min */ +u16 icmp_session_timeout = V4_DEF_ICMP_S_TO; /* 60 sec */ + +cnat_pptp_config_t pptp_cfg = + { + .enable = PPTP_DISABLED, + .timeout = PPTP_GRE_TIMEOUT + } ; + +/* This flag is used as indication of timeout related config + * changes and hence db needs to be updated + */ +u8 timeout_dirty_flag = 0; + +/* mapping refresh direction, + * 1 inbound and outbound refresh + */ +u8 mapping_refresh_both_direction = V4_DEF_ENABLE; + +u16 cnat_main_db_max_ports_per_user = V4_DEF_MAX_PORTS; + +u32 cnat_main_db_icmp_rate_limit = DEF_RATE_LIMIT; +u32 cnat_main_db_icmp_rate_limit_core = DEF_RATE_LIMIT_CORE; +u32 crc_zero_udp_rate_limit_core = RATE_LIMIT_UDP_CORE; +u16 cnat_static_port_range = CNAT_DEF_STATIC_PORT_RANGE; + + +/* + * ftp alg enable + */ +u8 ftp_alg_enabled = V4_DEF_DISABLE; +u16 rtsp_alg_port_num = 0; + +/* + * load balancing debug mode + */ +u8 lb_debug_enable = V4_DEF_DISABLE; + + +/* good or evil mode + * 0 endpoint-independnet filter, good mode + * 1 address depedent filter, evil mode + */ +u8 address_dependent_filtering = V4_DEF_DISABLE; + +u16 per_user_icmp_msg_limit = ICMP_MSG_RATE_LIMIT; + +u16 config_delete_timeout = V4_CONFIG_DELETE_TO; + diff --git a/plugins/vcgn-plugin/vcgn/cnat_config.h b/plugins/vcgn-plugin/vcgn/cnat_config.h new file mode 100644 index 00000000..f1042737 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_config.h @@ -0,0 +1,582 @@ +/* + *------------------------------------------------------------------ + * cnat_config.h - configuration database definitions + * + * Copyright (c) 2007-2013 Cisco and/or its affiliates. + * 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 __CNAT_CONFIG_H__ +#define __CNAT_CONFIG_H__ + +#include +#include + +#include "cnat_bulk_port_defs.h" + +/* default policy value */ +#define V4_DEF_ICMP_S_TO 60 /*icmp session timeout */ +#define V4_DEF_UDP_IS_TO 30 /*udp init session timeout */ +#define V4_DEF_UDP_AS_TO 120 /*udp active session timeout */ +#define V4_DEF_TCP_IS_TO 120 /*tcp init session timeout */ +#define V4_DEF_TCP_AS_TO 1800 /*tcp active session timeout, 30 min */ +#define V4_DEF_TCP_MSS 1460 /*tcp mss */ +#define V4_DEF_MAX_PORTS 100 /*max port limit per user */ +#define DEF_RATE_LIMIT PLATFORM_MAX_CORES /* No of packets/sec icmp generated */ +#define DEF_RATE_LIMIT_CORE 1 /* No of packets/sec icmp generated (per core) */ +#define RATE_LIMIT_UDP_CORE 1000 /* Max allowed udp crc zero packets/sec/core */ + +#define NAT44_RESERVED_INST_ID 1 +#define DSLITE_START_ID (NAT44_RESERVED_INST_ID + 1) +#define V4_DEF_VRF_MAX_PORTS 0 /*max port limit per vrf user; + 0 means use the global port limit for user*/ +/*Hardcoded . TBD - can be made configurable */ + +#define V4_DEF_ENABLE 1 /* feature enable */ +#define V4_DEF_DISABLE 0 /* feature disable */ + +#define CNAT_DEF_STATIC_PORT_RANGE 1024 /* Default range for static ports */ +/* + * If TCP MSS is not configured, store the maximum possible value + */ +#define V4_TCP_MSS_NOT_CONFIGURED_VALUE 0xffff + +/* default timeout for fragments in seconds set to 2 + * in case its not configured + */ +#define CNAT_IPV4_FRAG_TIMEOUT_DEF 2 +/* other */ +/* max db entries to be scaned */ +#define MAX_DB_ENTRY_PER_SCAN PLATFORM_MAX_DB_ENTRY_PER_SCAN +/* max db entries selected per scan */ +#define MAX_DB_ENTRY_SELECTED_PER_SCAN PLATFORM_MAX_DB_ENTRY_SELECTED_PER_SCAN + +#define ICMP_MSG_RATE_LIMIT 3 /* rate limit for icmp message */ +#define V4_CONFIG_DELETE_TO 600 /* timeout for entry to be deleted */ + +/* session timeout */ + +extern u16 tcp_initial_setup_timeout; +extern u16 tcp_active_timeout; +extern u16 udp_init_session_timeout; +extern u16 udp_act_session_timeout; +extern u16 icmp_session_timeout; + +extern u8 timeout_dirty_flag; + +/* mapping refresh direction, + * 0 outbound only refresh, + * 1 inbound and outbound refresh + */ +extern u8 mapping_refresh_both_direction; + + +extern u16 cnat_main_db_max_ports_per_user; +extern u32 cnat_main_db_icmp_rate_limit; +extern u32 cnat_main_db_icmp_rate_limit_core; +extern u32 crc_zero_udp_rate_limit_core; + +extern u16 cnat_static_port_range; + +typedef enum { + LOG_FORMAT_UNDEFINED =0, + LOG_FORMAT_COMPACT, + LOG_FORMAT_NF9, + LOG_FORMAT_MAX, /* keep this as last */ +} log_format_t; + +typedef enum { + CNAT_CONFIG_DEL_OP = 0, + CNAT_CONFIG_ADD_OP, +} cnat_op_flag_t; + +extern u8 ftp_alg_enabled; +extern u16 rtsp_alg_port_num; + +/* + * load balancing debug mode + */ +extern u8 lb_debug_enable; + +/* good or evil mode + * 0 endpoint-independnet filter, good mode + * 1 address depedent filter, evil mode + */ +extern u8 address_dependent_filtering; + +extern u16 per_user_icmp_msg_limit; + +/* vrfmap or portmap holding time + * after delete + */ +extern u16 config_delete_timeout; + +/* + * Bit map for various configuration in the POLICY KNOB case + */ +#define BIDIR_REFRESH_ENABLE 0x01 +#define BIDIR_REFRESH_DISABLE 0x02 +#define FTP_ALG_ENABLE 0x04 +#define FTP_ALG_DISABLE 0x08 +#define DEFAULT_NFV9_LOGGING_SERVER_ENABLE 0x10 +#define DEFAULT_NFV9_LOGGING_SERVER_DISABLE 0x20 + + +/* + * This structure contains a single VRF map configuration + * from a bulk message. This structure is in conformanace + * with the following structures defined in cnat_config_api.h + * - spp_api_cnat_v4_bulk_vrf_map_t + * + * Any change in the above structures should be propagated here + */ +typedef struct _spp_api_cnat_v4_single_vrf_map_req { + u32 i_vrf_id; + u32 o_vrf_id; + + u16 i_vrf; + u16 o_vrf; + + u32 start_addr; + u32 end_addr; + + u16 vrf_policy_enable; +#define TCP_MSS_ENABLE 0x0001 +#define TCP_MSS_DISABLE 0x0002 +#define NFV9_LOGGING_ENABLE 0x0004 +#define NFV9_LOGGING_DISABLE 0x0008 +#define VRF_MAP_DELETE 0x0010 +#define VRF_MAP_ADD 0x0020 +#define BULK_ALLOC_CHANGE 0x0040 + + u16 tcp_mss_value; + u32 vrf_nfv9_logging_ipv4_address; + u16 vrf_nfv9_logging_udp_port; + u16 vrf_nfv9_refresh_rate; + u16 vrf_nfv9_timeout_rate; + u16 vrf_nfv9_path_mtu; +#ifndef NO_BULK_LOGGING + bulk_alloc_size_t bulk_size; +#endif /* NO_BULK_LOGGING */ +} spp_api_cnat_v4_single_vrf_map_req; + +typedef struct _spp_api_cnat_v4_single_vrf_map_rc { + u8 vrf_map_rc; + u8 tcp_mss_rc; + u8 nfv9_logging_rc; + u8 pad; +} spp_api_cnat_v4_single_vrf_map_rc; + +/* + * Bulk Response for the VRF map request + */ +typedef struct _spp_api_cnat_v4_bulk_vrf_map_resp { + u16 _spp_msg_id; + u8 bulk_rc; + u8 pad; + + u32 num_vrfmap_entries; + + spp_api_cnat_v4_single_vrf_map_rc vrf_map_rc; + +} spp_api_cnat_v4_bulk_vrf_map_resp; + +/* + * Bulk Response for the Policy Knob request + */ +typedef struct _spp_api_cnat_v4_bulk_policy_knob_resp { + u16 _spp_msg_id; + u8 bulk_rc; /* Global rc code */ + u8 pad; + + u8 port_limit_rc; + u8 icmp_timeout_rc; + u8 udp_init_timeout_rc; + u8 udp_act_timeout_rc; + + u8 tcp_init_timeout_rc; + u8 tcp_act_timeout_rc; + u8 nfv9_logging_rc; + u8 pad2; +} spp_api_cnat_v4_bulk_policy_knob_resp; + + +/* PPTP ALG defs and structures */ + +/* dont change the order.. + maintened at offset mapped to msg ids */ + +typedef struct pptp_ctrl_msg_ctrs_t { + u64 dummy; + u64 sccr; + u64 sccrp; + u64 stccrq; + u64 stccrp; + u64 erq; + u64 erp; + u64 ocrq; + u64 ocrp; + u64 icrq; + u64 icrp; + u64 iccn; + u64 cclr; + u64 cdn; + u64 wen; + u64 sli; +}pptp_ctrl_msg_ctrs_t; + +#define PPTP_INCR(ctr) pptp_cfg.counters.pptp_##ctr++ +#define PPTP_DECR(ctr) pptp_cfg.counters.pptp_##ctr-- + +typedef struct pptp_counters_t { + + u64 pptp_ctrl_msg_drops; + u64 pptp_active_tunnels; + u64 pptp_active_channels; + u64 pptp_in2out_gre_drops; + u64 pptp_out2in_gre_drops; + u64 pptp_in2out_gre_fwds; + u64 pptp_out2in_gre_fwds; + pptp_ctrl_msg_ctrs_t ctrl_ctrs; + +} pptp_counters_t; + +#define CNAT_PPTP_ENABLE 1 +#define CNAT_PPTP_DEF_TIMEOUT 60 /* secs */ + +typedef struct cnat_pptp_config_t { + u8 enable; + u16 timeout; + pptp_counters_t counters; + +} cnat_pptp_config_t; + + +#define CNAT_PPTP_ENABLE_FLAG 0x01 +#define CNAT_PPTP_TIMEOUT_FLAG 0x02 + +/* pptp config msg resp */ +typedef struct _spp_api_cnat_v4_config_pptp_alg_resp { + u16 _spp_msg_id; + u8 bulk_rc; + u8 pad; + +} spp_api_cnat_v4_config_pptp_alg_resp_t; + +typedef struct { + u16 msg_id; + u8 rc; + u8 pad[5]; + + /* better to have a group structures rather than individual + variables, any change in counters is will automatically + reflect here */ + pptp_counters_t counters; +} pptp_show_counters_resp_t ; + + +extern cnat_pptp_config_t pptp_cfg; + + +/* ========= 6RD declarations =============================== */ + +#define V6RD_ENTRY_DELETE 0x00 +#define IPV4_TUNNEL_SRC_CONFIG 0x04 +#define TUNNEL_MTU_CONFIG 0x08 +#define IPV4_PREFIXMASK_LEN_CONFIG 0x10 +#define IPV4_SUFFIXMASK_LEN_CONFIG 0x20 +#define TTL_CONFIG 0x40 +#define TOS_CONFIG 0x80 +#define V6RD_IPV6_PREFIX_CONFIG 0x100 +#define V6RD_RESET_DF_BIT_CONFIG 0x200 +#define V6RD_UNICAST_ADDR_CONFIG 0x400 +#define V6RD_REASSEMB_CONFIG 0x800 + +#define TTL_ENABLE 0x1 +#define TOS_ENABLE 0x2 +#define RESET_DF_BIT 0x4 +#define REASSEMBLY_ENABLE 0x8 + +/* ========= 6RD declarations =============================== */ + +/* + * Single Request for XLAT config + */ +typedef struct _spp_api_cnat_v4_single_xlat_config_req { + + /* + * Indicates the xlat instance id - How big will this value be + * Can we restrict it between 0..255, that way the APP code + * can use an array to store the xlat instances. + */ + u32 xlat_id; + +#define XLAT_ENTRY_DELETE 0x0000 +#define IPV6_SVI_IF_NUM_CONFIG 0x0001 +#define IPV4_SVI_IF_NUM_CONFIG 0x0002 +#define IPV4_TO_IPV6_TCP_MSS_CONFIG 0x0004 +#define IPV6_TO_IPV4_TCP_MSS_CONFIG 0x0008 +#define IPV6_PREFIX_CONFIG 0x0010 +#define IPV6_UBIT_ON_CONFIG 0x0020 +#define IPV6_NON_TRANSLATABLE_PREFIX_MAP_CONFIG 0x0040 +#define IPV4_TOS_SETTING_CONFIG 0x0080 +#define IPV6_TOS_SETTING_CONFIG 0x0100 +#define IPV4_DFBIT_CLEAR_CONFIG 0x0200 +#define ICMPV6_PTB_MTU_SET_CONFIG 0x0400 +#define IPV6_NON_TRANSLATABLE_PREFIX_MAP_ALG_CONFIG 0x0800 +#define CPE_V4_PREFIX_CONFIG 0x1000 /* for map-t */ +#define CPE_V6_PREFIX_CONFIG 0x2000 /* for map-t */ +#define EXTERNAL_V6_PREFIX_CONFIG 0x4000 /* for map-t */ +#define PORT_SHARING_RATIO_CONFIG 0x8000 /* for map-t */ +#define CONSECUTIVE_PORTS_CONFIG 0x10000 /* for map-t */ + + u32 xlat_config_fields_enable; + + /* + * If numbers of the IPv6 and IPv4 SVI interfaces + */ + u32 ipv6_svi_if_num; + u32 ipv4_svi_if_num; + + /* + * TCP MSS values for the 2 XLAT directions + */ + u16 v4_to_v6_tcp_mss; + u16 v6_to_v4_tcp_mss; + + /* + * XLAT IPv6 prefix + */ + u32 v6_prefix[4]; + + /* + * XLAT IPv6 prefix mask + */ + u8 v6_prefix_mask_len; + + /* + * Set to non-zero if UBITs are reserved + */ +#define UBITS_ON 0x01 +#define IPV4_DF_BIT_CLEAR 0x02 +#define ICMPV6_MTU_SET 0x04 +#define IPV4_TOS_SET_ENABLED 0x08 +#define IPV6_TC_SET_ENABLED 0x10 + + u8 feature_enable_bits; + + u8 v4_prefix_mask_len; + +#define IPV6_NON_TRANSLATABLE_PREFIX_MAP_ALG_HASH 0x1 +#define IPV6_NON_TRANSLATABLE_PREFIX_MAP_ALG_TTL 0x2 +#define IPV6_NON_TRANSLATABLE_PREFIX_MAP_ALG_RANDOM 0x3 + u8 non_translatable_v6_prefix_v4_map_prefix_alg; + + u8 ipv6_tos_value; + + u8 ipv4_tos_value; + + u8 pad2; + + u8 pad3; + + u32 v4_prefix; + + /* + * MAP-T/MAP-E specific parameters + */ + u8 xlat_type; + + u32 cpe_domain_v6_prefix[4]; + u8 cpe_domain_v6_prefix_len; + + u32 cpe_domain_v4_prefix; + u8 cpe_domain_v4_prefix_len; + + u32 external_domain_v6_prefix[4]; + u8 external_domain_v6_prefix_len; + + u8 port_sharing_ratio_bits; + u8 consecutive_ports_bits; + +} spp_api_cnat_v4_single_xlat_config_req; + +/* + * Single Response for the xlat config request + */ +typedef struct _spp_api_cnat_v4_single_xlat_config_resp { + u8 v4_if_num_rc; + u8 v6_if_num_rc; + u8 v4_to_v6_tcp_mss_rc; + u8 v6_to_v4_tcp_mss_rc; + + u8 v6_prefix_rc; + u8 ubit_on_rc; + u8 v4_prefix_rc; + u8 xlat_id_rc; + + u8 non_translatable_v6_prefix_v4_map_alg_rc; + u8 ipv4_dfbit_clear_rc; + u8 icmpv6_ptb_mtu_set_rc; + u8 ipv4_tos_set_rc; + + u8 ipv6_tos_set_rc; + u8 pad1; + u8 pad2; + u8 pad3; +} spp_api_cnat_v4_single_xlat_config_resp; + +/* + * Bulk Response for the xlat config request + */ +typedef struct _spp_api_cnat_v4_bulk_xlat_config_resp { + u16 _spp_msg_id; + u16 pad; + + u32 bulk_rc; + + u32 num_xlat_entries; + + spp_api_cnat_v4_single_xlat_config_resp xlat_config_resp; + +} spp_api_cnat_v4_bulk_xlat_config_resp; + +typedef struct _spp_api_v6rd_v4_single_v6rd_config_resp { + u8 v6rd_id_rc; + u8 v4_if_num_rc; + u8 v6_if_num_rc; + u8 tunnel_source_rc; + u8 tunnel_mtu_rc; + u8 ipv4masklen_prefix_rc; + u8 ipv4masklen_suffix_rc; + u8 ttl_rc; + u8 tos_rc; + u8 anycast_rc; + u8 v6_prefix_rc; + u8 v6_br_unicast_rc; + u8 reassembly_rc; + u8 pad1; + u8 pad2; + u8 pad3; +} spp_api_v6rd_v4_single_v6rd_config_resp_t; + +typedef struct _spp_api_v6rd_v4_bulk_v6rd_config_resp { + u16 _spp_msg_id; + u16 pad; + u32 bulk_rc; + u32 num_v6rd_entries; + spp_api_v6rd_v4_single_v6rd_config_resp_t v6rd_config_resp[0]; +} spp_api_v6rd_v4_bulk_v6rd_config_resp_t; + +/* + * Single Request for MAPE config + */ +typedef struct _spp_api_mape_single_config_req { + + /* + * Indicates the mape instance id - How big will this value be + * Can we restrict it between 0..255, that way the APP code + * can use an array to store the xlat instances. + */ + u32 mape_id; + +#define MAPE_ENTRY_DELETE 0x0000 +#define MAPE_IPV4_SVI_IF_NUM_CONFIG 0x0001 +#define MAPE_IPV6_SVI_IF_NUM_CONFIG 0x0002 +#define MAPE_IPV4_TO_IPV6_TCP_MSS_CONFIG 0x0004 +#define MAPE_IPV6_TO_IPV4_TCP_MSS_CONFIG 0x0008 +#define MAPE_CPE_V4_PREFIX_CONFIG 0x0010 +#define MAPE_CPE_V6_PREFIX_CONFIG 0x0020 +#define MAPE_PORT_SHARING_RATIO_CONFIG 0x0040 +#define MAPE_CONSECUTIVE_PORTS_CONFIG 0x0080 +#define MAPE_PATH_MTU 0x0100 +#define MAPE_TUNNEL_ENDPOINT_V6_CONFIG 0x0200 + + u32 mape_config_fields_enable; + + /* + * If numbers of the IPv6 and IPv4 SVI interfaces + */ + u32 ipv6_svi_if_num; + u32 ipv4_svi_if_num; + + /* + * TCP MSS values for the 2 XLAT directions + */ + u16 v4_to_v6_tcp_mss; + u16 v6_to_v4_tcp_mss; + + /* + * Path v6 MTU. + */ + u32 path_mtu; + + /* + * CPE IPv6 prefix and mask len. + */ + u32 cpe_domain_v6_prefix[4]; + u8 cpe_domain_v6_prefix_len; + + /* + * CPE IPv4 prefix and mask len. + */ + u32 cpe_domain_v4_prefix; + u8 cpe_domain_v4_prefix_len; + + /* + * BR IPv6 tunnel end point V6 prefix and mask len. + */ + u32 aftr_tunnel_endpoint_address_v6[4]; + u8 aftr_tunnel_endpoint_address_v6_len; + + /* + * BR IPv6 tunnel end point V6 prefix and mask len. + */ + u8 port_sharing_ratio_bits; + u8 consecutive_ports_bits; + +} spp_api_mape_single_config_req; + + +/* + * Single Response for the mape config response + */ +typedef struct _spp_api_mape_single_config_resp { + u8 v4_if_num_rc; + u8 v6_if_num_rc; + u8 v4_to_v6_tcp_mss_rc; + u8 v6_to_v4_tcp_mss_rc; + u8 mape_id_rc; + u8 path_mtu_rc; + u8 cpe_v6_prefix_rc; + u8 cpe_v4_prefix_rc; + u8 tunnel_endpoint_prefix_rc; + u8 port_sharing_ratio_rc; + u8 port_contiguous_rc; + u8 pad1; +} spp_api_mape_single_config_resp; + +/* + * Bulk Response for the mape config request + */ +typedef struct _spp_api_mape_bulk_config_resp { + u16 _spp_msg_id; + u16 pad; + u32 bulk_rc; + u32 num_mape_entries; + spp_api_mape_single_config_resp mape_config_resp; +} spp_api_mape_bulk_config_resp; + + +#endif /* __CNAT_CONFIG_H__ */ diff --git a/plugins/vcgn-plugin/vcgn/cnat_config_api.h b/plugins/vcgn-plugin/vcgn/cnat_config_api.h new file mode 100644 index 00000000..0789d6a9 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_config_api.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2015 Cisco and/or its affiliates. + * 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 __CNAT_CONFIG_API_H__ +#define __CNAT_CONFIG_API_H__ + +typedef struct _spp_api_cnat_v4_add_vrf_map { + u16 _spp_msg_id; + u8 rc; + u8 pad; + u32 i_vrf_id; + u32 o_vrf_id; + u16 i_vrf; + u16 o_vrf; + u32 start_addr[8]; + u32 end_addr[8]; +} spp_api_cnat_v4_add_vrf_map_t; + +typedef struct _spp_api_cnat_v4_config_nfv9_logging { + u16 _spp_msg_id; + u8 rc; + u8 enable; + u32 ipv4_address; + u32 i_vrf_id; + u16 i_vrf; + u16 port; + u16 refresh_rate; + u16 timeout_rate; + u16 path_mtu; + u8 nfv9_global_collector; + u8 session_logging; +} spp_api_cnat_v4_config_nfv9_logging_t; + + +#endif diff --git a/plugins/vcgn-plugin/vcgn/cnat_db.h b/plugins/vcgn-plugin/vcgn/cnat_db.h new file mode 100644 index 00000000..3596e238 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_db.h @@ -0,0 +1,701 @@ +/* + *------------------------------------------------------------------ + * cnat_db.h - translation database definitions + * + * Copyright (c) 2007-2013 Cisco and/or its affiliates. + * 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 __CNAT_DB_H__ +#define __CNAT_DB_H__ + +#include "cnat_cli.h" +#include "cnat_ports.h" +#include "index_list.h" + +#define VRF_NAME_LEN_STORED 12 +#define MAX_VRFID 400 +typedef struct _cnat_svi_params_entry { + u16 svi_type; + u16 pad; + + u32 vrf_id; + u16 if_num; + + u32 ipv6_addr[4]; + u32 ipv4_addr; + + u8 direction; + u32 tbl_id; /* vrf */ + u32 vrf_override_id; /* tbl_id for override vrf */ + u8 vrf_override_flag; + u8 partition_id; +} cnat_svi_params_entry; + +typedef struct _cnat_ingress_vrfid_name_entry { + u32 vrf_id; + u16 ref_count; /*no# of serviceApps under a single vrf*/ + u8 vrf_name[VRF_NAME_LEN_STORED]; + u16 pad1; +} cnat_ingress_vrfid_name_entry; +#define HASH_ENHANCE 4 + +#define CNAT_DB_SIZE (PLATFORM_MAX_NAT_ENTRIES / PLATFORM_CNAT_INSTS) +#define CNAT_MAIN_HASH_SIZE (HASH_ENHANCE * PLATFORM_CNAT_MAIN_PRELIM_HASH_SIZE) +#define CNAT_MAIN_HASH_MASK (CNAT_MAIN_HASH_SIZE-1) + +#define CNAT_USER_DB_SIZE (PLATFORM_MAX_USER_ENTRIES / PLATFORM_CNAT_INSTS) +#define CNAT_USER_HASH_SIZE (HASH_ENHANCE * PLATFORM_CNAT_USER_PRELIM_HASH_SIZE) +#define CNAT_USER_HASH_MASK (CNAT_USER_HASH_SIZE-1) + +#define CNAT_SESSION_DB_SIZE (PLATFORM_MAX_NAT_ENTRIES / PLATFORM_CNAT_INSTS) +#define CNAT_SESSION_HASH_SIZE (HASH_ENHANCE * PLATFORM_CNAT_MAIN_PRELIM_HASH_SIZE) +#define CNAT_SESSION_HASH_MASK (CNAT_SESSION_HASH_SIZE-1) + + +#define CNAT_MAX_SESSIONS_PER_BIB 0xFFFF + +#define NUM_BITS_IN_UWORD (8*sizeof(uword)) + +/* No. of per ip/port config will be limited to 1024 */ +#define CNAT_TIMEOUT_HASH_SIZE 1024 +#define CNAT_TIMEOUT_HASH_MASK (CNAT_TIMEOUT_HASH_SIZE - 1) +#define CNAT_TIMEOUT_FULL_MASK 0xFFFFFFFFFFFFFFFF +#define CNAT_TIMEOUT_IPPROT_MASK PLATFORM_CNAT_TIMEOUT_IPPROT_MASK +#define CNAT_TIMEOUT_PORTPROT_MASK PLATFORM_CNAT_TIMEOUT_PORTPROT_MASK + +#define TRUE 1 +#define FALSE 0 + +/* + * The key structure. All fields are in NETWORK byte order! + */ +typedef struct { + u32 ipv4; + u16 port; + u16 vrf; //bit0-12:vrf, bit13:unused, bit14-15:protocol +} cnat_db_key_t; + +/* bit14-15:protocol in cnat_db_key_t */ +#define CNAT_INVALID_PROTO 0x0000 +#define CNAT_PPTP 0x0000 +#define CNAT_UDP 0x4000 +#define CNAT_TCP 0x8000 +#define CNAT_ICMP 0xc000 +#define CNAT_VRF_MASK 0x3fff +#define CNAT_PRO_MASK 0xc000 +#define CNAT_PRO_SHIFT 14 + +/* + * Maximum number of VRF entries supported + */ +#define CNAT_MAX_VRFMAP_ENTRIES (CNAT_VRF_MASK + 1) +/* + * for hashing purposes, fetch the key in one instr. + */ +typedef union { + cnat_db_key_t k; + u64 key64; +} cnat_key_t; + +typedef struct { + cnat_key_t k; + u32 bucket; +} cnat_db_key_bucket_t; + +typedef struct { + u32 ipv6[4]; + cnat_key_t ipv4_key; +} dslite_key_t; + +typedef struct { +/* + cnat_db_key_bucket_t ck; + u32 ipv6[4]; +*/ + dslite_key_t dk; + u32 bucket; +} dslite_db_key_bucket_t; + + +/* Per port/ip timeout related strucutres */ +extern index_slist_t *cnat_timeout_hash; + +typedef struct { + cnat_key_t timeout_key; + u16 timeout_value; +} cnat_timeout_t; + +typedef struct { + cnat_timeout_t t_key; + index_slist_t t_hash; +} cnat_timeout_db_entry_t; + +extern cnat_timeout_db_entry_t *cnat_timeout_db; + +/* + * Main translation database entries. Currently 0x5A = 90 bytes in length. + * Given 20,000,000 entries, it saves nearly 1gb of SDRAM to pack the entries + * and pay the extra prefetch. So, that's what we do. + */ + +typedef struct { + /* 0x00 */ + index_slist_t out2in_hash; /* hash-and-chain, x2 */ + index_slist_t in2out_hash; + + /* 0x08 */ + u16 flags; /* Always need flags... */ +#define CNAT_DB_FLAG_PORT_PAIR (1<<0) +#define CNAT_DB_FLAG_TCP_ACTIVE (1<<1) +#define CNAT_DB_FLAG_ENTRY_FREE (1<<2) +#define CNAT_DB_FLAG_UDP_ACTIVE (1<<3) +#define CNAT_DB_FLAG_STATIC_PORT (1<<4) +/* This alg entry is set for FTP data connection */ +#define CNAT_DB_FLAG_ALG_ENTRY (1<<5) + +/* Will be set for TCP connection with destination port - 1723 + * note - here CNAT_DB_FLAG_TCP_ACTIVE is also set */ +#define CNAT_DB_FLAG_PPTP_TUNNEL_INIT (1<<6) +#define CNAT_DB_FLAG_PPTP_TUNNEL_ACTIVE (1<<7) + +/* for PPTP GRE packtes */ +#define CNAT_DB_FLAG_PPTP_GRE_ENTRY (1<<8) + +/* for PCP support */ +#define CNAT_DB_FLAG_PCPI (1<<9) +#define CNAT_DB_FLAG_PCPE (1<<10) +#define CNAT_PCP_FLAG (CNAT_DB_FLAG_PCPI | CNAT_DB_FLAG_PCPE) + +#define CNAT_TAC_SEQ_MISMATCH (1<<11) +/* This alg entry is set for ftp control connection */ +#define CNAT_DB_FLAG_ALG_CTRL_FLOW (1<<12) + +/* This is for marking the state where connection is closing */ +#define CNAT_DB_FLAG_TCP_CLOSING (1<<13) + +#define CNAT_DB_DSLITE_FLAG (1<<14) +#define CNAT_DB_NAT64_FLAG (1<<15) + + /* 0x0A */ + u16 vrfmap_index; /* index of vrfmap */ + + /* 0x0C */ + u32 user_index; /* index of user that owns this entry */ + + /* 0x10 */ + cnat_key_t out2in_key; /* network-to-user, outside-to-inside key */ + + /* 0x18 */ + cnat_key_t in2out_key; /* user-to-network, inside-to-outside key */ + + /* 0x20 */ + index_dlist_t user_ports; /* per-user translation list */ + + /* 0x28 */ + u32 out2in_pkts; /* pkt counters */ + + /* 0x2C */ + u32 in2out_pkts; + + /* 0x30 */ + u32 entry_expires; /* timestamp used to expire translations */ + + /* 0x34 */ + union { /* used by FTP ALG, pkt len delta due to FTP PORT cmd */ + u16 delta; + i8 alg_dlt[2]; /* two delta values, 0 for previous, 1 for current */ + u16 il; /* Used to indicate if interleaved mode is used + in case of RTSP ALG */ + } alg; + + /* 0x36 */ + u16 timeout; + + /* 0x38 */ + union { + struct seq_pcp_t { + u32 tcp_seq_num; /* last tcp (FTP) seq # that has pkt len change due to PORT */ + u32 pcp_lifetime; /* peer and map life time value sent in reply*/ + } seq_pcp; + + /* This is for TCP seq check */ + struct tcp_seq_chk_t { + u32 seq_no; + u32 ack_no; + } tcp_seq_chk; + + /* used for pptp alg entries + 1. only tunnel : prev and next = 0xFFFFFFFF + 2. first gre entry : prev = tunnel db, next = next gre db + 3. last gre entry : prev = previous gre/tunnel db, next= 0xFFFFFFFF; + + *while adding gre entry- updated at the begining of head + *while deleting gre entry - hash look up will be done and prev and next are adjusted + * while deleting need not traverse throufgh the list, as done in index_dlist_remelem + + */ + index_dlist_t pptp_list; + + } proto_data; + + /* 0x40 */ + u32 dst_ipv4; /* pointer to ipv4 dst list, used in evil mode */ + + /* 0x44 */ + u16 dst_port; + + /* 0x46 */ + u16 dslite_nat44_inst_id; + + /* 0x48 */ + u32 session_head_index; + + /* 0x4C */ + u16 nsessions; + + /* 0x4E */ + u8 unused; + + /* 0x4F */ + u8 scale; + + /* 0x50 */ + u32 diff_window; + + /* Sizeof cnat_main_db_entry_t = 0x54 */ +} cnat_main_db_entry_t; + +/* Caution ... + * 1. The size of this structure should be same as that of + * nat64_bib_user_entry_t + * 2. Do not alter the position of first four fields + */ +typedef struct { + /* 0x00 */ + index_slist_t user_hash; /* hash 'n chain bucket chain */ + + /* 0x04 */ + u16 ntranslations; /* translations hold by this user */ + + /* 0x06 */ + u8 icmp_msg_count; /* use to rate limit imcp send to this user */ + + /* 0x07 */ + u8 flags; /* To identfiy whether it is NAT64 or NAT44 etc */ +#define CNAT_USER_DB_NAT44_FLAG 0 +#define CNAT_USER_DB_NAT64_FLAG 1 +#define CNAT_USER_DB_DSLITE_FLAG 2 +#define CNAT_USER_DB_PORT_LIMIT_EXCEEDED 0X80 + + /* 0x08 */ + u32 translation_list_head_index; + + /* 0x0C */ + u32 portmap_index; /* index of bound port-map */ + + /* 0x10 */ + cnat_key_t key; /* For dslite this should store IPv6 address */ + u32 ipv6[4]; // B4 ipv6 address + /* 0x18 */ +#if 0 + u32 temp1; + u32 temp2; + u32 temp3; +#endif + /* 0x28 same as nat64_user_db */ +#ifndef NO_BULK_LOGGING + /* Now adding 8 more bytes for bulk allocation.. This makes it + * 0x30 (48). Added the same to nat64_bib_user_entry_t make the + * the sizes equal. For nat64 stful, we may support bulk allocation + * later. + */ + /* Indicates the currently used bulk port range */ + i16 bulk_port_range_cache[BULK_RANGE_CACHE_SIZE]; +#endif /* #ifndef NO_BULK_LOGGING */ +} cnat_user_db_entry_t; + +/* + * cnat_session_entry_t + * This structure represents the cnat session table. It maintains the + * information about the destination of a given translation (main db) + * There would be entry here only if packets are send to more than 1 destn + * from the same source. + */ +typedef struct { + + /* 0x00 */ + index_slist_t cnat_session_hash; + + /* 0x04 */ + u32 main_db_index; /* would point to v4 src transport address */ + + /* 0x08 */ + cnat_key_t v4_dest_key; + + /* 0x10 */ + u16 flags; /* Same as cnat_main_db_t */ + + /* 0x12 */ + u16 timeout; + + /* 0x14 */ + u32 entry_expires; + /* 0x18 */ + index_dlist_t main_list; + /* 0x20 = 32 B */ + + union { /* alg same as cnat_main_db_t */ + u16 delta; + i8 alg_dlt[2]; + u16 il; + } alg; + + /* 0x22 */ + u16 tcp_flags; + + /* 0x24 */ + u32 tcp_seq_num; + + /* 0x28 */ + u32 ack_no; + + /* 0x2C */ + u32 window; + + /* 0x30 */ + u8 scale; + + /* 0x31 */ + u8 pad; + + /* 0x32 */ +} cnat_session_entry_t; + + + +/* + * out2in and in2out hash bucket arrays are simply arrays of index_slist_t's + */ + +typedef enum { + CNAT_DB_CREATE_DEFAULT=0, /* honor cnat_main_db_max_ports_per_user */ + CNAT_DB_CREATE_OVERRIDE, /* just do it. */ +} cnat_db_create_policy_t; + +typedef struct { + cnat_key_t in2out_key; + cnat_key_t out2in_key; + u32 dst_ipv4; /* evil for mode only */ + u16 cnat_instance; + cnat_portmap_t *portmap; + u16 *portmap_inuse; + cnat_main_db_entry_t *db; + cnat_db_create_policy_t policy; + port_pair_t pair_of_ports; +} cnat_db_create_args_t; + +extern cnat_main_db_entry_t *cnat_main_db; +extern cnat_user_db_entry_t *cnat_user_db; +extern cnat_session_entry_t *cnat_session_db; + +#define S_WAO 0 +#define S_WA 1 /* waiting for address pool */ +#define S_WO 2 /* waiting for outside vrf */ +#define S_RUN 3 /* got everything */ +#define S_DEL 4 /* just delete */ + +#define INVALID_UIDX 0xffff /*invalid svi app uidb index */ +#define INVALID_VRFID 0xffffffff /*invalid vrf id */ + +typedef struct { + u16 status; + u16 tcp_mss; //tcp max segment size for this inside vrf */ + u32 delete_time; + u16 i_vrf; //inside SVI uidx + u16 o_vrf; //outside SVI uidx + u32 i_vrf_id; //inside vrf id + u32 o_vrf_id; //outside vrf id + cnat_portmap_v2_t *portmap_list; + u32 nfv9_logging_index; + u32 syslog_logging_index; + u16 ip_n_to_1; +#ifndef NO_BULK_LOGGING + bulk_alloc_size_t bulk_size; +#endif /* #ifndef NO_BULK_LOGGING */ + u32 pcp_server_addr; + u32 pcp_server_port; + + u8 nf_logging_policy; + u8 syslog_logging_policy; + u8 frag_tout; + u32 rseed_ip; + u16 port_limit; + u8 tcp_seq_check_enable; + u8 pad; + u32 tcp_seq_user_window; + u8 filter_policy; + u8 ignore_port; +} cnat_vrfmap_t; + +/* + * When creating cnat_vrfmap entry, ensure that any already + * configured logging info is taken into account + */ +#define CNAT_SET_VRFMAP_NFV9_LOGGING_INDEX(logging_index, i_vrf) \ +do { \ + cnat_nfv9_logging_info_t *my_nfv9_logging_info = 0; \ + pool_foreach (my_nfv9_logging_info, cnat_nfv9_logging_info, ({ \ + if (my_nfv9_logging_info->i_vrf == i_vrf) { \ + logging_index = my_nfv9_logging_info - cnat_nfv9_logging_info; \ + break; \ + } \ + })); \ +while (0) + + +typedef struct { + /* + * spp_ctx_alloc() call failed + */ + u64 nfv9_logging_context_creation_fail_count; + + /* + * Cannot send the existing logging pkt, so cannot create + * any additional packets for logging purposes + */ + u64 nfv9_logging_context_creation_deferred_count; + + /* + * Cannot send the existing logging pkt due to cnat_rewrite_output + * superframe being full. + */ + u64 nfv9_downstream_constipation_count; + + /* + * buffer for spp_ctx_alloc() call failed + */ + u64 nfv9_logging_context_buffer_allocation_fail_count; + +} cnat_global_counters_t; + + +extern cnat_global_counters_t cnat_global_counters; + +extern u16 *cnat_portmap_indices_by_vrf; +extern cnat_vrfmap_t *cnat_portmap_by_vrf; +extern cnat_portmap_t **cnat_portmaps; +extern u16 **cnat_portmaps_inuse; + +extern cnat_vrfmap_t *cnat_map_by_vrf; + +/* + * Special define to indicate that the VRF map index entry is empty + */ +#define VRF_MAP_ENTRY_EMPTY 0xffff +extern u16 vrf_map_array[CNAT_MAX_VRFMAP_ENTRIES]; + +extern cnat_svi_params_entry svi_params_array[CNAT_MAX_VRFMAP_ENTRIES]; +extern cnat_ingress_vrfid_name_entry vrfid_name_map[MAX_VRFID]; + +extern index_slist_t *cnat_out2in_hash; +extern index_slist_t *cnat_in2out_hash; +extern index_slist_t *cnat_user_hash; +extern index_slist_t *cnat_session_hash; + +typedef enum { + CNAT_DB_IN2OUT = 0, + CNAT_DB_OUT2IN, +} cnat_db_which_t; + +typedef enum { + CNAT_NO_ICMP_MSG =0, + CNAT_ICMP_MSG, +} cnat_icmp_msg_t; + +typedef struct { + cnat_errno_t error; + cnat_icmp_msg_t gen_icmp_msg; + u32 svi_addr; +} cnat_gen_icmp_info; + +typedef cnat_vrfmap_t nat64_vrfmap_t; +typedef cnat_portmap_v2_t nat64_portmap_v2_t; + +#define CNAT_V4_GET_HASH(key64, hash, mask) \ + a = key64; \ + b = c = 0x9e3779b97f4a7c13LL; \ + /* Jenkins hash, arbitrarily use c as the "answer" */ \ + hash_mix64(a, b, c); \ + hash = c & mask; + +#define CNAT_V4_GET_SESSION_HASH(main_index, in_addr, port, vrf, hash, mask) \ + a = main_index ^ in_addr ^ port ^ vrf; \ + b = c = 0x9e3779b9; \ + /* Jenkins hash, arbitrarily use c as the "answer" */ \ + hash_mix32(a, b, c); \ + hash = c & mask; + +#define CNAT_V4_GET_FRAG_HASH(key64, key32, hash, mask) \ + a = key64; \ + b = key32; \ + c = 0x9e3779b97f4a7c13LL; \ + hash_mix64(a, b, c); \ + hash = c % mask; + +#define CNAT_DB_UPDATE_IN2OUT_TIMER \ + db->entry_expires = cnat_current_time; \ + db->in2out_pkts++; + +#define CNAT_DB_TIMEOUT_RST(db) \ + if(PREDICT_TRUE(db->entry_expires != 0 )) \ + db->entry_expires = cnat_current_time; + +#define DEBUG_I2O_DROP(debug_flag) \ +if (debug_i_flag & debug_flag) { \ + cnat_db_debug_i2o_drop(&ki); \ +} + + +cnat_main_db_entry_t *cnat_main_db_create (cnat_db_create_args_t *a); +void cnat_main_db_entry_delete(cnat_main_db_entry_t *ep); + +void cnat_delete_main_db_entry(cnat_main_db_entry_t *ep); +void cnat_delete_main_db_entry_v2(cnat_main_db_entry_t *ep); + + +cnat_main_db_entry_t* +cnat_get_main_db_entry(cnat_db_key_bucket_t *ki, + port_pair_t port_type, + cnat_errno_t *error, + cnat_user_db_entry_t ** user_db_entry); + +cnat_main_db_entry_t* +cnat_get_main_db_entry_v2(cnat_db_key_bucket_t *ki, + port_pair_t port_pair_type, + port_type_t port_type, + cnat_gen_icmp_info *info, + cnat_key_t *dest_info); + +cnat_main_db_entry_t* +cnat_create_static_main_db_entry_v2(cnat_db_key_bucket_t *ki, + cnat_db_key_bucket_t *ko, + cnat_vrfmap_t *my_vrfmap, + cnat_gen_icmp_info *info); + +cnat_main_db_entry_t* +cnat_create_main_db_entry_and_hash(cnat_db_key_bucket_t *ki, + cnat_db_key_bucket_t *ko, + cnat_user_db_entry_t *udb); + +cnat_user_db_entry_t* +cnat_user_db_create_entry(cnat_db_key_bucket_t *uki, + u32 portmap_index); + +cnat_user_db_entry_t* +cnat_user_db_lookup_entry(cnat_db_key_bucket_t *uki); + +cnat_main_db_entry_t* +cnat_main_db_lookup_entry(cnat_db_key_bucket_t *ki); + +cnat_main_db_entry_t* +cnat_main_db_lookup_entry_out2in (cnat_db_key_bucket_t *ko); + +void cnat_main_db_entry_dump (cnat_main_db_entry_t *db); +void cnat_db_in2out_hash_delete (cnat_main_db_entry_t *ep, cnat_user_db_entry_t *up); +void cnat_db_out2in_hash_delete (cnat_main_db_entry_t *ep); +void cnat_user_db_delete (cnat_user_db_entry_t *up); +void cnat_db_debug_i2o_drop(cnat_db_key_bucket_t *ki); + +/* + * Function to dump the Hash Table that maps if_num to uidb_index + */ +extern void cnat_if_num_hash_table_dump(void); + +#define MAIN_DB_TYPE 0 +#define SESSION_DB_TYPE 1 +u16 query_and_update_db_timeout(void *db, u8 db_type); + +u16 cnat_timeout_db_create (cnat_timeout_t t_entry); +void cnat_timeout_db_delete(cnat_key_t t_key); + +cnat_session_entry_t * +cnat_create_session_db_entry(cnat_key_t *ko, + cnat_main_db_entry_t *bdb, u8 log); + +void cnat_dest_update_main2session(cnat_main_db_entry_t *mdb, + cnat_session_entry_t *sdb); + +cnat_session_entry_t *cnat_handle_1to2_session( + cnat_main_db_entry_t *mdb, + cnat_key_t *dest_info); + +void cnat_add_dest_n_log( + cnat_main_db_entry_t *mdb, + cnat_key_t *dest_info); + +cnat_session_entry_t * + cnat_session_db_lookup_entry(cnat_key_t *ko,u32 main_db_index); + +cnat_session_entry_t * + cnat_session_db_edm_lookup_entry(cnat_key_t *ko, + u32 session_head_index, + u32 main_db_index); + + +typedef struct{ + u32 sessions; + u32 active_translations; + u32 num_dynamic_translations; + u32 num_static_translations; + u64 in2out_drops_port_limit_exceeded; + u64 in2out_drops_system_limit_reached; + u64 in2out_drops_resource_depletion; + u64 no_translation_entry_drops; + u32 num_subscribers; + u32 dummy; + u64 drops_sessiondb_limit_exceeded; +} nat44_dslite_common_stats_t; + +typedef struct { + u32 translation_delete_count; + u32 translation_create_count; + u32 out2in_forwarding_count; +} nat44_dslite_global_stats_t; + +typedef struct { + u64 v4_to_v6_tcp_seq_mismatch_drop_count; + u64 v4_to_v6_tcp_seq_mismatch_count; + u64 v4_to_v6_out2in_session_create_count; + u64 v4_to_v6_end_point_filter_drop_count; +} nat44_counters_stats_t; + +#define NAT44_STATS 0 +#define DSLITE_STATS 1 +extern nat44_dslite_common_stats_t nat44_dslite_common_stats[255]; /* 0 is for nat44 */ +extern nat44_dslite_global_stats_t nat44_dslite_global_stats[2]; /* 0 for nat44 and 1 for dslite */ +extern nat44_counters_stats_t nat44_counters_stats[CNAT_MAX_VRFMAP_ENTRIES];/*For displaying show cgn inside-vrf counters */ + +#define NAT44_COMMON_STATS nat44_dslite_common_stats[NAT44_RESERVED_INST_ID] +#define NAT44_GLOBAL_STATS nat44_dslite_global_stats[NAT44_STATS] +#define DSLITE_GLOBAL_STATS nat44_dslite_global_stats[DSLITE_STATS] +#define SESSION_LOG_ENABLE 1 +#define ALG_ENABLED_DB(db) \ + ((db->flags & CNAT_PCP_FLAG) || \ + (db->flags & CNAT_DB_FLAG_ALG_CTRL_FLOW) || \ + (db->flags & (CNAT_DB_FLAG_PPTP_TUNNEL_INIT | \ + CNAT_DB_FLAG_PPTP_TUNNEL_ACTIVE))) + + +#endif /* __CNAT_DB_H__ */ diff --git a/plugins/vcgn-plugin/vcgn/cnat_db_scanner.c b/plugins/vcgn-plugin/vcgn/cnat_db_scanner.c new file mode 100644 index 00000000..6e536d84 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_db_scanner.c @@ -0,0 +1,493 @@ +/* + *--------------------------------------------------------------------------- + * cnat_db_scanner.c - cnat_db_scanner dispatch function and initialization + * + * Copyright (c) 2009-2014 Cisco and/or its affiliates. + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "cnat_db.h" +#include "cnat_logging.h" +#include "cnat_global.h" +#include "cnat_ipv4_udp.h" +#include "cnat_common_api.h" + +u32 translation_create_count, translation_delete_count; +u32 translation_create_rate, translation_delete_rate; + +u32 in2out_forwarding_count, out2in_forwarding_count; +u32 in2out_forwarding_rate, out2in_forwarding_rate; + +u32 nat44_active_translations; +u32 num_entries; +uword check_these_pool_indices[2*MAX_DB_ENTRY_SELECTED_PER_SCAN]; + +#define CNAT_DB_SCANNER_TURN_ON 5 /* just an arbitary number for easier debugging */ + +//extern u32 pcp_throttle_count; + +typedef struct { + u32 cached_next_index; + /* $$$$ add data here */ + + /* convenience variables */ + vlib_main_t * vlib_main; + vnet_main_t * vnet_main; +} cnat_db_scanner_main_t; + +cnat_db_scanner_main_t cnat_db_scanner_main; + + +static inline void check_session_for_expiry( + cnat_session_entry_t * sdb, u8 timeout_dirty + /*,dslite_table_entry_t *dslite_entry_ptr*/) +{ + void cnat_delete_session_db_entry (cnat_session_entry_t *ep, u8 log); + /* Tasks - + * 1. Check for expiry for this entry + * 2. Delete if expired + */ + u32 timeout = 0; + + switch(sdb->v4_dest_key.k.vrf & CNAT_PRO_MASK) { + case CNAT_TCP: + if (sdb->flags & CNAT_DB_FLAG_TCP_ACTIVE) { + timeout = sdb->timeout; + if(PREDICT_FALSE(timeout_dirty)) { + timeout = query_and_update_db_timeout( + (void *)sdb, SESSION_DB_TYPE); + } + if(PREDICT_TRUE(timeout == 0)) { + timeout = tcp_active_timeout; + //dslite_entry_ptr->timeout_info.tcp_active_timeout; + } + } else { + timeout = tcp_initial_setup_timeout; + //dslite_entry_ptr->timeout_info.tcp_initial_setup_timeout; + } + break; + case CNAT_UDP: + if (sdb->flags & CNAT_DB_FLAG_UDP_ACTIVE) { + timeout = sdb->timeout; + if(PREDICT_FALSE(timeout_dirty)) { + timeout = query_and_update_db_timeout( + (void *)sdb, SESSION_DB_TYPE); + } + + if(PREDICT_TRUE(timeout == 0)) { + timeout = udp_act_session_timeout; + //dslite_entry_ptr->timeout_info.udp_act_session_timeout; + } + } else { + timeout = udp_init_session_timeout; + //dslite_entry_ptr->timeout_info.udp_init_session_timeout; + } + break; + case CNAT_ICMP: + timeout = icmp_session_timeout; + //dslite_entry_ptr->timeout_info.icmp_session_timeout; + break; + case CNAT_PPTP: + timeout = pptp_cfg.timeout; + break; + default: + return; + } + /* Changes required for clearing sessions */ + if (PREDICT_FALSE((sdb->entry_expires == 0) || + (sdb->entry_expires + timeout < cnat_current_time))) { + cnat_delete_session_db_entry(sdb, TRUE); + } +} + +static u8 handle_db_scan_for_sessions( + cnat_main_db_entry_t *db, int *dirty_index, uword db_index + /* ,dslite_table_entry_t *dslite_entry_ptr */) +{ + /* Tasks - + * 1. Traverse through the sessions and check for timeouts + * 2. Delete sessions that have exipred + * 3. Check if the db has only one session remaining.. if so, + * the details of the session has to be moved to main db + * and session db entry needs to be freed + * 4. If db does not have any sessions left, the db itself + * needs to be deleted. + */ + u32 nsessions, session_index_head, session_index; + cnat_session_entry_t *sdb; + u8 timeout_dirty = FALSE; + + if(PREDICT_FALSE(*dirty_index == db_index)) { + *dirty_index = -1; + } + if(PREDICT_FALSE(timeout_dirty_flag == 1)) { + timeout_dirty_flag = 0; + *dirty_index = db_index; + timeout_dirty = TRUE; + } + + session_index_head = session_index = db->session_head_index; + nsessions = db->nsessions; + + do { + sdb = cnat_session_db + session_index; + if(PREDICT_FALSE(!sdb)) { + //TO DO: Debug msg? + return FALSE; + } + session_index = sdb->main_list.next; + check_session_for_expiry(sdb, timeout_dirty /*,dslite_entry_ptr*/); + nsessions--; /* To ensure that we do not get in to an infinite loop */ + } while(session_index != session_index_head + && db->session_head_index != EMPTY && + nsessions); + + /* Note.. the code below assumes that while deleting the + * sessions, we do not delete the main db entry if it does + * not have any sessions anymore + */ + if(PREDICT_FALSE((!db->nsessions) && + (!(db->flags & CNAT_DB_FLAG_STATIC_PORT)))) { + cnat_delete_main_db_entry_v2(db); + return TRUE; /* to indicate that main db was deleted */ + } + return FALSE; +} + +static void cnat_db_scanner(void) +{ + cnat_main_db_entry_t * db; + u32 timeout; + cnat_vrfmap_t *my_vrfmap __attribute__((unused)) = 0; + static int dirty_index = -1; + u16 instance __attribute__((unused)); + //dslite_table_entry_t *dslite_entry_ptr; + u32 i; + uword db_index; + //pcp_throttle_count = 0; + + for (i = 0; i < num_entries; i++) { + db_index = check_these_pool_indices[i]; + db = cnat_main_db + db_index; + timeout=0; + my_vrfmap = 0; + +#if 0 + if(PREDICT_FALSE(db->flags & CNAT_PCP_FLAG)) { + + if(db->proto_data.seq_pcp.pcp_lifetime < cnat_current_time) { + /* mark as implicit */ + db->flags &= ~CNAT_PCP_FLAG; + } + continue; + } + +#endif + if(PREDICT_FALSE(db->nsessions > 1)) { + if(PREDICT_FALSE( + handle_db_scan_for_sessions(db, &dirty_index, db_index /*,dslite_entry_ptr */))) { + continue; + } else if(PREDICT_TRUE(db->nsessions > 1)) { + continue; + } + /* if there is exactly one dest left.. let it fall through + * and check if that needs to be deleted as well + */ + } + +#if 0 + if (PREDICT_FALSE(db->flags & CNAT_DB_FLAG_STATIC_PORT)) { + if (PREDICT_FALSE(db->flags & CNAT_DB_DSLITE_FLAG)) { + if(PREDICT_FALSE( + ((dslite_entry_ptr->nf_logging_policy != SESSION_LOG_ENABLE) && + (dslite_entry_ptr->syslog_logging_policy != SESSION_LOG_ENABLE)) + || (db->nsessions !=1))) { + continue; + } + } else { + my_vrfmap = cnat_map_by_vrf + db->vrfmap_index; + if(PREDICT_FALSE( + ((my_vrfmap->nf_logging_policy != SESSION_LOG_ENABLE) && + (my_vrfmap->syslog_logging_policy != SESSION_LOG_ENABLE)) || + (db->nsessions !=1))) { + continue; + } + } + } +#endif + + switch(db->in2out_key.k.vrf & CNAT_PRO_MASK) { + case CNAT_TCP: + if (db->flags & CNAT_DB_FLAG_TCP_ACTIVE) { + timeout = db->timeout; + if(PREDICT_FALSE(dirty_index == db_index)) { + dirty_index = -1; + } + if(PREDICT_FALSE(timeout_dirty_flag == 1)) { + timeout_dirty_flag = 0; + dirty_index = db_index; + } + if(PREDICT_FALSE(dirty_index != -1)) { + timeout = query_and_update_db_timeout( + (void *)db, MAIN_DB_TYPE); + } + if(PREDICT_TRUE(timeout == 0)) { + timeout = tcp_active_timeout; + } + } else { + timeout = tcp_initial_setup_timeout; + } + break; + case CNAT_UDP: + if (db->flags & CNAT_DB_FLAG_UDP_ACTIVE) { + timeout = db->timeout; + if(PREDICT_FALSE(dirty_index == db_index)) { + dirty_index = -1; + } + if(PREDICT_FALSE(timeout_dirty_flag == 1)) { + timeout_dirty_flag = 0; + dirty_index = db_index; + } + if(PREDICT_FALSE(dirty_index != -1)) { + timeout = query_and_update_db_timeout( + (void *)db, MAIN_DB_TYPE); + } + if(PREDICT_TRUE(timeout == 0)) { + timeout = udp_act_session_timeout; + } + } else { + timeout = udp_init_session_timeout; + } + break; + case CNAT_ICMP: + timeout = icmp_session_timeout; + break; + case CNAT_PPTP: + timeout = pptp_cfg.timeout; + break; + default: + continue; + } + + + /* Ref: CSCtu97536 */ + if (PREDICT_FALSE((db->entry_expires == 0) || + (db->entry_expires + timeout < cnat_current_time))) { +#if 0 + if (PREDICT_FALSE(db->flags & CNAT_DB_FLAG_STATIC_PORT)) { + if (PREDICT_FALSE(db->flags & CNAT_DB_DSLITE_FLAG)) { + instance = db->dslite_nat44_inst_id; + } else { + instance = NAT44_RESERVED_INST_ID; + cnat_session_log_nat44_mapping_delete(db, 0, my_vrfmap); + } + + /* Reset the session details */ + db->nsessions = 0; + db->dst_ipv4 = 0; + db->dst_port = 0; + db->flags &= ~(CNAT_DB_FLAG_TCP_ACTIVE | CNAT_DB_FLAG_UDP_ACTIVE + | CNAT_DB_FLAG_ALG_ENTRY); + db->timeout = 0; + db->entry_expires = 0; + db->alg.delta = 0; + db->proto_data.seq_pcp.tcp_seq_num = 0; + continue; + } +#endif + //printf("DELETING DB ENTRY FOR 0x%x\n", db->in2out_key.k.ipv4); + cnat_delete_main_db_entry_v2(db); + } + //free(check_these_pool_indices[i]); + } +} + +static void walk_the_db (void) +{ + pool_header_t *h = pool_header(cnat_main_db); + u32 db_uword_len; + static u32 base_index = 0, free_bitmap_index = 0; + int bits_scanned = 0, i; + uword inuse_bitmap; + + num_entries=0; + + /* Across all db entries... */ + db_uword_len = vec_len(cnat_main_db) / NUM_BITS_IN_UWORD; + if (PREDICT_FALSE(vec_len(cnat_main_db) % NUM_BITS_IN_UWORD)) { + /* + * It should not come here as in cnat_db_init_v2() + * it is made multiple of NUM_BITS_IN_UWORD + */ + ASSERT(0); + return ; + } + + if (PREDICT_FALSE(! db_uword_len)) + return ; + + while (bits_scanned < MAX_DB_ENTRY_PER_SCAN) { + + if (PREDICT_FALSE(free_bitmap_index < vec_len(h->free_bitmap))) { + + /* free_bitmap exists and it is not all 0 */ + + inuse_bitmap = ~(h->free_bitmap[free_bitmap_index]); + i = 0; + while (inuse_bitmap) { + + /* Check to see if the index is in use */ + if (PREDICT_FALSE((inuse_bitmap >> i) & 1)) { + check_these_pool_indices[num_entries] = base_index + i; + inuse_bitmap &= ~((uword) 1 << i); + num_entries++; + } + i++; + } // while (inuse_bitmap) + } else { + + /* + * 64-bit entry is 0, means all 64 entries are allocated. + * So, simply add all 64 entries here. + * No need to form inuse_bitmap, check and reset bits + */ + for (i=0; ifree_bitmap)) + + /* Update free_bitmap_index and base_index for next run */ + if (PREDICT_FALSE(free_bitmap_index == db_uword_len - 1)) { + /* wrap-around for next run */ + free_bitmap_index = 0; + base_index = 0; + } else { + free_bitmap_index ++; + base_index += NUM_BITS_IN_UWORD; + } + + /* increment # of bits scanned */ + bits_scanned += NUM_BITS_IN_UWORD; + + /* Found enough entries to check ? */ + if (PREDICT_FALSE(num_entries >= MAX_DB_ENTRY_SELECTED_PER_SCAN)) + { + /* This check is introduced to keep fixed MAX scan entry value */ + /* This is very much required when we do scanning for NAT64 */ + /* please check comments in cnat_db_scanner() & + * handler_nat64_db_scanner() */ + if (num_entries >= MAX_COMBINED_DB_ENTRIES_PER_SCAN) { + num_entries = MAX_COMBINED_DB_ENTRIES_PER_SCAN; + } + break; + } + + } // while (bits_scanned < MAX_DB_ENTRY_PER_SCAN) + + if (PREDICT_FALSE(num_entries > 0)) { + //printf("%s: num_entries [%d]\n", __func__, num_entries); + cnat_db_scanner(); + } + return ; +} + +static uword cnat_db_scanner_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + f64 timeout = 0.01; /* timeout value in sec (10 ms) */ + static u8 timeout_count = 0; + + uword event_type; + uword * event_data = 0; + /* Wait until vCGN is configured */ + while (1) { + /* Assigning a huge timeout value, vCGN may or + * may not get configured within this timeout */ + vlib_process_wait_for_event_or_clock (vm, 1e9); + event_type = vlib_process_get_events (vm, &event_data); + + /* check whether the process is waken up by correct guy, + * otherwise continue waiting for the vCGN config */ + if (event_type == CNAT_DB_SCANNER_TURN_ON) { + break; + } + } + + while(1) { + vlib_process_suspend(vm, timeout); + + /* Above suspend API should serve the purpose, no need to invoke wait API */ + /* vlib_process_wait_for_event_or_clock (vm, timeout); */ + + /* Lets make use of this timeout for netflow packet sent */ + if (timeout_count < 100) { /* 100*10 ms = 1 sec */ + timeout_count++; + } else { + if (nfv9_configured) { + handle_pending_nfv9_pkts(); + } + timeout_count = 0; + } + /* Do we need this ? */ + //event_type = vlib_process_get_events (vm, &event_data); + cnat_current_time = (u32)vlib_time_now (vm); + if (cnat_db_init_done) { + walk_the_db(); + } + } + + return 0; +} + + +VLIB_REGISTER_NODE (cnat_db_scanner_node) = { + .function = cnat_db_scanner_fn, + .type = VLIB_NODE_TYPE_PROCESS, + .name = "cnat-db-scanner", + .process_log2_n_stack_bytes = 18, +}; + +clib_error_t *cnat_db_scanner_init (vlib_main_t *vm) +{ + cnat_db_scanner_main_t *mp = &cnat_db_scanner_main; + + mp->vlib_main = vm; + mp->vnet_main = vnet_get_main(); + + return 0; +} + +void cnat_scanner_db_process_turn_on(vlib_main_t *vm) +{ + vlib_process_signal_event (vm, cnat_db_scanner_node.index, + CNAT_DB_SCANNER_TURN_ON, 0); + return; +} + +VLIB_INIT_FUNCTION (cnat_db_scanner_init); + diff --git a/plugins/vcgn-plugin/vcgn/cnat_db_v2.c b/plugins/vcgn-plugin/vcgn/cnat_db_v2.c new file mode 100644 index 00000000..2b43849d --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_db_v2.c @@ -0,0 +1,3802 @@ +/* + *------------------------------------------------------------------ + * cnat_db_v2.c - translation database definitions + * + * Copyright (c) 2007-2013 Cisco and/or its affiliates. + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include "cnat_db.h" +#include "cnat_config.h" +#include "cnat_global.h" +#include "cnat_v4_functions.h" +#include "cnat_log_api.h" +#include "cnat_cli.h" +#include "spp_platform_trace_log.h" +#include "cnat_bulk_port.h" +#include "nat64_db.h" +#include "dslite_db.h" +#include "cnat_config_api.h" + +#define HASH_TABLE_SIZE 8192 // hash table size +#define THROTTLE_TIME 180 // throttle time value for out of port msg/user + +u8 cnat_db_init_done = 0; + +typedef struct { + /* Locks for multi thread support */ + CLIB_CACHE_LINE_ALIGN_MARK(cacheline0); + pthread_spinlock_t *main_db_lockp; + pthread_spinlock_t *user_db_lockp; + pthread_spinlock_t *session_db_lockp; + + u32 cached_next_index; + /* $$$$ add data here */ + + /* convenience variables */ + vlib_main_t * vlib_main; + vnet_main_t * vnet_main; +} cnat_db_v2_main_t; + +cnat_db_v2_main_t cnat_db_v2_main; + +#if 1 +/* TOBE_PORTED : Remove the following once fixed */ +#undef PREDICT_TRUE +#undef PREDICT_FALSE +#define PREDICT_TRUE(x) (x) +#define PREDICT_FALSE(x) (x) +#endif + +#define foreach_cnat_db_v2_error \ +_(DROP, "error-drop packets") + +typedef enum { +#define _(sym,str) CNAT_DB_V2_##sym, + foreach_cnat_db_v2_error +#undef _ + CNAT_DB_V2_N_ERROR, +} cnat_db_v2_error_t; + +static char * cnat_db_v2_error_strings[] __attribute__((unused)) = { +#define _(sym,string) string, + foreach_cnat_db_v2_error +#undef _ +}; + + +void cnat_table_entry_fill_map(u32 start_addr, u32 end_addr, + cnat_portmap_v2_t **port_map_holder) +{ + u32 this_start_addr, this_end_addr, this_addr, new; + u32 loop_count; + u32 pm_len, i; + cnat_portmap_v2_t *my_pm =0; + cnat_portmap_v2_t *pm = 0; + + my_instance_number = 0; + + this_start_addr = start_addr; + this_end_addr = end_addr; + + /* + * How many new addresses are getting added ?? + */ + /* commenting this. Right now end - start will be for this vCGN instance */ + //new = ((this_end_addr - this_start_addr) / MAX_CORES_PER_PARTITION) + 1; + new = (this_end_addr - this_start_addr) + 1; + + pm = *port_map_holder; + pm_len = vec_len(pm); +#if DEBUG_NOT_COMMENTED + printf("this_start_addr = 0x%08X, this_end_addr = 0x%08X, Num Addr = %d\n", + this_start_addr, this_end_addr, new); + printf("pm_len = %d\n", pm_len); +#endif + /* Check whether the address pool add requested already exists */ + my_pm = pm; + for(i = 0; i< pm_len; i++) { + if(my_pm->ipv4_address == this_start_addr) { + printf("address pool with addr 0x%08X exists\n", this_start_addr); + return; + } + my_pm++; + } + + /* + * For now give a warning message only.... + */ +#if 0 + if ((total_address_pool_allocated + new) > + CNAT_MAX_ADDR_POOL_SIZE_PER_CORE) { + printf("address pool size (%d) would cross permissible limit (%u) \n", + (total_address_pool_allocated + new), + CNAT_MAX_ADDR_POOL_SIZE_PER_CORE); + } +#endif + + total_address_pool_allocated += new; + vec_add2(pm, my_pm, new); + +#if DEBUG_NOT_COMMENTED + printf("total_address_pool_allocated changed from %d to %d (added %d)", + (total_address_pool_allocated - new), + total_address_pool_allocated, new); + printf("vec add is ok\n"); +#endif + + memset(my_pm, 0, new*sizeof(*my_pm)); + this_addr = this_start_addr; + loop_count = 0; /* Sanity counter */ + + while (this_addr <= this_end_addr) { +#if DEBUG_NOT_COMMENTED + printf("loop %d: this addr = 0x%08X\n", loop_count+1, this_addr); +#endif + my_pm->ipv4_address = this_addr; + /* + * Set all bits to "1" indicating all ports are free + */ + memset(my_pm->bm, 0xff, + (((BITS_PER_INST + BITS(uword)-1)/BITS(uword))*(sizeof(uword)))); + //this_addr += MAX_CORES_PER_PARTITION; + this_addr += 1; + my_pm++; + loop_count++; + } + /* + * We should have loop_count same as the new value + */ + if (loop_count != new) { + printf("Mismatch in loop_count (%d) != new (%d)\n", + loop_count, new); + } + + *port_map_holder = pm; + +#if DEBUG_NOT_COMMENTED + printf("revised pm len %d\n", vec_len(*port_map_holder)); +#endif + + return; +} + + +void cnat_delete_session_db_entry (cnat_session_entry_t *ep, u8 log); +void handle_cnat_port_exceeded_logging( + cnat_user_db_entry_t *udb, + cnat_key_t * key, + cnat_vrfmap_t *vrfmap); + +cnat_global_counters_t cnat_global_counters; +u32 last_log_timestamp = 0; +u32 last_user_dyn_port_exc_timestamp = 0; +u32 last_user_stat_port_exc_timestamp = 0; + +index_slist_t *cnat_out2in_hash; +index_slist_t *cnat_in2out_hash; +index_slist_t *cnat_user_hash; +index_slist_t *cnat_timeout_hash; +index_slist_t *cnat_session_hash; + +cnat_main_db_entry_t *cnat_main_db; +cnat_user_db_entry_t *cnat_user_db; +cnat_session_entry_t *cnat_session_db; +cnat_timeout_db_entry_t *cnat_timeout_db; + +cgse_nat_db_entry_t *cgse_nat_db; +cgse_nat_user_db_entry_t *cgse_user_db; +cgse_nat_session_db_entry_t *cgse_session_db; + +nat44_dslite_common_stats_t nat44_dslite_common_stats[255]; /* 0 is for nat44 */ +nat44_dslite_global_stats_t nat44_dslite_global_stats[2]; /* 0 for nat44 and 1 for dslite */ +nat44_counters_stats_t nat44_counters_stats[CNAT_MAX_VRFMAP_ENTRIES]; +/*For displaying show cgn inside-vrf counters */ + +/* + * This is the pool of vrf map structures used by latest main-db functions + */ +cnat_vrfmap_t *cnat_map_by_vrf; + +/* + * Have a mapping table of vrf_id-->vrf_map_index + * This helps in easily getting the vrf_map structure during + * main-db create paths + */ +u16 vrf_map_array[CNAT_MAX_VRFMAP_ENTRIES]; +cnat_svi_params_entry svi_params_array[CNAT_MAX_VRFMAP_ENTRIES]; +cnat_ingress_vrfid_name_entry vrfid_name_map[MAX_VRFID] = {{0}}; +u64 in2out_drops_port_limit_exceeded; +u64 in2out_drops_system_limit_reached; +u64 in2out_drops_resource_depletion; +u64 no_translation_entry_drops; +u32 no_sessions; + +#define CNAT_SET_ICMP_MSG_INFO \ +if (PREDICT_TRUE((my_vrfmap->i_vrf < CNAT_MAX_VRFMAP_ENTRIES) && \ + (svi_params_array[my_vrfmap->i_vrf].ipv4_addr))) { \ + info->gen_icmp_msg = icmp_msg_gen_allowed(); \ + info->svi_addr = svi_params_array[my_vrfmap->i_vrf].ipv4_addr; \ +} + +#define CNAT_DEBUG_INSIDE_ERR(err) \ +if (((protocol == CNAT_UDP) && \ + (debug_i_flag & CNAT_DEBUG_ERR_UDP)) || \ + ((protocol == CNAT_TCP) && \ + (debug_i_flag & CNAT_DEBUG_ERR_TCP)) || \ + ((protocol == CNAT_ICMP) && \ + (debug_i_flag & CNAT_DEBUG_ERR_ICMP))) { \ + cnat_db_debug_error(&u_ki, err); \ +} + +#define DSLITE_DEBUG_INSIDE_ERR(err) \ +if (((protocol == CNAT_UDP) && \ + (debug_i_flag & CNAT_DEBUG_ERR_UDP)) || \ + ((protocol == CNAT_TCP) && \ + (debug_i_flag & CNAT_DEBUG_ERR_TCP)) || \ + ((protocol == CNAT_ICMP) && \ + (debug_i_flag & CNAT_DEBUG_ERR_ICMP))) { \ + dslite_db_debug_error(&u_ki, err); \ +} + +#define PORT_LIMIT_LOW_THRESHOLD_FOR_SYSLOG 7 +/* If the max_limit is less than 10, no meaningful throttling can be + * done.. so, log only once per user and never clear the flag + * once the user exceeds limit + */ +#define CHECK_CLEAR_PORT_LIMIT_EXCEED_FLAG(udb, max_limit) \ + if(PREDICT_FALSE(udb->flags & CNAT_USER_DB_PORT_LIMIT_EXCEEDED)) { \ + if(udb->ntranslations < \ + ((max_limit/10)*PORT_LIMIT_LOW_THRESHOLD_FOR_SYSLOG) && \ + max_limit >= 10) { \ + udb->flags = udb->flags & (~CNAT_USER_DB_PORT_LIMIT_EXCEEDED); \ + } \ + } + +#ifdef TOBE_PORTED +/* Commented to remove unused variable warning */ +static char *debug_db_error[] = { + "no error", /* CNAT_SUCCESS */ + "no config", /*CNAT_NO_CONFIG*/ + "not in run state", /*CNAT_NO_VRF_RUN*/ + "no pool for any", /*CNAT_NO_POOL_ANY*/ + "no port for any", /*CNAT_NO_PORT_ANY*/ + "bad in use for any", /*CNAT_BAD_INUSE_ANY*/ + "not found for any", /*CNAT_NOT_FOUND_ANY*/ + "invalid index for direct", /*CNAT_INV_PORT_DIRECT*/ + "deleted addr for direct", /*CNAT_DEL_PORT_DIRECT*/ + "bad in use for direct",/*CNAT_BAD_INUSE_DIRECT*/ + "not found for direct",/*CNAT_NOT_FOUND_DIRECT*/ + "out of port limit", /*CNAT_OUT_LIMIT*/ + "main db limit", /*CNAT_MAIN_DB_LIMIT*/ + "user db limit", /*CNAT_USER_DB_LIMIT*/ + "not static port", /*CNAT_NOT_STATIC_PORT*/ + "bad static port request", /*CNAT_BAD_STATIC_PORT_REQ*/ + "not this core", /*CNAT_NOT_THIS_CORE*/ + "parser error", /*CNAT_ERR_PARSER*/ + "invalid msg id", /*CNAT_ERR_INVALID_MSG_ID*/ + "invalid msg size", /*CNAT_ERR_INVALID_MSG_SIZE*/ + "invalid payload size", /*CNAT_ERR_INVALID_PAYLOAD_SIZE*/ + "bad tcp udp port", /*CNAT_ERR_BAD_TCP_UDP_PORT*/ + "bulk single failure", /*CNAT_ERR_BULK_SINGLE_FAILURE*/ + "xlat id invalid", /*CNAT_ERR_XLAT_ID_INVALID*/ + "xlat v6 prefix invalid", /*CNAT_ERR_XLAT_V6_PREFIX_INVALID*/ + "xlat v4 prefix invalid", /*CNAT_ERR_XLAT_V4_PREFIX_INVALID*/ + "xlat tcp mss invalid", /*CNAT_ERR_XLAT_TCP_MSS_INVALID*/ + "6rd id invalid", /*CNAT_ERR_6RD_ID_INVALID*/ + "6rd v4 tunnel src invalid", /*CNAT_ERR_6RD_V4_TUNNEL_SRC_INVALID*/ + "6rd v6 prefix invalid", /*CNAT_ERR_6RD_V6_PREFIX_INVALID*/ + "6rd v6 BR unicast invalid", /*CNAT_ERR_6RD_V6_BR_UNICAST_INVALID*/ + "6rd v4 prefix masklen invalid", /*CNAT_ERR_6RD_V4_PREFIX_MASK_LEN_INVALID*/ + "6rd v4 suffix masklen invalid", /*CNAT_ERR_6RD_V4_SUFFIX_MASK_LEN_INVALID*/ + "6rd v4 combo masklen invalid", /*CNAT_ERR_6RD_V4_COMBO_MASK_LEN_INVALID*/ + "6rd tunnel mtu invalid", /*CNAT_ERR_6RD_TUNNEL_MTU_INVALID*/ + "6rd tunnel ttl invalid", /*CNAT_ERR_6RD_TUNNEL_TTL_INVALID*/ + "6rd tunnel tos invalid", /*CNAT_ERR_6RD_TUNNEL_TOS_INVALID*/ +}; +#endif + +f64 port_log_timestamps[HASH_TABLE_SIZE]; /* 32 KB array per core */ + +void port_exceeded_msg_log (u32 src_addr, u16 i_vrf) +{ + u32 hash_value; + f64 current_timestamp; + vlib_main_t *vlib_main; + + vlib_main = vlib_get_main(); + current_timestamp = vlib_time_now((vlib_main_t *) vlib_main); + + hash_value = ((src_addr >> 16) ^ ((src_addr & 0xffff) ^ i_vrf)) % (1024*8); + + if (PREDICT_FALSE((current_timestamp - port_log_timestamps[hash_value]) > THROTTLE_TIME)) { + u32 arg[2] = {i_vrf, src_addr}; + /* update timestamp */ + port_log_timestamps[hash_value] = current_timestamp; + spp_printf(CNAT_USER_OUT_OF_PORTS, 2, arg); + } + + return ; +} + +static void log_port_alloc_error(cnat_errno_t error, cnat_key_t *k) +{ + u32 error_code; + u32 arr[] = {k->k.vrf, k->k.ipv4, k->k.port}; + switch (error) + { + case CNAT_NO_POOL_ANY: + error_code = CNAT_NO_POOL_FOR_ANY_ERROR; + break; + case CNAT_NO_PORT_ANY: + error_code = CNAT_NO_PORT_FOR_ANY_ERROR; + break; + case CNAT_ERR_PARSER: + error_code = CNAT_WRONG_PORT_ALLOC_TYPE; + break; + case CNAT_BAD_INUSE_ANY: + error_code = CNAT_BAD_INUSE_ANY_ERROR; + break; + case CNAT_BAD_INUSE_DIRECT: + error_code = CNAT_BAD_INUSE_DIRECT_ERROR; + break; + case CNAT_NOT_FOUND_ANY: + error_code = CNAT_NOT_FOUND_ANY_ERROR; + break; + case CNAT_NOT_FOUND_DIRECT: + error_code = CNAT_NOT_FOUND_DIRECT_ERROR; + break; + case CNAT_INV_PORT_DIRECT: + error_code = CNAT_INV_PORT_FOR_DIRECT_ERROR; + break; + default: + error_code = CNAT_NEW_PORT_ALLOC_ERROR; /* If this code is seen in the log, + it means, new error codes are to be added here */ + break; + } + spp_printf(error_code, 3, arr); +} + +void cnat_db_debug_error(cnat_db_key_bucket_t *u_ki, + cnat_errno_t error) +{ + if (PREDICT_FALSE((u_ki->k.k.vrf == debug_i_vrf) && + ((u_ki->k.k.ipv4 >= debug_i_addr_start) && + (u_ki->k.k.ipv4 <= debug_i_addr_end)))) { +#ifdef DEBUG_PRINTF_ENABLED + PLATFORM_DEBUG_PRINT("failed to allocate port due to %s " + "for i-vrf 0x%x addr 0x%x port 0x%x\n", + debug_db_error[error], u_ki->k.k.vrf, + u_ki->k.k.ipv4, u_ki->k.k.port); +#endif + { + u32 arg[] = {u_ki->k.k.vrf, u_ki->k.k.ipv4, u_ki->k.k.port}; + spp_printf(error, 3, arg); + } + } +} + +void dslite_db_debug_error(dslite_db_key_bucket_t *u_ki, + cnat_errno_t error) +{ + if (PREDICT_FALSE((u_ki->dk.ipv4_key.k.vrf == debug_i_vrf) && + ((u_ki->dk.ipv4_key.k.ipv4 >= debug_i_addr_start) && + (u_ki->dk.ipv4_key.k.ipv4 <= debug_i_addr_end)))) { +#ifdef DEBUG_PRINTF_ENABLED + PLATFORM_DEBUG_PRINT("failed to allocate port due to %s " + "for i-vrf 0x%x addr 0x%x port 0x%x\n", + debug_db_error[error], u_ki->dk.ipv4_key.k.vrf, + u_ki->dk.ipv4_key.k.ipv4, u_ki->dk.ipv4_key.k.port); +#endif + { + u32 arg[] = {u_ki->dk.ipv4_key.k.vrf, u_ki->dk.ipv4_key.k.ipv4, u_ki->dk.ipv4_key.k.port}; + spp_printf(error, 3, arg); + } + } +} + +void cnat_db_debug_i2o_drop(cnat_db_key_bucket_t *ki) +{ + if (PREDICT_FALSE(((ki->k.k.vrf & CNAT_VRF_MASK) == debug_i_vrf) && + ((ki->k.k.ipv4 >= debug_i_addr_start) && + (ki->k.k.ipv4 <= debug_i_addr_end)))) { +#ifdef DEBUG_PRINTF_ENABLED + PLATFORM_DEBUG_PRINT("pakcet[i-vrf 0x%x addr 0x%x port 0x%x] dropped\n", + ki->k.k.vrf, ki->k.k.ipv4, ki->k.k.port); +#endif + { + u32 arg[] = {ki->k.k.vrf, ki->k.k.ipv4, ki->k.k.port}; + spp_printf(CNAT_PACKET_DROP_ERROR, 3, arg); + } + } +} + +void cnat_db_in2out_hash_delete (cnat_main_db_entry_t *ep, cnat_user_db_entry_t *up) +{ + u64 a, b, c; + u32 index, bucket; + cnat_main_db_entry_t *this, *prev; + +#ifdef DSLITE_DEF + if (PREDICT_FALSE(ep->flags & CNAT_DB_DSLITE_FLAG)) { + dslite_key_t dk = { + {up->ipv6[0], up->ipv6[1], up->ipv6[2], up->ipv6[3]} , + {ep->in2out_key.k.ipv4, ep->in2out_key.k.port, ep->in2out_key.k.vrf} + }; + DSLITE_V6_GET_HASH((&dk), + bucket, + CNAT_MAIN_HASH_MASK); + DSLITE_PRINTF(1, "Delete1 DSL main hash bucket ..%u\n", bucket); + } else { + CNAT_V4_GET_HASH(ep->in2out_key.key64, + bucket, CNAT_MAIN_HASH_MASK) + DSLITE_PRINTF(1, "Delete1 NAT44 main hash bucket ..%u\n", bucket); + } +#else + CNAT_V4_GET_HASH(ep->in2out_key.key64, + bucket, CNAT_MAIN_HASH_MASK) +#endif + + index = cnat_in2out_hash[bucket].next; + + ASSERT(index != EMPTY); + + prev = 0; + do { + this = cnat_main_db + index; + if (PREDICT_TRUE(this == ep)) { + if (prev == 0) { + cnat_in2out_hash[bucket].next = ep->in2out_hash.next; + return; + } else { + prev->in2out_hash.next = ep->in2out_hash.next; + return; + } + } + prev = this; + index = this->in2out_hash.next; + } while (index != EMPTY); + + ASSERT(0); +} + +void cnat_db_out2in_hash_delete (cnat_main_db_entry_t *ep) +{ + u64 a, b, c; + u32 index, bucket; + cnat_main_db_entry_t *this, *prev; + + CNAT_V4_GET_HASH(ep->out2in_key.key64, + bucket, CNAT_MAIN_HASH_MASK) + + index = cnat_out2in_hash[bucket].next; + + ASSERT(index != EMPTY); + + prev = 0; + do { + this = cnat_main_db + index; + if (PREDICT_TRUE(this == ep)) { + if (prev == 0) { + cnat_out2in_hash[bucket].next = ep->out2in_hash.next; + return; + } else { + prev->out2in_hash.next = ep->out2in_hash.next; + return; + } + } + prev = this; + index = this->out2in_hash.next; + } while (index != EMPTY); + + ASSERT(0); +} + +cnat_main_db_entry_t* +cnat_main_db_lookup_entry(cnat_db_key_bucket_t *ki) +{ + u64 a, b, c; + u32 index; + cnat_main_db_entry_t *db; + + CNAT_V4_GET_HASH(ki->k.key64, + ki->bucket, + CNAT_MAIN_HASH_MASK); + + index = cnat_in2out_hash[ki->bucket].next; + if (PREDICT_TRUE(index == EMPTY)) { + return (NULL); + } + + do { + db = cnat_main_db + index; + if (PREDICT_TRUE(db->in2out_key.key64 == ki->k.key64)) { + return db; + } + index = db->in2out_hash.next; + } while (index != EMPTY); + + return (NULL); +} + +void cnat_user_db_delete (cnat_user_db_entry_t *up) +{ + u64 a, b, c; + u32 index, bucket; + cnat_user_db_entry_t *this, *prev; + + if (PREDICT_FALSE(up->flags & CNAT_USER_DB_NAT64_FLAG) != 0) { + /* Preventive check - Not a NAT44 entry */ + return; + } + + pthread_spin_lock(cnat_db_v2_main.user_db_lockp); +#if 1 + if(PREDICT_FALSE(up->flags & CNAT_USER_DB_DSLITE_FLAG)) { + dslite_key_t dk = { + {up->ipv6[0], up->ipv6[1], up->ipv6[2], up->ipv6[3]} , + {{up->key.k.ipv4, up->key.k.port, up->key.k.vrf}} + }; + + DSLITE_V6_GET_HASH((&dk), + bucket, + CNAT_USER_HASH_MASK); + DSLITE_PRINTF(1, "Delete1 DSL user hash bucket ..%u\n", bucket); + } else { + CNAT_V4_GET_HASH(up->key.key64, + bucket, CNAT_USER_HASH_MASK) + DSLITE_PRINTF(1, "Delete1 NAT44 user hash bucket ..%u\n", bucket); + } +#else + CNAT_V4_GET_HASH(up->key.key64, + bucket, CNAT_USER_HASH_MASK) + DSLITE_PRINTF(1, "Delete2 NAT44 user hash bucket ..%u\n", bucket); +#endif + + index = cnat_user_hash[bucket].next; + + ASSERT(index != EMPTY); + + prev = 0; + do { + this = cnat_user_db + index; + if (PREDICT_TRUE(this == up)) { + if (prev == 0) { + cnat_user_hash[bucket].next = up->user_hash.next; + goto found; + } else { + prev->user_hash.next = up->user_hash.next; + goto found; + } + } + prev = this; + index = this->user_hash.next; + } while (index != EMPTY); + + ASSERT(0); + + found: + pool_put(cnat_user_db, up); + pthread_spin_unlock(cnat_db_v2_main.user_db_lockp); +} + +cnat_user_db_entry_t* +cnat_user_db_lookup_entry(cnat_db_key_bucket_t *uki) +{ + u64 a, b, c; + u32 index; + cnat_user_db_entry_t *udb=NULL; + + CNAT_V4_GET_HASH(uki->k.key64, + uki->bucket, + CNAT_USER_HASH_MASK) + + /* now: index in user vector */ + index = cnat_user_hash[uki->bucket].next; + if (PREDICT_TRUE(index != EMPTY)) { + do { + udb = cnat_user_db + index; + if (PREDICT_FALSE(udb->key.key64 == uki->k.key64)) { + return udb; + } + index = udb->user_hash.next; + } while (index != EMPTY); + } + return (NULL); +} + +cnat_user_db_entry_t* +cnat_user_db_create_entry(cnat_db_key_bucket_t *uki, + u32 portmap_index) +{ + cnat_user_db_entry_t *udb = NULL; + + pthread_spin_lock(cnat_db_v2_main.user_db_lockp); + pool_get(cnat_user_db, udb); + memset(udb, 0, sizeof(*udb)); + + udb->ntranslations = 1; + udb->portmap_index = portmap_index; + udb->key.key64 = uki->k.key64; + /* Add this user to the head of the bucket chain */ + udb->user_hash.next = + cnat_user_hash[uki->bucket].next; + cnat_user_hash[uki->bucket].next = udb - cnat_user_db; + +#ifndef NO_BULK_LOGGING + INIT_BULK_CACHE(udb) +#endif /* NO_BULK_LOGGING */ + pthread_spin_unlock(cnat_db_v2_main.user_db_lockp); + return udb; +} + +cnat_main_db_entry_t* +cnat_create_main_db_entry_and_hash(cnat_db_key_bucket_t *ki, + cnat_db_key_bucket_t *ko, + cnat_user_db_entry_t *udb) +{ + u64 a, b, c; + u32 db_index; + cnat_main_db_entry_t *db = NULL; + + pool_get(cnat_main_db, db); + memset(db, 0, sizeof(*db)); + + db_index = db - cnat_main_db; + db->in2out_key.k.ipv4 = ki->k.k.ipv4; + db->in2out_key.k.port = ki->k.k.port; + db->in2out_key.k.vrf = ki->k.k.vrf; + db->out2in_key.k.ipv4 = ko->k.k.ipv4; + db->out2in_key.k.port = ko->k.k.port; + db->out2in_key.k.vrf = ko->k.k.vrf; + + db->user_ports.next = db_index; + db->user_ports.prev = db_index; + db->user_index = udb - cnat_user_db; + //db->portmap_index = udb->portmap_index; + db->flags &= ~(CNAT_DB_DSLITE_FLAG); // Mark that it is not dslite + if (PREDICT_FALSE(udb->ntranslations == 1)) { + /* + * first port for this src vrf/src ip addr + */ + udb->translation_list_head_index = db_index; + } else { + index_dlist_addtail(udb->translation_list_head_index, + (u8 *)cnat_main_db, sizeof(cnat_main_db[0]), + STRUCT_OFFSET_OF(cnat_main_db_entry_t, user_ports), + db_index); + } + + /* + * setup o2i hash key + */ + CNAT_V4_GET_HASH(ko->k.key64, + ko->bucket, + CNAT_MAIN_HASH_MASK) + db->out2in_hash.next = cnat_out2in_hash[ko->bucket].next; + cnat_out2in_hash[ko->bucket].next = db_index; + /* + * setup i2o hash key, bucket is already calculate + */ + db->in2out_hash.next = cnat_in2out_hash[ki->bucket].next; + cnat_in2out_hash[ki->bucket].next = db_index; + +#if DEBUG > 1 + printf("\nMy_Instance_Number %d: Bucket %d, Db_Index %d", + my_instance_number, ki->bucket, db_index); + printf("\nInside (VRF 0x%x, IP 0x%x, PORT 0x%x)", + db->in2out_key.k.vrf, db->in2out_key.k.ipv4, db->in2out_key.k.port); + printf("\nOutside (VRF 0x%x, IP 0x%x, PORT 0x%x)", + db->out2in_key.k.vrf, db->out2in_key.k.ipv4, db->out2in_key.k.port); + printf("\nUser Index %d, IP 0x%x", + db->user_index, udb->key.k.ipv4); +#endif + + NAT44_COMMON_STATS.active_translations++; + + return db; +} + +static inline void pptp_clear_all_channels( + cnat_main_db_entry_t *db) +{ + u32 db_index, current_db_index; + cnat_main_db_entry_t *temp_db; + + /* clear all channels */ + + db_index = db->proto_data.pptp_list.next; + current_db_index = db - cnat_main_db; + + while( db_index != EMPTY) { + temp_db = cnat_main_db + db_index; + db_index = temp_db->proto_data.pptp_list.next; + temp_db->entry_expires = 0; + if(PREDICT_FALSE(temp_db->proto_data.pptp_list.prev + == current_db_index)) { // Decouple child GREs from parent + temp_db->proto_data.pptp_list.prev = EMPTY; + } + } + + db->proto_data.pptp_list.next = EMPTY; +} + +void pptp_remove_channel_from_tunnel(cnat_main_db_entry_t *db) { + + cnat_main_db_entry_t *prev_db, *next_db; + + prev_db = cnat_main_db + db->proto_data.pptp_list.prev; + next_db = cnat_main_db + db->proto_data.pptp_list.next; + + /* remove entry from the tunnel list */ + if(PREDICT_TRUE(db->proto_data.pptp_list.prev != EMPTY)) { + prev_db->proto_data.pptp_list.next = + db->proto_data.pptp_list.next ; + } + + if(db->proto_data.pptp_list.next != EMPTY) { + next_db->proto_data.pptp_list.prev + = db->proto_data.pptp_list.prev; + } + +} + +void cnat_delete_main_db_entry_v2 (cnat_main_db_entry_t *ep) +{ + u32 main_db_index; + u32 vrfmap_len, udb_len; + cnat_user_db_entry_t *up =0; + cnat_portmap_v2_t *pm =0; + cnat_portmap_v2_t *my_pm =0; + cnat_vrfmap_t *my_vrfmap =0; + u16 static_port_range; +#ifndef NO_BULK_LOGGING + bulk_alloc_size_t bulk_size; + int nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED; +#endif + pool_header_t *h = pool_header(cnat_user_db); + u16 instance = 0; + u32 my_index; + + + if (PREDICT_FALSE(ep->flags & CNAT_DB_NAT64_FLAG) != 0) { + /* Preventive check - Not a NAT44 entry */ + return; + } + + pthread_spin_lock(cnat_db_v2_main.main_db_lockp); + if(PREDICT_FALSE(ep->flags & + CNAT_DB_FLAG_PPTP_TUNNEL_ACTIVE)) { + pptp_clear_all_channels(ep); + PPTP_DECR(active_tunnels); + } + + if(PREDICT_FALSE(ep->flags & + CNAT_DB_FLAG_PPTP_GRE_ENTRY)) { + pptp_remove_channel_from_tunnel(ep); + PPTP_DECR(active_channels); + } + + /* This function gets called from various locations.. + * many times from config handler.. so we + * to ensure that multiple sessions if any are + * released + */ + + if(PREDICT_FALSE(ep->nsessions > 1)) { + cnat_session_entry_t *sdb; + while(ep->nsessions > 1 && + ep->session_head_index != EMPTY) { + sdb = cnat_session_db + ep->session_head_index; + cnat_delete_session_db_entry(sdb, TRUE); + } + } + + /* Find the set of portmaps for the outside vrf */ + vrfmap_len = vec_len(cnat_map_by_vrf); + udb_len = vec_len(cnat_user_db); + + /* In case of invalid user just return, deleting only main db + * is not a good idea, since some valid user db entry might be pointing + * to that main db and hence leave the dbs in a inconsistent state + */ + if (PREDICT_FALSE((ep->user_index >= udb_len) || + (clib_bitmap_get(h->free_bitmap, ep->user_index)))) { +#ifdef DEBUG_PRINTF_ENABLED + printf("invalid/unused user index in db %d\n", ep->user_index); +#endif + spp_printf(CNAT_INV_UNUSED_USR_INDEX, 1, (u32 *) &(ep->user_index)); + cnat_main_db_entry_dump(ep); + goto unlock; + } + + up = cnat_user_db + ep->user_index; + +/* Point to the right portmap list */ +if (PREDICT_FALSE(ep->flags & CNAT_DB_DSLITE_FLAG)) { + instance = ep->dslite_nat44_inst_id; + pm = dslite_table_db_ptr[instance].portmap_list; + if(PREDICT_FALSE((pm == NULL))) { + DSLITE_PRINTF(3, "NULL portmap list for dslite_id %u, state %u\n", + instance, dslite_table_db_ptr[instance].state); + cnat_main_db_entry_dump(ep); + goto delete_entry; + } + static_port_range = + STAT_PORT_RANGE_FROM_INST_PTR(&(dslite_table_db_ptr[instance])); + /* + * Netflow logging API for delete event + */ + bulk_size = + BULKSIZE_FROM_VRFMAP(&(dslite_table_db_ptr[instance])); +} else { + if (PREDICT_FALSE(ep->vrfmap_index >= vrfmap_len)) { +#ifdef DEBUG_PRINTF_ENABLED + printf("invalid vrfmap index in db\n"); +#endif + spp_printf(CNAT_INVALID_VRFMAP_INDEX, 0, NULL); + cnat_main_db_entry_dump(ep); + goto delete_entry; + } + instance = NAT44_RESERVED_INST_ID; + my_vrfmap = cnat_map_by_vrf + ep->vrfmap_index; + pm = my_vrfmap->portmap_list; + static_port_range = cnat_static_port_range; + bulk_size = BULKSIZE_FROM_VRFMAP(my_vrfmap); +} + + if (PREDICT_FALSE(ep->flags & CNAT_DB_FLAG_PORT_PAIR)) { + /* Give back the port(s) */ + cnat_port_free_v2_bulk(pm, up->portmap_index, + PORT_PAIR, ep->out2in_key.k.port, up, static_port_range +#ifndef NO_BULK_LOGGING + , bulk_size, &nfv9_log_req +#endif + ); + } else { + /* Give back the port(s) */ + cnat_port_free_v2_bulk (pm, up->portmap_index, + PORT_SINGLE, ep->out2in_key.k.port, up, static_port_range +#ifndef NO_BULK_LOGGING + , bulk_size, &nfv9_log_req +#endif + ); + } + + if (PREDICT_TRUE(!(ep->flags & CNAT_DB_DSLITE_FLAG))) { + if(PREDICT_FALSE(nfv9_log_req != CACHE_ALLOC_NO_LOG_REQUIRED)) { + if(PREDICT_FALSE(my_vrfmap->nf_logging_policy == SESSION_LOG_ENABLE)) { + if(ep->nsessions != 0) { + cnat_nfv9_nat44_log_session_delete(ep, NULL, my_vrfmap); + } + } else { + cnat_nfv9_log_mapping_delete(ep, my_vrfmap +#ifndef NO_BULK_LOGGING + , nfv9_log_req +#endif + ); + } + if(PREDICT_TRUE((my_vrfmap->syslog_logging_policy != SESSION_LOG_ENABLE) || + (ep->nsessions != 0))) { + cnat_syslog_nat44_mapping_delete(ep, my_vrfmap, NULL +#ifndef NO_BULK_LOGGING + , nfv9_log_req +#endif + ); + } + } + } else { + if(PREDICT_FALSE(nfv9_log_req != CACHE_ALLOC_NO_LOG_REQUIRED)) { + if(PREDICT_FALSE( dslite_table_db_ptr[instance].nf_logging_policy == + SESSION_LOG_ENABLE)) { + cnat_nfv9_ds_lite_log_session_delete(ep, + (dslite_table_db_ptr + instance),NULL); + } else { + cnat_nfv9_ds_lite_mapping_delete(ep, + (dslite_table_db_ptr + instance) +#ifndef NO_BULK_LOGGING + , nfv9_log_req +#endif + ); + } +#ifdef TOBE_PORTED + cnat_syslog_ds_lite_mapping_delete(ep, + (dslite_table_db_ptr + instance), NULL +#ifndef NO_BULK_LOGGING + , nfv9_log_req +#endif + ); +#endif /* TOBE_PORTED */ + } + } + +delete_entry: + + main_db_index = ep - cnat_main_db; + + pthread_spin_lock(cnat_db_v2_main.user_db_lockp); + up->ntranslations--; + pthread_spin_unlock(cnat_db_v2_main.user_db_lockp); + + /* + * when user reaches max allowed port limit + * we generate icmp msg and inc the counter + * when counter reach the icmp msg rate limit + * we stop icmp msg gen + * when a user port is freed + * that means we need to clear the msg gen counter + * so that next time + * reach max port limit, we can generate new icmp msg again + */ + up->icmp_msg_count = 0; + + up->translation_list_head_index = index_dlist_remelem ( + up->translation_list_head_index, (u8 *)cnat_main_db, + sizeof (cnat_main_db[0]), + STRUCT_OFFSET_OF(cnat_main_db_entry_t, user_ports), + main_db_index); + + cnat_db_in2out_hash_delete(ep, up); + + if (PREDICT_FALSE(up->ntranslations == 0)) { + ASSERT(up->translation_list_head_index == EMPTY); + nat44_dslite_common_stats[instance].num_subscribers--; + my_index = up->portmap_index; + my_pm = pm + my_index; + if(PREDICT_TRUE(my_pm->private_ip_users_count)) { + my_pm->private_ip_users_count--; +#ifdef DEBUG_PRINTF_IP_N_TO_1_ENABLED + PLATFORM_DEBUG_PRINT("\n cnat_delete_main_db_entry_v2 " + "private_ip_users_count = %d", + my_pm->private_ip_users_count); +#endif + + } + cnat_user_db_delete(up); + + } + + /* Remove from main DB hashes */ + //cnat_db_in2out_hash_delete(ep); + cnat_db_out2in_hash_delete(ep); + + pool_put(cnat_main_db, ep); + + if(PREDICT_FALSE(ep->flags & CNAT_DB_FLAG_STATIC_PORT)) { + nat44_dslite_common_stats[instance].num_static_translations--; + } else { + nat44_dslite_common_stats[instance].num_dynamic_translations--; + } + nat44_dslite_common_stats[instance].active_translations--; + nat44_dslite_global_stats[!!(instance - 1)].translation_delete_count ++; +unlock: + pthread_spin_unlock(cnat_db_v2_main.main_db_lockp); +} + +cnat_main_db_entry_t* +cnat_main_db_lookup_entry_out2in (cnat_db_key_bucket_t *ko) +{ + u64 a, b, c; + u32 index; + cnat_main_db_entry_t *db; + + CNAT_V4_GET_HASH(ko->k.key64, + ko->bucket, + CNAT_MAIN_HASH_MASK); + + index = cnat_out2in_hash[ko->bucket].next; + if (PREDICT_TRUE(index == EMPTY)) { + return (NULL); + } + + do { + db = cnat_main_db + index; + if (PREDICT_TRUE(db->out2in_key.key64 == ko->k.key64)) { + return db; + } + index = db->out2in_hash.next; + } while (index != EMPTY); + + return (NULL); +} + +/* Creates 2 sessions. + * Moves the default dest info from mdb to first session + * Fills the dest_info details in to second session and + * returns the pointer to second session + */ +cnat_session_entry_t *cnat_handle_1to2_session( + cnat_main_db_entry_t *mdb, + cnat_key_t *dest_info) +{ + cnat_key_t old_dest_info; + pool_header_t *h; + u32 free_session = 0; + u16 instance; + cnat_session_entry_t *session_db1 = NULL, *session_db2 = NULL; + + h = pool_header(cnat_session_db); + free_session = vec_len(h->free_indices) - 1; + + if (PREDICT_FALSE(free_session < 2)) { + if (mdb->flags & CNAT_DB_DSLITE_FLAG) { + instance = mdb->dslite_nat44_inst_id; + } else { + instance = NAT44_RESERVED_INST_ID; + } + + /* we need 2 sessions here, return NULL */ + nat44_dslite_common_stats[instance].drops_sessiondb_limit_exceeded++; + return NULL; + } + + old_dest_info.k.ipv4 = mdb->dst_ipv4; + old_dest_info.k.port = mdb->dst_port; + old_dest_info.k.vrf = mdb->in2out_key.k.vrf; + + /* create 2 new sessions */ + session_db1 = cnat_create_session_db_entry(&old_dest_info, + mdb, FALSE); + + if(PREDICT_FALSE(session_db1 == NULL)) { + return NULL; + } + + /* update pkt info to session 2 */ + session_db2 = cnat_create_session_db_entry(dest_info, + mdb, TRUE); + + if(PREDICT_FALSE(session_db2 == NULL)) { + cnat_delete_session_db_entry(session_db1, FALSE); + return NULL; + } + /* update main db info to session 1 */ + cnat_dest_update_main2session(mdb, session_db1); + + return session_db2; +} + +/* The below function shold be called only + * when a NAT44 STATIC entry received traffic + * for the first time. This is to ensure + * the destination is noted and logged + */ +void cnat_add_dest_n_log( + cnat_main_db_entry_t *mdb, + cnat_key_t *dest_info) +{ + + if(PREDICT_FALSE(mdb->nsessions != 0)) { + return; /* Should not have been called */ + } + + mdb->dst_ipv4 = dest_info->k.ipv4; + mdb->dst_port = dest_info->k.port; + mdb->nsessions = 1; + mdb->entry_expires = cnat_current_time; + u16 instance; + + if (mdb->flags & CNAT_DB_DSLITE_FLAG) { + instance = mdb->dslite_nat44_inst_id; + cnat_session_log_ds_lite_mapping_create(mdb, + (dslite_table_db_ptr + instance),NULL); + } else { + instance = NAT44_RESERVED_INST_ID; + cnat_vrfmap_t *my_vrfmap = cnat_map_by_vrf + mdb->vrfmap_index; + cnat_session_log_nat44_mapping_create(mdb, 0, my_vrfmap); + } +} + +/* + * this function is called by exception node + * when lookup is fialed in i2o node + * + * if reash per user port limit, + * set user_db_entry pointer, and error == CNAT_OUT_LIMIT + */ +static cnat_main_db_entry_t* +_cnat_get_main_db_entry_v2(cnat_db_key_bucket_t *ki, + port_pair_t port_pair_type, + port_type_t port_type, + cnat_gen_icmp_info *info, + cnat_key_t *dest_info) +{ + u16 protocol; + cnat_errno_t rv; + cnat_db_key_bucket_t u_ki, ko; + u32 my_index, free_main, free_user; + u32 current_timestamp; + u16 my_vrfmap_index; + u16 my_vrfmap_entry_found = 0; + cnat_vrfmap_t *my_vrfmap =0; + cnat_portmap_v2_t *pm =0; + cnat_user_db_entry_t *udb = 0; + cnat_main_db_entry_t *db = 0; + pool_header_t *h; + u16 port_limit; + cnat_portmap_v2_t *my_pm = 0; + +#ifndef NO_BULK_LOGGING + int nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED; +#endif + + + /* + * need to try lookup again because + * second pkt may come here before the entry is created + * by receiving first pkt due to high line rate. + */ + info->gen_icmp_msg = CNAT_NO_ICMP_MSG; + info->error = CNAT_SUCCESS; + db = cnat_main_db_lookup_entry(ki); + if (PREDICT_TRUE(db)) { + /* what if the source is talking to a + * new dest now? We will have to handle this case and + * take care of - creating session db and logging + */ + if(PREDICT_FALSE((!dest_info->k.ipv4) && (!dest_info->k.port))) { + return db; /* if dest_info is null don't create session */ + } + if(PREDICT_TRUE((db->dst_ipv4 == dest_info->k.ipv4) && + (db->dst_port == dest_info->k.port))) { + return db; + } + dest_info->k.vrf = db->in2out_key.k.vrf; + /* Src is indeed talking to a different dest */ + cnat_session_entry_t *session_db2 = NULL; + if(PREDICT_TRUE(db->nsessions == 1)) { + session_db2 = cnat_handle_1to2_session(db, dest_info); + if(PREDICT_TRUE(session_db2 != NULL)) { + CNAT_DB_TIMEOUT_RST(session_db2); + return db; + } else { + info->error = CNAT_ERR_NO_SESSION_DB; + return NULL; + } + } else if(PREDICT_FALSE(db->nsessions == 0)) { + /* Should be static entry.. should never happen + */ + if(PREDICT_TRUE(dest_info->k.ipv4 != 0)) { + cnat_add_dest_n_log(db, dest_info); + } + return db; + } else { + /* The src has already created multiple sessions.. very rare + */ + session_db2 = cnat_create_session_db_entry(dest_info, + db, TRUE); + if(PREDICT_TRUE(session_db2 != NULL)) { + CNAT_DB_TIMEOUT_RST(session_db2); + return db; + } else { + info->error = CNAT_ERR_NO_SESSION_DB; + return NULL; + } + } + + } + + /* + * step 1. check if outside vrf is configured or not + * and Find the set of portmaps for the outside vrf + * insider vrf is one to one mappted to outside vrf + * key is vrf and ip only + * ki.k.k.vrf has protocol bits, mask out + */ + protocol = ki->k.k.vrf & CNAT_PRO_MASK; + u_ki.k.k.vrf = ki->k.k.vrf & CNAT_VRF_MASK; + u_ki.k.k.ipv4 = ki->k.k.ipv4; + u_ki.k.k.port = 0; + + my_vrfmap_index = vrf_map_array[u_ki.k.k.vrf]; + my_vrfmap = cnat_map_by_vrf + my_vrfmap_index; + + my_vrfmap_entry_found = ((my_vrfmap_index != VRF_MAP_ENTRY_EMPTY) && + (my_vrfmap->status == S_RUN) && + (my_vrfmap->i_vrf == u_ki.k.k.vrf)); + + if (PREDICT_FALSE(!my_vrfmap_entry_found)) { + u32 arr[] = {ki->k.k.vrf, ki->k.k.ipv4, ki->k.k.port}; + if ((my_vrfmap_index == VRF_MAP_ENTRY_EMPTY) || + (my_vrfmap->i_vrf == u_ki.k.k.vrf)) { + info->error = CNAT_NO_CONFIG; + CNAT_DEBUG_INSIDE_ERR(CNAT_NO_CONFIG) + spp_printf(CNAT_NO_CONFIG_ERROR, 3, arr); + } else { + info->error = CNAT_NO_VRF_RUN; + CNAT_DEBUG_INSIDE_ERR(CNAT_NO_VRF_RUN) + spp_printf(CNAT_NO_VRF_RUN_ERROR, 3, arr); + } + + return (NULL); + } + + pm = my_vrfmap->portmap_list; + + port_limit = my_vrfmap->port_limit; + if(PREDICT_FALSE(!port_limit)) { + port_limit = cnat_main_db_max_ports_per_user; + } + /* + * set o2i key with protocl bits + */ + ko.k.k.vrf = my_vrfmap->o_vrf | protocol; + + /* + * step 2. check if src vrf, src ip addr is alreay + * in the user db + * if yes, use PORT_ALLOC_DIRECTED + * if no, use PORT_ALLOC_ANY since it is first time + */ + udb = cnat_user_db_lookup_entry(&u_ki); + if (PREDICT_TRUE(udb)) { + /* + * not first time allocate port for this user + * check limit + */ + if (PREDICT_FALSE(udb->ntranslations >= + port_limit)) { + /* Check for the port type here. If we are getting + * a STATIC PORT, allow the config. + */ + if (PREDICT_TRUE(port_type != PORT_TYPE_STATIC)) { + info->error = CNAT_OUT_LIMIT; + CNAT_SET_ICMP_MSG_INFO + CNAT_DEBUG_INSIDE_ERR(CNAT_OUT_LIMIT) + port_exceeded_msg_log(u_ki.k.k.ipv4, u_ki.k.k.vrf); + in2out_drops_port_limit_exceeded ++; + u_ki.k.k.port = ki->k.k.port; + u_ki.k.k.vrf = ki->k.k.vrf; + handle_cnat_port_exceeded_logging(udb, &u_ki.k, my_vrfmap); + return (NULL); + } + } + CHECK_CLEAR_PORT_LIMIT_EXCEED_FLAG(udb, + port_limit) + + /* + * check if main db has space to accomodate new entry + */ + h = pool_header(cnat_main_db); + + free_main = vec_len(h->free_indices) - 1; + if (PREDICT_FALSE(!free_main)) { + info->error = CNAT_MAIN_DB_LIMIT; + CNAT_SET_ICMP_MSG_INFO + in2out_drops_system_limit_reached ++; + CNAT_DEBUG_INSIDE_ERR(CNAT_MAIN_DB_LIMIT) + + current_timestamp = spp_trace_log_get_unix_time_in_seconds(); + if (PREDICT_FALSE((current_timestamp - last_log_timestamp) > + 1800)) { + spp_printf(CNAT_SESSION_THRESH_EXCEEDED, 0, NULL); + last_log_timestamp = current_timestamp; + } + +#ifdef UT_TEST_CODE + printf("Limit reached : OLD USER"); +#endif + return NULL; + } + + /* + * allocate port, from existing mapping + */ + my_index = udb->portmap_index; + + if (PREDICT_FALSE(port_type == PORT_TYPE_STATIC)) { + rv = cnat_static_port_alloc_v2_bulk(pm, + PORT_ALLOC_DIRECTED, + port_pair_type, + ki->k.k.ipv4, + ki->k.k.port, + &my_index, + &(ko.k.k.ipv4), + &(ko.k.k.port), + cnat_static_port_range +#ifndef NO_BULK_LOGGING + , + udb, BULKSIZE_FROM_VRFMAP(my_vrfmap), + &nfv9_log_req +#endif + , my_vrfmap->ip_n_to_1 + ); + + } else if (PREDICT_TRUE(port_type != PORT_TYPE_RTSP) ) { + + rv = cnat_dynamic_port_alloc_v2_bulk(pm, + PORT_ALLOC_DIRECTED, + port_pair_type, + &my_index, + &(ko.k.k.ipv4), + &(ko.k.k.port), + cnat_static_port_range +#ifndef NO_BULK_LOGGING + , + udb, BULKSIZE_FROM_VRFMAP(my_vrfmap), + &nfv9_log_req +#endif + , my_vrfmap->ip_n_to_1, + &(my_vrfmap->rseed_ip) + ); + + } else { + /* + * For RTSP, two translation entries are created, + * check if main db has space to accomodate two new entry + */ + free_main = free_main - 1; + if (PREDICT_FALSE(!free_main)) { + info->error = CNAT_MAIN_DB_LIMIT; + CNAT_SET_ICMP_MSG_INFO + in2out_drops_system_limit_reached ++; + CNAT_DEBUG_INSIDE_ERR(CNAT_MAIN_DB_LIMIT) + + return NULL; + } else { + rv = cnat_dynamic_port_alloc_rtsp_bulk(pm, + PORT_ALLOC_DIRECTED, + port_pair_type, + ki->k.k.port, + &my_index, + &(ko.k.k.ipv4), + &(ko.k.k.port), + cnat_static_port_range +#ifndef NO_BULK_LOGGING + , + udb, BULKSIZE_FROM_VRFMAP(my_vrfmap), + &nfv9_log_req +#endif + , &(my_vrfmap->rseed_ip) + ); + } + } + + + if (PREDICT_FALSE(rv != CNAT_SUCCESS)) { + info->error = rv; + CNAT_SET_ICMP_MSG_INFO + CNAT_DEBUG_INSIDE_ERR(rv) + in2out_drops_resource_depletion++; + log_port_alloc_error(rv, &(ki->k)); + return (NULL); + } + /* + * increment port in use for this user + */ + pthread_spin_lock(cnat_db_v2_main.user_db_lockp); + udb->ntranslations += 1; + pthread_spin_unlock(cnat_db_v2_main.user_db_lockp); + + } else { + /* + * first time allocate port for this user + */ + + /* + * Do not create entry if port limit is invalid + */ + + if (PREDICT_FALSE(!port_limit)) { + if (PREDICT_TRUE(port_type != PORT_TYPE_STATIC)) { + info->error = CNAT_OUT_LIMIT; + in2out_drops_port_limit_exceeded ++; + port_exceeded_msg_log(u_ki.k.k.ipv4, u_ki.k.k.vrf); + CNAT_SET_ICMP_MSG_INFO + CNAT_DEBUG_INSIDE_ERR(CNAT_OUT_LIMIT) + return (NULL); + } + } + + /* + * Check if main db has space for new entry + * Allowing a user db entry to be created if main db is not free + * will cause a port to be allocated to that user, which results in + * wastage of that port, hence the check is done here. + */ + h = pool_header(cnat_main_db); + free_main = vec_len(h->free_indices) - 1; + h = pool_header(cnat_user_db); + free_user = vec_len(h->free_indices) - 1; + + /* + * If either main_db or user_db does not have entries + * bail out, with appropriate error + */ + if (PREDICT_FALSE(!(free_main && free_user))) { + u32 log_error; + if(free_main) { + info->error = CNAT_USER_DB_LIMIT; + log_error = CNAT_USER_DB_LIMIT_ERROR; + } else { + info->error = CNAT_MAIN_DB_LIMIT; + log_error = CNAT_MAIN_DB_LIMIT_ERROR; + } + in2out_drops_system_limit_reached ++; + CNAT_SET_ICMP_MSG_INFO + CNAT_DEBUG_INSIDE_ERR(info->error) + spp_printf(log_error, 0, 0); + return NULL; + } + + if (PREDICT_FALSE(port_type == PORT_TYPE_STATIC)) { + rv = cnat_static_port_alloc_v2_bulk(pm, + PORT_ALLOC_ANY, + port_pair_type, + ki->k.k.ipv4, + ki->k.k.port, + &my_index, + &(ko.k.k.ipv4), + &(ko.k.k.port), + cnat_static_port_range +#ifndef NO_BULK_LOGGING + , + udb, BULKSIZE_FROM_VRFMAP(my_vrfmap), + &nfv9_log_req +#endif + , my_vrfmap->ip_n_to_1 + ); + + } else if (PREDICT_TRUE(port_type != PORT_TYPE_RTSP)) { + rv = cnat_dynamic_port_alloc_v2_bulk(pm, + PORT_ALLOC_ANY, + port_pair_type, + &my_index, + &(ko.k.k.ipv4), + &(ko.k.k.port), + cnat_static_port_range +#ifndef NO_BULK_LOGGING + , NULL, BULKSIZE_FROM_VRFMAP(my_vrfmap), + &nfv9_log_req +#endif + , my_vrfmap->ip_n_to_1, + &(my_vrfmap->rseed_ip) + ); + } else { + /* + * For RTSP, two translation entries are created, + * check if main db has space to accomodate two new entry + */ + free_main = free_main - 1; + if (PREDICT_FALSE(!free_main)) { + info->error = CNAT_MAIN_DB_LIMIT; + CNAT_SET_ICMP_MSG_INFO + in2out_drops_system_limit_reached ++; + CNAT_DEBUG_INSIDE_ERR(CNAT_MAIN_DB_LIMIT) + + return NULL; + } else { + + rv = cnat_dynamic_port_alloc_rtsp_bulk(pm, + PORT_ALLOC_ANY, + port_pair_type, + ki->k.k.port, + &my_index, + &(ko.k.k.ipv4), + &(ko.k.k.port), + cnat_static_port_range +#ifndef NO_BULK_LOGGING + , NULL, BULKSIZE_FROM_VRFMAP(my_vrfmap), + &nfv9_log_req +#endif + , &(my_vrfmap->rseed_ip) + ); + /* TODO: Add the port pair flag here */ + } + } + + + + if (PREDICT_FALSE(rv != CNAT_SUCCESS)) { + info->error = rv; + in2out_drops_resource_depletion ++; + CNAT_SET_ICMP_MSG_INFO + CNAT_DEBUG_INSIDE_ERR(rv) + log_port_alloc_error(rv, &(ki->k)); + return (NULL); + } + /* + * create entry in user db + */ + udb = cnat_user_db_create_entry(&u_ki, my_index); + NAT44_COMMON_STATS.num_subscribers++; + my_pm = pm + my_index; + if(PREDICT_TRUE(my_pm->private_ip_users_count < PORTS_PER_ADDR)) { + my_pm->private_ip_users_count++; +#ifdef DEBUG_PRINTF_IP_N_TO_1_ENABLED + PLATFORM_DEBUG_PRINT("\n cnat_get_main_db_entry_v2 " + "dynamic alloc private_ip_users_count = %d", + my_pm->private_ip_users_count); +#endif + } else { + PLATFORM_DEBUG_PRINT("\n ERROR: private_ip_users_count has " + "reached MAX PORTS_PER_ADDR"); + } +#ifndef NO_BULK_LOGGING + if(PREDICT_TRUE(udb && (BULK_ALLOC_NOT_ATTEMPTED != nfv9_log_req))) { + cnat_update_bulk_range_cache(udb, ko.k.k.port, + BULKSIZE_FROM_VRFMAP(my_vrfmap)); + } +#endif /* #ifndef NO_BULK_LOGGING */ + + } + + /* + * step 3: + * outside port is allocated for this src vrf/src ip addr + * 1)create a new entry in main db + * 2)setup cnat_out2in_hash key + * 3)setup cnat_in2out_hash key + */ + db = cnat_create_main_db_entry_and_hash(ki, &ko, udb); + + translation_create_count ++; +#ifdef DSLITE_DEF + db->dslite_nat44_inst_id = NAT44_RESERVED_INST_ID; +#endif + db->vrfmap_index = my_vrfmap - cnat_map_by_vrf; + + /* + * don't forget logging + * logging API is unconditional, + * logging configuration check is done inside the inline function + */ + + db->dst_ipv4 = dest_info->k.ipv4; + db->dst_port = dest_info->k.port; + if(PREDICT_TRUE(db->dst_ipv4 || db->dst_port)) { + db->nsessions++; + } + + if(PREDICT_FALSE(nfv9_log_req != CACHE_ALLOC_NO_LOG_REQUIRED)) { + if(PREDICT_FALSE(my_vrfmap->nf_logging_policy == SESSION_LOG_ENABLE)) { + /* do not log for static entries.. we will log when traffic flows */ + if(PREDICT_TRUE(db->dst_ipv4 || db->dst_port)) { + cnat_nfv9_nat44_log_session_create(db, 0, my_vrfmap); + } + } else { + cnat_nfv9_log_mapping_create(db, my_vrfmap +#ifndef NO_BULK_LOGGING + , nfv9_log_req +#endif + ); + } + if(PREDICT_TRUE((my_vrfmap->syslog_logging_policy != SESSION_LOG_ENABLE) || + (db->dst_ipv4 || db->dst_port))) { + cnat_syslog_nat44_mapping_create(db, my_vrfmap, 0 +#ifndef NO_BULK_LOGGING + , nfv9_log_req +#endif + ); + } + } + if (PREDICT_FALSE(port_pair_type == PORT_PAIR)) { + cnat_main_db_entry_t *db2 = 0; + cnat_db_key_bucket_t new_ki = *ki; + u64 a, b, c; + + new_ki.k.k.port += 1; + ko.k.k.port += 1; + + CNAT_V4_GET_HASH(new_ki.k.key64, new_ki.bucket, + CNAT_MAIN_HASH_MASK); + + db2 = cnat_create_main_db_entry_and_hash(&new_ki, &ko, udb); + + translation_create_count ++; +#ifdef DSLITE_DEF + db2->dslite_nat44_inst_id = NAT44_RESERVED_INST_ID; +#endif + db2->vrfmap_index = my_vrfmap - cnat_map_by_vrf; + db2->entry_expires = cnat_current_time; + db2->flags |= CNAT_DB_FLAG_ALG_ENTRY; + pthread_spin_lock(cnat_db_v2_main.user_db_lockp); + udb->ntranslations += 1; + pthread_spin_unlock(cnat_db_v2_main.user_db_lockp); + db2->dst_ipv4 = dest_info->k.ipv4; + db2->dst_port = dest_info->k.port; + db2->nsessions = 0; /* For ALG db, set sessions to 0 - CSCuf78420 */ + + if(PREDICT_FALSE(nfv9_log_req != CACHE_ALLOC_NO_LOG_REQUIRED)) { + if(PREDICT_FALSE(my_vrfmap->nf_logging_policy == SESSION_LOG_ENABLE)) { + /* do not log for static entries.. we will log when traffic flows */ + if(PREDICT_TRUE(db2->dst_ipv4 || db2->dst_port)) { + cnat_nfv9_nat44_log_session_create(db2, 0, my_vrfmap); + } + } else { + cnat_nfv9_log_mapping_create(db2, my_vrfmap +#ifndef NO_BULK_LOGGING + , nfv9_log_req +#endif + ); + } + if(PREDICT_TRUE((my_vrfmap->syslog_logging_policy != SESSION_LOG_ENABLE) || + (db2->dst_ipv4 || db2->dst_port))) { + cnat_syslog_nat44_mapping_create(db2, my_vrfmap, 0 +#ifndef NO_BULK_LOGGING + , nfv9_log_req +#endif + ); + } + } + } + + return db; +} + +cnat_main_db_entry_t* +cnat_get_main_db_entry_v2(cnat_db_key_bucket_t *ki, + port_pair_t port_pair_type, + port_type_t port_type, + cnat_gen_icmp_info *info, + cnat_key_t *dest_info) +{ + + cnat_main_db_entry_t *db; + pthread_spin_lock(cnat_db_v2_main.main_db_lockp); + db = _cnat_get_main_db_entry_v2(ki, port_pair_type, + port_type, info, dest_info); + pthread_spin_unlock(cnat_db_v2_main.main_db_lockp); + return db; +} + +/* + * this function is called from config handler only + * to allocate a static port based db entry + * + * the actual mapped address and port are already specified + */ +cnat_main_db_entry_t* +cnat_create_static_main_db_entry_v2 (cnat_db_key_bucket_t *ki, + cnat_db_key_bucket_t *ko, + cnat_vrfmap_t *my_vrfmap, + cnat_gen_icmp_info *info) +{ + u16 protocol; + u32 head; + cnat_errno_t rv; + cnat_db_key_bucket_t u_ki; + u32 my_index, free_main, free_user; + cnat_portmap_v2_t *pm =0; + cnat_portmap_v2_t *my_pm =0; + cnat_user_db_entry_t *udb = 0; + cnat_main_db_entry_t *db = 0; + pool_header_t *h; +#ifndef NO_BULK_LOGGING + int nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED; +#endif + + /* UNUSED. Therefore not ported to be multi-thread friendly */ + ASSERT(0); + + /* + * need to try lookup again because + * second pkt may come here before the entry is created + * by receiving first pkt due to high line rate. + */ + info->gen_icmp_msg = CNAT_NO_ICMP_MSG; + info->error = CNAT_SUCCESS; + db = cnat_main_db_lookup_entry(ki); + + /* + * If we already have an entry with this inside address, port + * check delete the entry and proceed further. This should + * If yes, something is terribly wrong. Bail out + */ + if (PREDICT_FALSE(db)) { + + if (db->flags & CNAT_DB_FLAG_STATIC_PORT) { + + if ((db->out2in_key.k.ipv4 == ko->k.k.ipv4) && + (db->out2in_key.k.port == ko->k.k.port) && + (db->out2in_key.k.vrf == ko->k.k.vrf)) { + +#ifdef DEBUG_PRINTF_ENABLED + printf("Same Static Port Exists ki 0x%16llx ko 0x%16llx", + ki->k, ko->k); +#endif + /* + * We have already programmed this, return + */ + return (db); + } + + /* + * We already have a static port with different mapping + * Return an error for this case. + */ + info->error = CNAT_ERR_PARSER; + +#ifdef DEBUG_PRINTF_ENABLED + printf("Static Port Existing and Diff ki 0x%16llx ko 0x%16llx", + ki, db->out2in_key); +#endif + { + u32 arr[] = {STAT_PORT_CONFIG_IN_USE, (ki->k.k.vrf & CNAT_VRF_MASK), + ki->k.k.ipv4, ki->k.k.port, (ki->k.k.vrf & CNAT_PRO_MASK) }; + spp_printf(CNAT_CONFIG_ERROR, 5, arr); + } + return (db); + } + +#ifdef DEBUG_PRINTF_ENABLED + printf("Deleting Dynamic entry ki 0x%16llx ko 0x%16llx", + ki, db->out2in_key); +#endif + + /* + * If for some reason we have dynamic entries, just delete them + * and proceed. + */ + cnat_delete_main_db_entry_v2(db); + + db = NULL; + } + + protocol = ki->k.k.vrf & CNAT_PRO_MASK; + u_ki.k.k.vrf = ki->k.k.vrf & CNAT_VRF_MASK; + u_ki.k.k.ipv4 = ki->k.k.ipv4; + u_ki.k.k.port = 0; + + pm = my_vrfmap->portmap_list; + + /* + * check if src vrf, src ip addr is already + * in the user db + * if yes, use PORT_ALLOC_DIRECTED + * if no, use PORT_ALLOC_ANY since it is first time + */ + udb = cnat_user_db_lookup_entry(&u_ki); + if (PREDICT_TRUE(udb)) { + /* + * check if main db has space to accomodate new entry + */ + h = pool_header(cnat_main_db); + + free_main = vec_len(h->free_indices) - 1; + if (PREDICT_FALSE(!free_main)) { + info->error = CNAT_MAIN_DB_LIMIT; + CNAT_SET_ICMP_MSG_INFO + in2out_drops_system_limit_reached ++; + CNAT_DEBUG_INSIDE_ERR(CNAT_MAIN_DB_LIMIT) +#ifdef UT_TEST_CODE + printf("Limit reached : OLD USER"); +#endif + spp_printf(CNAT_MAIN_DB_LIMIT_ERROR, 0, 0); + return NULL; + } + + /* + * allocate port, from existing mapping + */ + my_index = udb->portmap_index; + my_pm = pm + my_index; + /* It is quite possible that we hit the scenario of CSCtj17774. + * Delete all the main db entries and add the ipv4 address sent by + * CGN-MA as Static port alloc any + */ + + if (PREDICT_FALSE(my_pm->ipv4_address != ko->k.k.ipv4)) { + if (PREDICT_FALSE(global_debug_flag && CNAT_DEBUG_GLOBAL_ALL)) { + printf("Delete Main db entry and check for" + " ipv4 address sanity pm add = 0x%x ip add = 0x%x\n", + my_pm->ipv4_address, ko->k.k.ipv4); + } + do { + /* udb is not NULL when we begin with for sure */ + head = udb->translation_list_head_index; + db = cnat_main_db + head; + cnat_delete_main_db_entry_v2(db); + } while (!pool_is_free(cnat_user_db, udb)); + + rv = cnat_mapped_static_port_alloc_v2_bulk (pm, + PORT_ALLOC_ANY, &my_index, ko->k.k.ipv4, ko->k.k.port, + udb, BULKSIZE_FROM_VRFMAP(my_vrfmap), &nfv9_log_req, + my_vrfmap->ip_n_to_1); + + if (PREDICT_FALSE(rv != CNAT_SUCCESS)) { + info->error = rv; + in2out_drops_resource_depletion ++; + CNAT_SET_ICMP_MSG_INFO + CNAT_DEBUG_INSIDE_ERR(rv) + return (NULL); + } + /* + * create entry in user db + */ + udb = cnat_user_db_create_entry(&u_ki, my_index); + my_pm = pm + my_index; + if(PREDICT_TRUE(my_pm->private_ip_users_count < PORTS_PER_ADDR)) { + my_pm->private_ip_users_count++; +#ifdef DEBUG_PRINTF_IP_N_TO_1_ENABLED + PLATFORM_DEBUG_PRINT("\n cnat_create_static_main_db_entry_v2 " + "static del n alloc private_ip_users_count = " + "%d",my_pm->private_ip_users_count); +#endif + } else { + PLATFORM_DEBUG_PRINT("\n ERROR: private_ip_users_count has " + "reached MAX PORTS_PER_ADDR"); + } + NAT44_COMMON_STATS.num_subscribers++; +#ifndef NO_BULK_LOGGING + cnat_update_bulk_range_cache(udb, ko->k.k.port, + BULKSIZE_FROM_VRFMAP(my_vrfmap)); +#endif /* #ifndef NO_BULK_LOGGING */ + } else { + + rv = cnat_mapped_static_port_alloc_v2_bulk (pm, + PORT_ALLOC_DIRECTED, &my_index, ko->k.k.ipv4, ko->k.k.port, + udb, BULKSIZE_FROM_VRFMAP(my_vrfmap), &nfv9_log_req, + my_vrfmap->ip_n_to_1); + + if (PREDICT_FALSE(rv != CNAT_SUCCESS)) { + info->error = rv; + CNAT_SET_ICMP_MSG_INFO + CNAT_DEBUG_INSIDE_ERR(rv) + log_port_alloc_error(rv, &(ki->k)); + return (NULL); + } + + /* + * increment port in use for this user + */ + udb->ntranslations += 1; + } + } else { + if (PREDICT_FALSE(global_debug_flag && CNAT_DEBUG_GLOBAL_ALL)) { + printf ("Static port alloc any\n"); + } + /* + * first time allocate port for this user + */ + + /* + * Check if main db has space for new entry + * Allowing a user db entry to be created if main db is not free + * will cause a port to be allocated to that user, which results in + * wastage of that port, hence the check is done here. + */ + h = pool_header(cnat_main_db); + free_main = vec_len(h->free_indices) - 1; + h = pool_header(cnat_user_db); + free_user = vec_len(h->free_indices) - 1; + + /* + * If either main_db or user_db does not have entries + * bail out, with appropriate error + */ + if (PREDICT_FALSE(!(free_main && free_user))) { + u32 log_error; + if(free_main) { + info->error = CNAT_USER_DB_LIMIT; + log_error = CNAT_USER_DB_LIMIT_ERROR; + } else { + info->error = CNAT_MAIN_DB_LIMIT; + log_error = CNAT_MAIN_DB_LIMIT_ERROR; + } + in2out_drops_system_limit_reached ++; + CNAT_SET_ICMP_MSG_INFO + CNAT_DEBUG_INSIDE_ERR(info->error) + spp_printf(log_error, 0, 0); + return NULL; + } + + rv = cnat_mapped_static_port_alloc_v2_bulk (pm, + PORT_ALLOC_ANY, &my_index, ko->k.k.ipv4, ko->k.k.port, + udb, BULKSIZE_FROM_VRFMAP(my_vrfmap), &nfv9_log_req, + my_vrfmap->ip_n_to_1); + + if (PREDICT_FALSE(rv != CNAT_SUCCESS)) { + info->error = rv; + in2out_drops_resource_depletion ++; + CNAT_SET_ICMP_MSG_INFO + CNAT_DEBUG_INSIDE_ERR(rv) + log_port_alloc_error(rv, &(ki->k)); + return (NULL); + } + /* + * create entry in user db + */ + udb = cnat_user_db_create_entry(&u_ki, my_index); + my_pm = pm + my_index; + if(PREDICT_TRUE(my_pm->private_ip_users_count < PORTS_PER_ADDR)) { + my_pm->private_ip_users_count++; +#ifdef DEBUG_PRINTF_IP_N_TO_1_ENABLED + PLATFORM_DEBUG_PRINT("\n cnat_create_static_main_db_entry_v2 " + "static alloc private_ip_users_count = %d", + my_pm->private_ip_users_count); +#endif + } else { + PLATFORM_DEBUG_PRINT("\n ERROR: private_ip_users_count has " + "reached MAX PORTS_PER_ADDR"); + } + NAT44_COMMON_STATS.num_subscribers++; +#ifndef NO_BULK_LOGGING + cnat_update_bulk_range_cache(udb, ko->k.k.port, + BULKSIZE_FROM_VRFMAP(my_vrfmap)); +#endif /* #ifndef NO_BULK_LOGGING */ + } + + /* + * step 3: + * outside port is allocated for this src vrf/src ip addr + * 1)create a new entry in main db + * 2)setup cnat_out2in_hash key + * 3)setup cnat_in2out_hash key + */ + db = cnat_create_main_db_entry_and_hash(ki, ko, udb); + + translation_create_count ++; + db->vrfmap_index = my_vrfmap - cnat_map_by_vrf; + + /* + * don't forget logging + * logging API is unconditional, + * logging configuration check is done inside the inline function + */ + + if(PREDICT_FALSE(nfv9_log_req != CACHE_ALLOC_NO_LOG_REQUIRED)) { + /* if session logging is enabled .. do not log as there is no + * traffic yet + */ + if(PREDICT_FALSE(my_vrfmap->nf_logging_policy != SESSION_LOG_ENABLE)) { + cnat_nfv9_log_mapping_create(db, my_vrfmap +#ifndef NO_BULK_LOGGING + , nfv9_log_req +#endif + ); + } + if(PREDICT_FALSE(my_vrfmap->syslog_logging_policy != SESSION_LOG_ENABLE)) { + cnat_syslog_nat44_mapping_create(db, my_vrfmap, 0 +#ifndef NO_BULK_LOGGING + , nfv9_log_req +#endif + ); + } + } + + return db; +} + + +cnat_main_db_entry_t* +dslite_main_db_lookup_entry(dslite_db_key_bucket_t *ki); + +cnat_user_db_entry_t* +dslite_user_db_lookup_entry(dslite_db_key_bucket_t *uki); + +cnat_user_db_entry_t* +dslite_user_db_create_entry(dslite_db_key_bucket_t *uki, u32 portmap_index); + +cnat_main_db_entry_t* +dslite_create_main_db_entry_and_hash(dslite_db_key_bucket_t *ki, + cnat_db_key_bucket_t *ko, + cnat_user_db_entry_t *udb); + +#ifdef TOBE_PORTED +/* + * this function is called from config handler only + * to allocate a static port based db entry + * + * the actual mapped address and port are already specified + */ +cnat_main_db_entry_t* +dslite_create_static_main_db_entry_v2 (dslite_db_key_bucket_t *ki, + cnat_db_key_bucket_t *ko, + dslite_table_entry_t *dslite_entry_ptr, + cnat_gen_icmp_info *info) +{ + u16 protocol; + u32 head; + cnat_errno_t rv; + dslite_db_key_bucket_t u_ki; + u32 my_index, free_main, free_user; + cnat_portmap_v2_t *pm =0; + cnat_portmap_v2_t *my_pm =0; + cnat_user_db_entry_t *udb = 0; + cnat_main_db_entry_t *db = 0; + pool_header_t *h; + u16 dslite_id = dslite_entry_ptr->dslite_id; +#ifndef NO_BULK_LOGGING + int nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED; +#endif + cnat_vrfmap_t *my_vrfmap =0; + u16 my_vrfmap_index; + + /* UNUSED. Therefore not ported to be multi-thread friendly */ + ASSERT(0); + /* + * need to try lookup again because + * second pkt may come here before the entry is created + * by receiving first pkt due to high line rate. + */ + info->gen_icmp_msg = CNAT_NO_ICMP_MSG; + info->error = CNAT_SUCCESS; + db = dslite_main_db_lookup_entry(ki); + + /* + * If we already have an entry with this inside address, port + * check delete the entry and proceed further. This should + * If yes, something is terribly wrong. Bail out + */ + if (PREDICT_FALSE(db)) { + + if (db->flags & CNAT_DB_FLAG_STATIC_PORT) { + + if ((db->out2in_key.k.ipv4 == ko->k.k.ipv4) && + (db->out2in_key.k.port == ko->k.k.port) && + (db->out2in_key.k.vrf == ko->k.k.vrf)) { + +#ifdef DEBUG_PRINTF_ENABLED + printf("Same Static Port Exists ki 0x%16llx ko 0x%16llx", + ki->k, ko->k); +#endif + /* + * We have already programmed this, return + */ + return (db); + } + + /* + * We already have a static port with different mapping + * Return an error for this case. + */ + info->error = CNAT_ERR_PARSER; + +#ifdef DEBUG_PRINTF_ENABLED + printf("Static Port Existing and Diff ki 0x%16llx ko 0x%16llx", + ki, db->out2in_key); +#endif + { + u32 arr[] = {STAT_PORT_CONFIG_IN_USE, (ki->dk.ipv4_key.k.vrf & CNAT_VRF_MASK), + ki->dk.ipv4_key.k.ipv4, ki->dk.ipv4_key.k.port, (ki->dk.ipv4_key.k.vrf & CNAT_PRO_MASK) }; + spp_printf(CNAT_CONFIG_ERROR, 5, arr); + } + return (db); + } + +#ifdef DEBUG_PRINTF_ENABLED + printf("Deleting Dynamic entry ki 0x%16llx ko 0x%16llx", + ki, db->out2in_key); +#endif + + /* + * If for some reason we have dynamic entries, just delete them + * and proceed. + */ + cnat_delete_main_db_entry_v2(db); + + db = NULL; + } + + + protocol = ki->dk.ipv4_key.k.vrf & CNAT_PRO_MASK; + u_ki.dk.ipv4_key.k.vrf = ki->dk.ipv4_key.k.vrf & CNAT_VRF_MASK; + u_ki.dk.ipv4_key.k.ipv4 = ki->dk.ipv4_key.k.ipv4; + u_ki.dk.ipv4_key.k.port = 0; + u_ki.dk.ipv6[0] = ki->dk.ipv6[0]; + u_ki.dk.ipv6[1] = ki->dk.ipv6[1]; + u_ki.dk.ipv6[2] = ki->dk.ipv6[2]; + u_ki.dk.ipv6[3] = ki->dk.ipv6[3]; + + my_vrfmap_index = vrf_map_array[u_ki.dk.ipv4_key.k.vrf]; + my_vrfmap = cnat_map_by_vrf + my_vrfmap_index; + + pm = dslite_entry_ptr->portmap_list; + + /* + * check if src vrf, src ip addr is already + * in the user db + * if yes, use PORT_ALLOC_DIRECTED + * if no, use PORT_ALLOC_ANY since it is first time + */ + udb = dslite_user_db_lookup_entry(&u_ki); + if (PREDICT_TRUE(udb)) { + /* + * check if main db has space to accomodate new entry + */ + h = pool_header(cnat_main_db); + + free_main = vec_len(h->free_indices) - 1; + if (PREDICT_FALSE(!free_main)) { + info->error = CNAT_MAIN_DB_LIMIT; + nat44_dslite_common_stats[dslite_id].in2out_drops_port_limit_exceeded ++; + DSLITE_DEBUG_INSIDE_ERR(CNAT_MAIN_DB_LIMIT) +#ifdef UT_TEST_CODE + printf("Limit reached : OLD USER"); +#endif + spp_printf(CNAT_MAIN_DB_LIMIT_ERROR, 0, 0); + return NULL; + } + + /* + * allocate port, from existing mapping + */ + my_index = udb->portmap_index; + my_pm = pm + my_index; + /* It is quite possible that we hit the scenario of CSCtj17774. + * Delete all the main db entries and add the ipv4 address sent by + * CGN-MA as Static port alloc any + */ + + if (PREDICT_FALSE(my_pm->ipv4_address != ko->k.k.ipv4)) { + if (PREDICT_FALSE(global_debug_flag && CNAT_DEBUG_GLOBAL_ALL)) { + printf("Delete Main db entry and check for" + " ipv4 address sanity pm add = 0x%x ip add = 0x%x\n", + my_pm->ipv4_address, ko->k.k.ipv4); + } + do { + /* udb is not NULL when we begin with for sure */ + head = udb->translation_list_head_index; + db = cnat_main_db + head; + cnat_delete_main_db_entry_v2(db); + } while (!pool_is_free(cnat_user_db, udb)); + + rv = cnat_mapped_static_port_alloc_v2_bulk (pm, + PORT_ALLOC_ANY, &my_index, ko->k.k.ipv4, ko->k.k.port, + udb, BULKSIZE_FROM_VRFMAP(dslite_entry_ptr), &nfv9_log_req, + my_vrfmap->ip_n_to_1); + + if (PREDICT_FALSE(rv != CNAT_SUCCESS)) { + info->error = rv; + nat44_dslite_common_stats[dslite_id].in2out_drops_port_limit_exceeded ++; + DSLITE_DEBUG_INSIDE_ERR(rv) + return (NULL); + } + /* + * create entry in user db + */ + udb = dslite_user_db_create_entry(&u_ki, my_index); + nat44_dslite_common_stats[dslite_id].num_subscribers++; +#ifndef NO_BULK_LOGGING + if(PREDICT_FALSE(udb && (BULK_ALLOC_NOT_ATTEMPTED != nfv9_log_req))) { + cnat_update_bulk_range_cache(udb, ko->k.k.port, + BULKSIZE_FROM_VRFMAP(dslite_entry_ptr)); + } +#endif /* #ifndef NO_BULK_LOGGING */ + } else { + + rv = cnat_mapped_static_port_alloc_v2_bulk (pm, + PORT_ALLOC_DIRECTED, &my_index, ko->k.k.ipv4, ko->k.k.port, + udb, BULKSIZE_FROM_VRFMAP(dslite_entry_ptr), &nfv9_log_req, + my_vrfmap->ip_n_to_1); + + if (PREDICT_FALSE(rv != CNAT_SUCCESS)) { + info->error = rv; + DSLITE_DEBUG_INSIDE_ERR(rv) + log_port_alloc_error(rv, &(ki->dk.ipv4_key)); + return (NULL); + } + + /* + * increment port in use for this user + */ + udb->ntranslations += 1; + } + } else { + if (PREDICT_FALSE(global_debug_flag && CNAT_DEBUG_GLOBAL_ALL)) { + printf ("Static port alloc any\n"); + } + /* + * first time allocate port for this user + */ + + /* + * Check if main db has space for new entry + * Allowing a user db entry to be created if main db is not free + * will cause a port to be allocated to that user, which results in + * wastage of that port, hence the check is done here. + */ + h = pool_header(cnat_main_db); + free_main = vec_len(h->free_indices) - 1; + h = pool_header(cnat_user_db); + free_user = vec_len(h->free_indices) - 1; + + /* + * If either main_db or user_db does not have entries + * bail out, with appropriate error + */ + if (PREDICT_FALSE(!(free_main && free_user))) { + u32 log_error; + if(free_main) { + info->error = CNAT_USER_DB_LIMIT; + log_error = CNAT_USER_DB_LIMIT_ERROR; + } else { + info->error = CNAT_MAIN_DB_LIMIT; + log_error = CNAT_MAIN_DB_LIMIT_ERROR; + } + nat44_dslite_common_stats[dslite_id].in2out_drops_port_limit_exceeded ++; + DSLITE_DEBUG_INSIDE_ERR(info->error) + spp_printf(log_error, 0, 0); + return NULL; + } + + rv = cnat_mapped_static_port_alloc_v2_bulk (pm, + PORT_ALLOC_ANY, &my_index, ko->k.k.ipv4, ko->k.k.port, + udb, BULKSIZE_FROM_VRFMAP(dslite_entry_ptr), &nfv9_log_req, + my_vrfmap->ip_n_to_1); + + if (PREDICT_FALSE(rv != CNAT_SUCCESS)) { + info->error = rv; + nat44_dslite_common_stats[dslite_id].in2out_drops_port_limit_exceeded ++; + DSLITE_DEBUG_INSIDE_ERR(rv) + log_port_alloc_error(rv, &(ki->dk.ipv4_key)); + return (NULL); + } + /* + * create entry in user db + */ + udb = dslite_user_db_create_entry(&u_ki, my_index); + nat44_dslite_common_stats[dslite_id].num_subscribers++; +#ifndef NO_BULK_LOGGING + if(PREDICT_FALSE(udb && (BULK_ALLOC_NOT_ATTEMPTED != nfv9_log_req))) { + cnat_update_bulk_range_cache(udb, ko->k.k.port, + BULKSIZE_FROM_VRFMAP(dslite_entry_ptr)); + } +#endif /* #ifndef NO_BULK_LOGGING */ + } + + /* + * step 3: + * outside port is allocated for this src vrf/src ip addr + * 1)create a new entry in main db + * 2)setup cnat_out2in_hash key + * 3)setup cnat_in2out_hash key + */ + db = dslite_create_main_db_entry_and_hash(ki, ko, udb); + db->dslite_nat44_inst_id = dslite_id; + nat44_dslite_common_stats[dslite_id].active_translations++; + dslite_translation_create_count++; + + /* + * don't forget logging + * logging API is unconditional, + * logging configuration check is done inside the inline function + */ +#if 0 /* TBD - NEED TO DECIDE ON LOGGING */ + if(PREDICT_FALSE(nfv9_log_req != CACHE_ALLOC_NO_LOG_REQUIRED)) { + /* if session logging is enabled .. do not log as there is no + * traffic yet + */ +#endif /* #if 0 - this has to be removed later */ + + return db; +} +#endif /* TOBE_PORTED */ + + +/* Per port/ip timeout related routines */ +static +u32 cnat_timeout_db_hash_lookup (cnat_key_t t_key) +{ + cnat_key_t key; + u64 a, b, c; + u32 index; + cnat_timeout_db_entry_t *db; + + key.k.ipv4 = t_key.k.ipv4; + key.k.port = t_key.k.port; + key.k.vrf = t_key.k.vrf; + + CNAT_V4_GET_HASH(key.key64, + index, CNAT_TIMEOUT_HASH_MASK) + + + index = cnat_timeout_hash[index].next; + + if (PREDICT_FALSE(index == EMPTY)) + return EMPTY; + + do { + db = cnat_timeout_db + index; + if (PREDICT_TRUE((db->t_key.timeout_key.key64 & CNAT_TIMEOUT_FULL_MASK) + == (key.key64 & CNAT_TIMEOUT_FULL_MASK))) + break; + index = db->t_hash.next; + } while (index != EMPTY); + + return index; +} + +/* Pass db_type as MAIN_DB_TYPE if you are passing + * cnat_main_db_entry_t * casted as void * for db + * else pass db_type as SESSION_DB_TYPE + */ +u16 +query_and_update_db_timeout(void *db, u8 db_type) +{ + cnat_key_t t_search_key; + u32 index; + cnat_timeout_db_entry_t *timeout_db_entry; + pool_header_t *h; + u32 free; + + cnat_main_db_entry_t *mdb = NULL; + cnat_session_entry_t *sdb = NULL; + + if(PREDICT_TRUE(db_type == MAIN_DB_TYPE)) { + mdb = (cnat_main_db_entry_t *)db; + } else if(db_type == SESSION_DB_TYPE) { + sdb = (cnat_session_entry_t *)db; + } else { + return 0; + } + + h = pool_header(cnat_timeout_db); + free = vec_len(h->free_indices) - 1; + + if(free == CNAT_TIMEOUT_HASH_SIZE) { + /* No timeout db configured */ + return 0; + } + + /* First search for ip/port pair */ + if(PREDICT_TRUE(db_type == MAIN_DB_TYPE)) { + t_search_key.k.ipv4 = mdb->dst_ipv4; + t_search_key.k.port = mdb->dst_port; + t_search_key.k.vrf = mdb->in2out_key.k.vrf; + } else { + t_search_key.k.ipv4 = sdb->v4_dest_key.k.ipv4; + t_search_key.k.port = sdb->v4_dest_key.k.port; + t_search_key.k.vrf = sdb->v4_dest_key.k.vrf; + } + + index = cnat_timeout_db_hash_lookup(t_search_key); + + if(index == EMPTY) { + /* Search for port map */ + t_search_key.k.ipv4 = 0; + + index = cnat_timeout_db_hash_lookup(t_search_key); + + if(index == EMPTY) { + /* Search for ip only map */ + if(PREDICT_TRUE(db_type == MAIN_DB_TYPE)) { + t_search_key.k.ipv4 = mdb->dst_ipv4; + } else { + t_search_key.k.ipv4 = sdb->v4_dest_key.k.ipv4; + } + t_search_key.k.port = 0; + + index = cnat_timeout_db_hash_lookup(t_search_key); + if(index != EMPTY) { +#ifdef DEBUG_PRINTF_ENABLED + printf("%s: ip only map sucess\n","query_and_update_db_timeout"); +#endif + } + } else { +#ifdef DEBUG_PRINTF_ENABLED + printf("%s: port only map sucess\n", "query_and_update_db_timeout"); +#endif + } + + } else { +#ifdef DEBUG_PRINTF_ENABLED + printf("%s: ip port map sucess\n","query_and_update_db_timeout"); +#endif + + } + + if(index == EMPTY) { + /* No match found, clear timeout */ + if(PREDICT_TRUE(db_type == MAIN_DB_TYPE)) { + mdb->timeout = 0; + } else { + sdb->timeout = 0; + } +#ifdef DEBUG_PRINTF_ENABLED + printf("%s: No match\n","query_and_update_db_timeout"); +#endif + } else { + /* Match found, update timeout */ + timeout_db_entry = cnat_timeout_db + index; + if(PREDICT_TRUE(db_type == MAIN_DB_TYPE)) { + mdb->timeout = timeout_db_entry->t_key.timeout_value; + } else { + sdb->timeout = timeout_db_entry->t_key.timeout_value; + } + return timeout_db_entry->t_key.timeout_value; + } + return 0; +} + + + +static +void cnat_timeout_db_hash_add (cnat_timeout_db_entry_t *t_entry) +{ + cnat_key_t key; + u64 a, b, c; + u32 index, bucket; + cnat_key_t t_key = t_entry->t_key.timeout_key; + + key.k.ipv4 = t_key.k.ipv4; + key.k.port = t_key.k.port; + key.k.vrf = t_key.k.vrf; + + CNAT_V4_GET_HASH(key.key64, + bucket, CNAT_TIMEOUT_HASH_MASK) + + + index = cnat_timeout_hash[bucket].next; + + /* Add this db entry to the head of the bucket chain */ + t_entry->t_hash.next = index; + cnat_timeout_hash[bucket].next = t_entry - cnat_timeout_db; +} + + + +u16 +cnat_timeout_db_create (cnat_timeout_t t_entry) +{ + cnat_timeout_db_entry_t *db; + cnat_key_t t_key = t_entry.timeout_key; + u32 db_index; + + pool_header_t *h; + u32 free; + + /* UNUSED. Therefore not ported to be multi-thread friendly */ + ASSERT(0); + + db_index = cnat_timeout_db_hash_lookup(t_key); + + if(db_index != EMPTY) { + /* Entry already exists. Check if it is replay or update */ + db = cnat_timeout_db + db_index; + db->t_key.timeout_value = t_entry.timeout_value; + return CNAT_SUCCESS; + } + + h = pool_header(cnat_timeout_db); + free = vec_len(h->free_indices) - 1; + + if(free == 0) { + return CNAT_OUT_LIMIT; + } + + + pool_get(cnat_timeout_db, db); + ASSERT(db); + + memset(db, 0, sizeof(*db)); + + db_index = db - cnat_timeout_db; + + db->t_key.timeout_key.k.ipv4 = t_key.k.ipv4; + db->t_key.timeout_key.k.port = t_key.k.port; + db->t_key.timeout_key.k.vrf = t_key.k.vrf; + db->t_key.timeout_value = t_entry.timeout_value; + + + cnat_timeout_db_hash_add(db); + return CNAT_SUCCESS; +} + +void cnat_timeout_db_delete(cnat_key_t t_key) +{ + cnat_key_t key; + u64 a, b, c; + u32 index, bucket; + cnat_timeout_db_entry_t *this, *prev; + + /* UNUSED. Therefore not ported to be multi-thread friendly */ + ASSERT(0); + + key.k.ipv4 = t_key.k.ipv4; + key.k.port = t_key.k.port; + key.k.vrf = t_key.k.vrf; + + + CNAT_V4_GET_HASH(key.key64, + bucket, CNAT_TIMEOUT_HASH_MASK) + + + index = cnat_timeout_hash[bucket].next; + + if(index == EMPTY) return; + + prev = 0; + do { + this = cnat_timeout_db + index; + if (PREDICT_TRUE( + (this->t_key.timeout_key.key64 & CNAT_TIMEOUT_FULL_MASK) == + (key.key64 & CNAT_TIMEOUT_FULL_MASK))) { + if (prev == 0) { + cnat_timeout_hash[bucket].next = this->t_hash.next; + goto found; + } else { + prev->t_hash.next = this->t_hash.next; + goto found; + } + } + + prev = this; + index = this->t_hash.next; + } while (index != EMPTY); + + if(index == EMPTY) return; + + found: + pool_put(cnat_timeout_db, this); + +} + +void cnat_session_db_hash_delete (cnat_session_entry_t *ep) +{ + u32 a, b, c; + u32 index, bucket; + cnat_session_entry_t *this, *prev; + + CNAT_V4_GET_SESSION_HASH(ep->main_db_index, ep->v4_dest_key.k.ipv4, + ep->v4_dest_key.k.port, ep->v4_dest_key.k.vrf, bucket, + CNAT_SESSION_HASH_MASK) + + + index = cnat_session_hash[bucket].next; + + ASSERT(index != EMPTY); + + prev = 0; + do { + this = cnat_session_db + index; + if (PREDICT_TRUE(this == ep)) { + if (prev == 0) { + cnat_session_hash[bucket].next = + ep->cnat_session_hash.next; + return; + } else { + prev->cnat_session_hash.next = + ep->cnat_session_hash.next; + return; + } + } + prev = this; + index = this->cnat_session_hash.next; + } while (index != EMPTY); + + ASSERT(0); + +} + +cnat_session_entry_t * +cnat_session_db_edm_lookup_entry(cnat_key_t *ko,u32 session_head_index, + u32 main_db_index) +{ + u32 index; + cnat_session_entry_t *db; + + + index = session_head_index; + if (PREDICT_TRUE(index == EMPTY)) { + return (NULL); + } + + do { + db = cnat_session_db + index; + if(PREDICT_TRUE((db->main_db_index == main_db_index) && + (db->v4_dest_key.k.vrf == ko->k.vrf) && + (db->v4_dest_key.k.ipv4 == ko->k.ipv4))) { + + return db; + } + index = db->cnat_session_hash.next; + } while (index != EMPTY); + + return (NULL); +} + + + +cnat_session_entry_t * +cnat_session_db_lookup_entry(cnat_key_t *ko,u32 main_db_index) +{ + u32 a, b, c; + u32 index, bucket; + cnat_session_entry_t *db; + + CNAT_V4_GET_SESSION_HASH(main_db_index, ko->k.ipv4, ko->k.port, + ko->k.vrf, bucket, CNAT_SESSION_HASH_MASK) + + + index = cnat_session_hash[bucket].next; + if (PREDICT_TRUE(index == EMPTY)) { + return (NULL); + } + + do { + db = cnat_session_db + index; + if(PREDICT_TRUE((db->main_db_index == main_db_index) && + (db->v4_dest_key.k.vrf == ko->k.vrf) && + (db->v4_dest_key.k.port == ko->k.port) && + (db->v4_dest_key.k.ipv4 == ko->k.ipv4))) { + + return db; + } + index = db->cnat_session_hash.next; + } while (index != EMPTY); + + return (NULL); +} + +cnat_session_entry_t * +cnat_create_session_db_entry(cnat_key_t *ko, + cnat_main_db_entry_t *bdb, u8 log) +{ + u32 a, b, c; + u32 db_index, bucket_out; + cnat_session_entry_t *db = NULL; + pool_header_t *h; + u32 free_session; + u16 instance; + + db = cnat_session_db_lookup_entry(ko, bdb - cnat_main_db); + if (PREDICT_FALSE(db != NULL)) { + /*printf("Create Session - Entry already Exists\n");*/ + return db; + } + + h = pool_header(cnat_session_db); + free_session = vec_len(h->free_indices) - 1; + + if (bdb->flags & CNAT_DB_DSLITE_FLAG) { + instance = bdb->dslite_nat44_inst_id; + } else { + instance = NAT44_RESERVED_INST_ID; + } + + if (PREDICT_FALSE(!free_session)) { + nat44_dslite_common_stats[instance].drops_sessiondb_limit_exceeded++; + return NULL; + } + + if( PREDICT_FALSE(bdb->nsessions == CNAT_MAX_SESSIONS_PER_BIB)) { + /* printf("Create Session - Max sessions per BIB reached\n"); */ + return NULL; + } + + pthread_spin_lock(cnat_db_v2_main.session_db_lockp); + pool_get(cnat_session_db, db); + memset(db, 0, sizeof(*db)); + + db_index = db - cnat_session_db; + db->v4_dest_key.k.port = ko->k.port; + db->v4_dest_key.k.ipv4 = ko->k.ipv4; + db->v4_dest_key.k.vrf = ko->k.vrf; + + db->main_list.next = db_index; + db->main_list.prev = db_index; + db->main_db_index = bdb - cnat_main_db; + + db->tcp_seq_num = 0; + db->ack_no = 0; + db->window = 0; + + if(PREDICT_FALSE(log)) { + bdb->nsessions++; + query_and_update_db_timeout(db, SESSION_DB_TYPE); + } + + if (PREDICT_FALSE(bdb->nsessions == 1)) { + /* + * first port for this src vrf/src ip addr + */ + bdb->session_head_index = db_index; + } else { + index_dlist_addtail(bdb->session_head_index, + (u8 *)cnat_session_db, sizeof(cnat_session_db[0]), + STRUCT_OFFSET_OF(cnat_session_entry_t, main_list), + db_index); + } + + /* + * setup o2i hash key + */ + CNAT_V4_GET_SESSION_HASH(db->main_db_index, ko->k.ipv4, ko->k.port, + ko->k.vrf, bucket_out, CNAT_SESSION_HASH_MASK) + + + db->cnat_session_hash.next = + cnat_session_hash[bucket_out].next; + cnat_session_hash[bucket_out].next = db_index; + + + if(PREDICT_FALSE(log)) { + if (bdb->flags & CNAT_DB_DSLITE_FLAG) { + cnat_session_log_ds_lite_mapping_create(bdb, + (dslite_table_db_ptr + instance),db); + } else { + cnat_vrfmap_t *my_vrfmap = cnat_map_by_vrf + bdb->vrfmap_index; + cnat_session_log_nat44_mapping_create(bdb, db, my_vrfmap); + } + } + + /* Need to set entry_expires here, as we need to override 0 check for + newly established sessions */ + db->entry_expires = cnat_current_time; + nat44_dslite_common_stats[instance].sessions++; + pthread_spin_unlock(cnat_db_v2_main.session_db_lockp); + return db; +} + +void +cnat_dest_update_main2session(cnat_main_db_entry_t *mdb, + cnat_session_entry_t *sdb) +{ + + sdb->flags = mdb->flags; + sdb->timeout = mdb->timeout; + sdb->entry_expires = mdb->entry_expires; + sdb->alg.delta = mdb->alg.delta; + sdb->tcp_seq_num = mdb->proto_data.seq_pcp.tcp_seq_num; + + /* Reset Main db values to 0 */ + /* Reset only session specific flags */ + mdb->flags &= ~(CNAT_DB_FLAG_TCP_ACTIVE | CNAT_DB_FLAG_UDP_ACTIVE + | CNAT_DB_FLAG_ALG_ENTRY | CNAT_DB_FLAG_ALG_CTRL_FLOW); + mdb->timeout = 0; + mdb->entry_expires = 0; + mdb->alg.delta = 0; + if(PREDICT_FALSE(!((mdb->flags & CNAT_DB_FLAG_PPTP_TUNNEL_ACTIVE) || + (mdb->flags & CNAT_DB_FLAG_PPTP_TUNNEL_INIT)))) { + mdb->proto_data.seq_pcp.tcp_seq_num = 0; + } + + mdb->dst_ipv4 = 0; + mdb->dst_port = 0; +} + + +void +cnat_dest_update_session2main(cnat_main_db_entry_t *mdb, + cnat_session_entry_t *sdb) +{ + + u16 flags = sdb->flags & (CNAT_DB_FLAG_TCP_ACTIVE | + CNAT_DB_FLAG_UDP_ACTIVE | CNAT_DB_FLAG_ALG_ENTRY | + CNAT_DB_FLAG_ALG_CTRL_FLOW); + mdb->flags |= flags; + mdb->timeout = sdb->timeout; + mdb->entry_expires = sdb->entry_expires; + mdb->alg.delta = sdb->alg.delta; + if(PREDICT_FALSE(!((mdb->flags & CNAT_DB_FLAG_PPTP_TUNNEL_ACTIVE) || + (mdb->flags & CNAT_DB_FLAG_PPTP_TUNNEL_INIT)))) { + mdb->proto_data.seq_pcp.tcp_seq_num = sdb->tcp_seq_num; + } + mdb->dst_ipv4 = sdb->v4_dest_key.k.ipv4; + mdb->dst_port = sdb->v4_dest_key.k.port; +} + +static void +_cnat_delete_session_db_entry (cnat_session_entry_t *ep, u8 log) +{ + u32 session_db_index; + u32 bdb_len; + cnat_main_db_entry_t *be =0; + cnat_session_entry_t *sdb_last = NULL; + u16 instance; + + if (PREDICT_FALSE(ep->flags & CNAT_DB_NAT64_FLAG) != 0) { + /* Preventive check - Not a NAT44 entry */ + return; + } + + pool_header_t *h = pool_header(cnat_main_db); + + /* Validate .. just in case we are trying to delete a non existing one */ + bdb_len = vec_len(cnat_main_db); + + /* In case of invalid user just return, deleting only main db + * is not a good idea, since some valid user db entry might be pointing + * to that main db and hence leave the dbs in a inconsistent state + */ + if (PREDICT_FALSE((ep->main_db_index >= bdb_len) || + (clib_bitmap_get(h->free_bitmap, ep->main_db_index)))) { +#ifdef DEBUG_PRINTF_ENABLED + printf("invalid/unused user index in db %d\n", ep->main_db_index); +#endif + spp_printf(CNAT_INV_UNUSED_USR_INDEX, 1, (u32 *) &(ep->main_db_index)); + return; + } + + be = cnat_main_db + ep->main_db_index; + + session_db_index = ep - cnat_session_db; + + be->session_head_index = index_dlist_remelem ( + be->session_head_index, (u8 *)cnat_session_db, + sizeof (cnat_session_db[0]), + STRUCT_OFFSET_OF(cnat_session_entry_t, main_list), + session_db_index); + + if (be->flags & CNAT_DB_DSLITE_FLAG) { + instance = be->dslite_nat44_inst_id; + } else { + instance = NAT44_RESERVED_INST_ID; + } + + if(PREDICT_TRUE(log)) { + if (be->flags & CNAT_DB_DSLITE_FLAG) { + cnat_session_log_ds_lite_mapping_delete(be, + (dslite_table_db_ptr + instance),ep); + } else { + cnat_vrfmap_t *my_vrfmap = cnat_map_by_vrf + be->vrfmap_index; + cnat_session_log_nat44_mapping_delete(be, ep, my_vrfmap); + } + be->nsessions--; + } + + if (PREDICT_FALSE(be->nsessions == 1 && log)) { + /* There is only 1 session left + * Copy the info back to main db and release the last + * existing session + */ + + sdb_last = cnat_session_db + be->session_head_index; + ASSERT(sdb_last != NULL); + + cnat_dest_update_session2main(be, sdb_last); + _cnat_delete_session_db_entry(sdb_last, FALSE); + } + + /* Remove from session DB hashes */ + cnat_session_db_hash_delete(ep); + nat44_dslite_common_stats[instance].sessions--; + + pool_put(cnat_session_db, ep); +} + +void cnat_delete_session_db_entry (cnat_session_entry_t *ep, u8 log) +{ + pthread_spin_lock(cnat_db_v2_main.session_db_lockp); + _cnat_delete_session_db_entry (ep, log); + pthread_spin_unlock(cnat_db_v2_main.session_db_lockp); +} + +cnat_main_db_entry_t* +dslite_main_db_lookup_entry(dslite_db_key_bucket_t *ki) +{ + u64 a, b, c; + u32 index; + cnat_main_db_entry_t *db; + cnat_user_db_entry_t *userdb; + + DSLITE_V6_GET_HASH((&(ki->dk)), + ki->bucket, + CNAT_MAIN_HASH_MASK); + + DSLITE_PRINTF(1,"MDBLU hash..%u\n", ki->bucket); + + index = cnat_in2out_hash[ki->bucket].next; + if (PREDICT_TRUE(index == EMPTY)) { + DSLITE_PRINTF(1,"MDBLU index MT..\n"); + return (NULL); + } + + do { +/* We can add a flag here to indicate if the db entry is for nat44 or + * dslite. If the db entry is for nat44 then we can simply move to the + * one. + */ + db = cnat_main_db + index; + userdb = cnat_user_db + db->user_index; + if (PREDICT_TRUE(db->in2out_key.key64 == ki->dk.ipv4_key.key64) + && userdb->ipv6[0] == ki->dk.ipv6[0] + && userdb->ipv6[1] == ki->dk.ipv6[1] + && userdb->ipv6[2] == ki->dk.ipv6[2] + && userdb->ipv6[3] == ki->dk.ipv6[3]) { + DSLITE_PRINTF(1,"MDBLU success..%u\n", index); + return db; + } + index = db->in2out_hash.next; + } while (index != EMPTY); + + DSLITE_PRINTF(1,"MDBLU Entry does not exist..\n"); + return (NULL); +} + +cnat_user_db_entry_t* +dslite_user_db_lookup_entry(dslite_db_key_bucket_t *uki) +{ + u64 a, b, c; + u32 index; + cnat_user_db_entry_t *udb=NULL; + + DSLITE_V6_GET_HASH((&(uki->dk)), + uki->bucket, + CNAT_USER_HASH_MASK) + + DSLITE_PRINTF(1,"UDBLU hash..%u\n", uki->bucket); + + /* now: index in user vector */ + index = cnat_user_hash[uki->bucket].next; + if (PREDICT_TRUE(index != EMPTY)) { + DSLITE_PRINTF(1,"UDBLU hash table entry not MT..\n"); + do { + udb = cnat_user_db + index; + if (PREDICT_FALSE(udb->key.key64 == uki->dk.ipv4_key.key64) + && udb->ipv6[0] == uki->dk.ipv6[0] + && udb->ipv6[1] == uki->dk.ipv6[1] + && udb->ipv6[2] == uki->dk.ipv6[2] + && udb->ipv6[3] == uki->dk.ipv6[3]) { + DSLITE_PRINTF(1,"UDBLU success..%u\n", index); + return udb; + } + index = udb->user_hash.next; + } while (index != EMPTY); + } + DSLITE_PRINTF(1,"UDBLU Entry doesnt exist..\n"); + return (NULL); +} + +cnat_user_db_entry_t* +dslite_user_db_create_entry(dslite_db_key_bucket_t *uki, + u32 portmap_index) +{ + cnat_user_db_entry_t *udb = NULL; + + /* UNUSED. Therefore not ported to be multi-thread friendly */ + ASSERT(0); + + pool_get(cnat_user_db, udb); + memset(udb, 0, sizeof(*udb)); + + udb->ntranslations = 1; + udb->portmap_index = portmap_index; +// udb->key.key64 = uki->k.key64; + + udb->key.key64 = uki->dk.ipv4_key.key64; + udb->ipv6[0] = uki->dk.ipv6[0]; + udb->ipv6[1] = uki->dk.ipv6[1]; + udb->ipv6[2] = uki->dk.ipv6[2]; + udb->ipv6[3] = uki->dk.ipv6[3]; + + udb->flags |= CNAT_USER_DB_DSLITE_FLAG; + /* Add this user to the head of the bucket chain */ + udb->user_hash.next = + cnat_user_hash[uki->bucket].next; + cnat_user_hash[uki->bucket].next = udb - cnat_user_db; + +#ifndef NO_BULK_LOGGING + INIT_BULK_CACHE(udb) +#endif /* NO_BULK_LOGGING */ + + return udb; +} + +#ifndef TOBE_PORTED +cnat_main_db_entry_t* +dslite_create_main_db_entry_and_hash(dslite_db_key_bucket_t *ki, + cnat_db_key_bucket_t *ko, + cnat_user_db_entry_t *udb) +{ + return 0; +} +#else +cnat_main_db_entry_t* +dslite_create_main_db_entry_and_hash(dslite_db_key_bucket_t *ki, + cnat_db_key_bucket_t *ko, + cnat_user_db_entry_t *udb) +{ + u64 a, b, c; + u32 db_index; + cnat_main_db_entry_t *db = NULL; + + /* UNUSED. Therefore not ported to be multi-thread friendly */ + ASSERT(0); + + pool_get(cnat_main_db, db); + memset(db, 0, sizeof(*db)); + + db_index = db - cnat_main_db; + db->in2out_key.k.ipv4 = ki->dk.ipv4_key.k.ipv4; + db->in2out_key.k.port = ki->dk.ipv4_key.k.port; + db->in2out_key.k.vrf = ki->dk.ipv4_key.k.vrf; + db->out2in_key.k.ipv4 = ko->k.k.ipv4; + db->out2in_key.k.port = ko->k.k.port; + db->out2in_key.k.vrf = ko->k.k.vrf; + + db->user_ports.next = db_index; + db->user_ports.prev = db_index; + db->user_index = udb - cnat_user_db; + //db->portmap_index = udb->portmap_index; + db->flags |= CNAT_DB_DSLITE_FLAG; + + if (PREDICT_FALSE(udb->ntranslations == 1)) { + /* + * first port for this src vrf/src ip addr + */ + udb->translation_list_head_index = db_index; + DSLITE_PRINTF(1,"First translation of this user..\n"); + } else { + index_dlist_addtail(udb->translation_list_head_index, + (u8 *)cnat_main_db, sizeof(cnat_main_db[0]), + STRUCT_OFFSET_OF(cnat_main_db_entry_t, user_ports), + db_index); + } + + /* + * setup o2i hash key + */ + CNAT_V4_GET_HASH(ko->k.key64, + ko->bucket, + CNAT_MAIN_HASH_MASK) + db->out2in_hash.next = cnat_out2in_hash[ko->bucket].next; + cnat_out2in_hash[ko->bucket].next = db_index; + /* + * setup i2o hash key, bucket is already calculate + */ + db->in2out_hash.next = cnat_in2out_hash[ki->bucket].next; + cnat_in2out_hash[ki->bucket].next = db_index; + + DSLITE_PRINTF(1,"Create main db and hash..%u %u %u %u %x\n", + ki->bucket, ko->bucket, + db_index, db->user_index, ko->k.key64); + +#if DEBUG > 1 + printf("\nMy_Instance_Number %d: Bucket %d, Db_Index %d", + my_instance_number, ki->bucket, db_index); + printf("\nInside (VRF 0x%x, IP 0x%x, PORT 0x%x)", + db->in2out_key.k.vrf, db->in2out_key.k.ipv4, db->in2out_key.k.port); + printf("\nOutside (VRF 0x%x, IP 0x%x, PORT 0x%x)", + db->out2in_key.k.vrf, db->out2in_key.k.ipv4, db->out2in_key.k.port); + printf("\nUser Index %d, IP 0x%x", + db->user_index, udb->key.k.ipv4); +#endif + + //nat44_dslite_common_stats[DSLITE_COMMON_STATS].active_translations++; + + return db; +} + +static inline void handle_dslite_port_exceeded_logging( + cnat_user_db_entry_t *udb, + dslite_key_t * key, + dslite_table_entry_t *dslite_entry_ptr) +{ + + if(PREDICT_TRUE(udb->flags & CNAT_USER_DB_PORT_LIMIT_EXCEEDED)) { + /* Already logged ..*/ + return; + } + + /* else, set the flag and call the log API */ + udb->flags = udb->flags | CNAT_USER_DB_PORT_LIMIT_EXCEEDED; + cnat_log_ds_lite_port_limit_exceeded(key, dslite_entry_ptr); + return; +} +#endif + +void handle_cnat_port_exceeded_logging( + cnat_user_db_entry_t *udb, + cnat_key_t * key, + cnat_vrfmap_t *vrfmap) +{ + + if(PREDICT_TRUE(udb->flags & CNAT_USER_DB_PORT_LIMIT_EXCEEDED)) { + /* Already logged ..*/ + return; + } + + /* else, set the flag and call the log API */ + udb->flags = udb->flags | CNAT_USER_DB_PORT_LIMIT_EXCEEDED; + cnat_log_nat44_port_limit_exceeded(key,vrfmap); + return; +} + +#ifndef TOBE_PORTED +cnat_main_db_entry_t* +dslite_get_main_db_entry_v2(dslite_db_key_bucket_t *ki, + port_pair_t port_pair_type, + port_type_t port_type, + cnat_gen_icmp_info *info, + dslite_table_entry_t *dslite_entry_ptr, + cnat_key_t *dest_info) +{ + return 0; +} +#else +/* + * this function is called by exception node + * when lookup is fialed in i2o node + * + * if reash per user port limit, + * set user_db_entry pointer, and error == CNAT_OUT_LIMIT + */ +cnat_main_db_entry_t* +dslite_get_main_db_entry_v2(dslite_db_key_bucket_t *ki, + port_pair_t port_pair_type, + port_type_t port_type, + cnat_gen_icmp_info *info, + dslite_table_entry_t *dslite_entry_ptr, + cnat_key_t *dest_info) +{ + u16 protocol; + cnat_errno_t rv; + dslite_db_key_bucket_t u_ki; + cnat_db_key_bucket_t ko; + u32 my_index, free_main, free_user; + u32 current_timestamp; + cnat_vrfmap_t *my_vrfmap =0; + u16 my_vrfmap_index; + cnat_portmap_v2_t *pm =0; + cnat_user_db_entry_t *udb = 0; + cnat_main_db_entry_t *db = 0; + pool_header_t *h; + u16 dslite_id = dslite_entry_ptr->dslite_id; + +#ifndef NO_BULK_LOGGING + int nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED; +#endif + + /* UNUSED. Therefore not ported to be multi-thread friendly */ + ASSERT(0); + + /* + * need to try lookup again because + * second pkt may come here before the entry is created + * by receiving first pkt due to high line rate. + */ + info->gen_icmp_msg = CNAT_NO_ICMP_MSG; + info->error = CNAT_SUCCESS; + db = dslite_main_db_lookup_entry(ki); + if (PREDICT_TRUE(db)) { + /* what if the source is talking to a + * new dest now? We will have to handle this case and + * take care of - creating session db and logging + */ + if(PREDICT_FALSE((!dest_info->k.ipv4) && (!dest_info->k.port))) { + return db; /* if dest_info is null don't create session */ + } + + if(PREDICT_TRUE((db->dst_ipv4 == dest_info->k.ipv4) && + (db->dst_port == dest_info->k.port))) { + return db; + } + dest_info->k.vrf = db->in2out_key.k.vrf; + /* Src is indeed talking to a different dest */ + cnat_session_entry_t *session_db2 = NULL; + if(PREDICT_TRUE(db->nsessions == 1)) { + session_db2 = cnat_handle_1to2_session(db, dest_info); + if(PREDICT_TRUE(session_db2 != NULL)) { + CNAT_DB_TIMEOUT_RST(session_db2); + return db; + } else { + info->error = CNAT_ERR_NO_SESSION_DB; + return NULL; + } + } else if(PREDICT_FALSE(db->nsessions == 0)) { + /* Should be static entry.. should never happen + */ + if(PREDICT_TRUE(dest_info->k.ipv4 != 0)) { + cnat_add_dest_n_log(db, dest_info); + } + return db; + } else { + /* The src has already created multiple sessions.. very rare + */ + session_db2 = cnat_create_session_db_entry(dest_info, + db, TRUE); + if(PREDICT_TRUE(session_db2 != NULL)) { + CNAT_DB_TIMEOUT_RST(session_db2); + return db; + } else { + info->error = CNAT_ERR_NO_SESSION_DB; + return NULL; + } + } + + } + + /* + * step 1. check if outside vrf is configured or not + * and Find the set of portmaps for the outside vrf + * insider vrf is one to one mappted to outside vrf + * key is vrf and ip only + * ki.k.k.vrf has protocol bits, mask out + */ + protocol = ki->dk.ipv4_key.k.vrf & CNAT_PRO_MASK; + u_ki.dk.ipv4_key.k.vrf = ki->dk.ipv4_key.k.vrf & CNAT_VRF_MASK; +#ifdef DSLITE_USER_IPV4 + u_ki.dk.ipv4_key.k.ipv4 = ki->dk.ipv4_key.k.ipv4; +#else + /* + * Inside ipv4 address should be masked, if port limit + * need to be done at B4 element level. + */ + u_ki.dk.ipv4_key.k.ipv4 = 0; +#endif + u_ki.dk.ipv4_key.k.port = 0; + + u_ki.dk.ipv6[0] = ki->dk.ipv6[0]; + u_ki.dk.ipv6[1] = ki->dk.ipv6[1]; + u_ki.dk.ipv6[2] = ki->dk.ipv6[2]; + u_ki.dk.ipv6[3] = ki->dk.ipv6[3]; + + my_vrfmap_index = vrf_map_array[u_ki.dk.ipv4_key.k.vrf]; + my_vrfmap = cnat_map_by_vrf + my_vrfmap_index; +/* Checking if the inst entry is active or not is done much earlier + */ +#if 0 + my_vrfmap_index = vrf_map_array[u_ki.k.k.vrf]; + my_vrfmap = cnat_map_by_vrf + my_vrfmap_index; + my_vrfmap_entry_found = ((my_vrfmap_index != VRF_MAP_ENTRY_EMPTY) && + (my_vrfmap->status == S_RUN) && + (my_vrfmap->i_vrf == u_ki.k.k.vrf)); + + if (PREDICT_FALSE(!my_vrfmap_entry_found)) { + u32 arr[] = {ki->k.k.vrf, ki->k.k.ipv4, ki->k.k.port}; + if ((my_vrfmap_index == VRF_MAP_ENTRY_EMPTY) || + (my_vrfmap->i_vrf == u_ki.k.k.vrf)) { + info->error = CNAT_NO_CONFIG; + CNAT_DEBUG_INSIDE_ERR(CNAT_NO_CONFIG) + spp_printf(CNAT_NO_CONFIG_ERROR, 3, arr); + } else { + info->error = CNAT_NO_VRF_RUN; + CNAT_DEBUG_INSIDE_ERR(CNAT_NO_VRF_RUN) + spp_printf(CNAT_NO_VRF_RUN_ERROR, 3, arr); + } + + return (NULL); + } +#endif +/* + dslite_inst_ptr = dslite_nat44_config_table[dslite_inst_id]; +*/ + pm = dslite_entry_ptr->portmap_list; + //pm = my_vrfmap->portmap_list; + + /* + * set o2i key with protocl bits + */ + ko.k.k.vrf = dslite_entry_ptr->o_vrf | protocol; + //ko.k.k.vrf = my_vrfmap->o_vrf | protocol; + + /* + * step 2. check if src vrf, src ip addr is alreay + * in the user db + * if yes, use PORT_ALLOC_DIRECTED + * if no, use PORT_ALLOC_ANY since it is first time + */ + udb = dslite_user_db_lookup_entry(&u_ki); + if (PREDICT_TRUE(udb)) { + /* + * not first time allocate port for this user + * check limit + */ + if (PREDICT_FALSE(udb->ntranslations >= + dslite_entry_ptr->cnat_main_db_max_ports_per_user)) { + //cnat_main_db_max_ports_per_user)) + + /* Check for the port type here. If we are getting + * a STATIC PORT, allow the config. + */ + if (PREDICT_TRUE(port_type != PORT_TYPE_STATIC)) { + info->error = CNAT_OUT_LIMIT; + DSLITE_DEBUG_INSIDE_ERR(CNAT_OUT_LIMIT) + port_exceeded_msg_log(u_ki.dk.ipv4_key.k.ipv4, u_ki.dk.ipv4_key.k.vrf); + nat44_dslite_common_stats[dslite_id].in2out_drops_port_limit_exceeded ++; + u_ki.dk.ipv4_key.k.vrf = ki->dk.ipv4_key.k.vrf; + u_ki.dk.ipv4_key.k.port = ki->dk.ipv4_key.k.port; + handle_dslite_port_exceeded_logging(udb, &u_ki.dk, dslite_entry_ptr); + return (NULL); + } + } + + CHECK_CLEAR_PORT_LIMIT_EXCEED_FLAG(udb, + dslite_entry_ptr->cnat_main_db_max_ports_per_user) + + /* + * check if main db has space to accomodate new entry + */ + h = pool_header(cnat_main_db); + + free_main = vec_len(h->free_indices) - 1; + if (PREDICT_FALSE(!free_main)) { + info->error = CNAT_MAIN_DB_LIMIT; + nat44_dslite_common_stats[dslite_id].in2out_drops_system_limit_reached ++; + DSLITE_DEBUG_INSIDE_ERR(CNAT_MAIN_DB_LIMIT) + + current_timestamp = spp_trace_log_get_unix_time_in_seconds(); + if (PREDICT_FALSE((current_timestamp - last_log_timestamp) > + 1800)) { + spp_printf(CNAT_SESSION_THRESH_EXCEEDED, 0, NULL); + last_log_timestamp = current_timestamp; + } + +#ifdef UT_TEST_CODE + printf("Limit reached : OLD USER"); +#endif + return NULL; + } + + /* + * allocate port, from existing mapping + */ + my_index = udb->portmap_index; + + if (PREDICT_FALSE(port_type == PORT_TYPE_STATIC)) { + rv = cnat_static_port_alloc_v2_bulk(pm, + PORT_ALLOC_DIRECTED, + port_pair_type, + ki->dk.ipv4_key.k.ipv4, + ki->dk.ipv4_key.k.port, + &my_index, + &(ko.k.k.ipv4), + &(ko.k.k.port), + STAT_PORT_RANGE_FROM_INST_PTR(dslite_entry_ptr) +#ifndef NO_BULK_LOGGING + , udb, + BULKSIZE_FROM_VRFMAP(dslite_entry_ptr), + &nfv9_log_req +#endif + , my_vrfmap->ip_n_to_1 + ); + } else if (PREDICT_TRUE(port_type != PORT_TYPE_RTSP) ) { + + rv = cnat_dynamic_port_alloc_v2_bulk(pm, + PORT_ALLOC_DIRECTED, + port_pair_type, + &my_index, + &(ko.k.k.ipv4), + &(ko.k.k.port), + STAT_PORT_RANGE_FROM_INST_PTR(dslite_entry_ptr) +#ifndef NO_BULK_LOGGING + , udb, + BULKSIZE_FROM_VRFMAP(dslite_entry_ptr), + &nfv9_log_req +#endif + , 0, + &(dslite_entry_ptr->rseed_ip) + ); + DSLITE_PRINTF(1,"D_PORT_ALLOC %x %u\n", ko.k.k.ipv4, ko.k.k.port); + } else { + /* + * For RTSP, two translation entries are created, + * check if main db has space to accomodate two new entry + */ + free_main = free_main - 1; + + if (PREDICT_FALSE(!free_main)) { + info->error = CNAT_MAIN_DB_LIMIT; + nat44_dslite_common_stats[dslite_id].in2out_drops_system_limit_reached ++; + DSLITE_DEBUG_INSIDE_ERR(CNAT_MAIN_DB_LIMIT) + + return NULL; + } else { + + rv = cnat_dynamic_port_alloc_rtsp_bulk(pm, + PORT_ALLOC_DIRECTED, + port_pair_type, + ki->dk.ipv4_key.k.port, + &my_index, + &(ko.k.k.ipv4), + &(ko.k.k.port), + STAT_PORT_RANGE_FROM_INST_PTR(dslite_entry_ptr) +#ifndef NO_BULK_LOGGING + , udb, + BULKSIZE_FROM_VRFMAP(dslite_entry_ptr), + &nfv9_log_req +#endif + , &(dslite_entry_ptr->rseed_ip) + ); + } + } + + if (PREDICT_FALSE(rv != CNAT_SUCCESS)) { + DSLITE_PRINTF(1,"D_PORT_ALLOC port alloc error\n"); + info->error = rv; + DSLITE_DEBUG_INSIDE_ERR(rv) + nat44_dslite_common_stats[dslite_id].in2out_drops_resource_depletion ++; + log_port_alloc_error(rv, &(ki->dk.ipv4_key)); + return (NULL); + } + /* + * increment port in use for this user + */ + udb->ntranslations += 1; + } else { + /* + * first time allocate port for this user + */ + + /* + * Do not create entry if port limit is invalid + */ + if (PREDICT_FALSE(!(dslite_entry_ptr->cnat_main_db_max_ports_per_user))) { + if (PREDICT_TRUE(port_type != PORT_TYPE_STATIC)) { + info->error = CNAT_OUT_LIMIT; + nat44_dslite_common_stats[dslite_id].in2out_drops_port_limit_exceeded ++; + port_exceeded_msg_log(u_ki.dk.ipv4_key.k.ipv4, u_ki.dk.ipv4_key.k.vrf); + DSLITE_DEBUG_INSIDE_ERR(CNAT_OUT_LIMIT) + return (NULL); + } + } + + /* + * Check if main db has space for new entry + * Allowing a user db entry to be created if main db is not free + * will cause a port to be allocated to that user, which results in + * wastage of that port, hence the check is done here. + */ + h = pool_header(cnat_main_db); + free_main = vec_len(h->free_indices) - 1; + + h = pool_header(cnat_user_db); + free_user = vec_len(h->free_indices) - 1; + + /* + * If either main_db or user_db does not have entries + * bail out, with appropriate error + */ + if (PREDICT_FALSE(!(free_main && free_user))) { + u32 log_error; + if(free_main) { + info->error = CNAT_USER_DB_LIMIT; + log_error = CNAT_USER_DB_LIMIT_ERROR; + } else { + info->error = CNAT_MAIN_DB_LIMIT; + log_error = CNAT_MAIN_DB_LIMIT_ERROR; + } + nat44_dslite_common_stats[dslite_id].in2out_drops_system_limit_reached ++; + DSLITE_DEBUG_INSIDE_ERR(info->error) + spp_printf(log_error, 0, 0); + return NULL; + } + + if (PREDICT_FALSE(port_type == PORT_TYPE_STATIC)) { + rv = cnat_static_port_alloc_v2_bulk(pm, + PORT_ALLOC_ANY, + port_pair_type, + ki->dk.ipv4_key.k.ipv4, + ki->dk.ipv4_key.k.port, + &my_index, + &(ko.k.k.ipv4), + &(ko.k.k.port), + STAT_PORT_RANGE_FROM_INST_PTR(dslite_entry_ptr) +#ifndef NO_BULK_LOGGING + , NULL, + BULKSIZE_FROM_VRFMAP(dslite_entry_ptr), + &nfv9_log_req +#endif + , my_vrfmap->ip_n_to_1 + + ); + } else if (PREDICT_TRUE(port_type != PORT_TYPE_RTSP)) { + rv = cnat_dynamic_port_alloc_v2_bulk(pm, + PORT_ALLOC_ANY, + port_pair_type, + &my_index, + &(ko.k.k.ipv4), + &(ko.k.k.port), + STAT_PORT_RANGE_FROM_INST_PTR(dslite_entry_ptr) +#ifndef NO_BULK_LOGGING + , NULL, + BULKSIZE_FROM_VRFMAP(dslite_entry_ptr), + &nfv9_log_req +#endif + , 0, + &(dslite_entry_ptr->rseed_ip) + ); + DSLITE_PRINTF(1,"NU:D PORT ALLOC..%x %u\n", ko.k.k.ipv4, + ko.k.k.port); + + } else { + /* + * For RTSP, two translation entries are created, + * check if main db has space to accomodate two new entry + */ + free_main = free_main - 1; + + if (PREDICT_FALSE(!free_main)) { + info->error = CNAT_MAIN_DB_LIMIT; + nat44_dslite_common_stats[dslite_id].in2out_drops_system_limit_reached ++; + DSLITE_DEBUG_INSIDE_ERR(CNAT_MAIN_DB_LIMIT) + + return NULL; + } else { + + rv = cnat_dynamic_port_alloc_rtsp_bulk(pm, + PORT_ALLOC_DIRECTED, + port_pair_type, + ki->dk.ipv4_key.k.port, + &my_index, + &(ko.k.k.ipv4), + &(ko.k.k.port), + STAT_PORT_RANGE_FROM_INST_PTR(dslite_entry_ptr) +#ifndef NO_BULK_LOGGING + , NULL, + BULKSIZE_FROM_VRFMAP(dslite_entry_ptr), + &nfv9_log_req +#endif + , &(dslite_entry_ptr->rseed_ip) + ); + /* TODO: Add the port pair flag here */ + } + } + + + + if (PREDICT_FALSE(rv != CNAT_SUCCESS)) { + DSLITE_PRINTF(1,"NU:D_PORT_ALLOC port alloc error\n"); + info->error = rv; + nat44_dslite_common_stats[dslite_id].in2out_drops_resource_depletion ++; + DSLITE_DEBUG_INSIDE_ERR(rv) + log_port_alloc_error(rv, &(ki->dk.ipv4_key)); + return (NULL); + } + /* + * create entry in user db + */ + udb = dslite_user_db_create_entry(&u_ki, my_index); + nat44_dslite_common_stats[dslite_id].num_subscribers++; + DSLITE_PRINTF(1,"UDB crete entry done..\n"); +#ifndef NO_BULK_LOGGING + if(PREDICT_TRUE(udb && (BULK_ALLOC_NOT_ATTEMPTED != nfv9_log_req))) { + cnat_update_bulk_range_cache(udb, ko.k.k.port, + BULKSIZE_FROM_VRFMAP(dslite_entry_ptr)); + } +#endif /* #ifndef NO_BULK_LOGGING */ + } + + /* + * step 3: + * outside port is allocated for this src vrf/src ip addr + * 1)create a new entry in main db + * 2)setup cnat_out2in_hash key + * 3)setup cnat_in2out_hash key + */ + db = dslite_create_main_db_entry_and_hash(ki, &ko, udb); + DSLITE_PRINTF(1,"dslite_create_main_db_entry_and_hash done..\n"); + //db->vrfmap_index = my_vrfmap - cnat_map_by_vrf; + db->dslite_nat44_inst_id = dslite_id; + nat44_dslite_common_stats[dslite_id].active_translations++; + if (PREDICT_FALSE(port_type == PORT_TYPE_STATIC)) { + nat44_dslite_common_stats[dslite_id].num_static_translations++; + } else { + nat44_dslite_common_stats[dslite_id].num_dynamic_translations++; + } + + dslite_translation_create_count++; + + db->dst_ipv4 = dest_info->k.ipv4; + db->dst_port = dest_info->k.port; + if(PREDICT_TRUE(db->dst_ipv4 || db->dst_port)) { + /* for static fwding, let the nsessions remain zero */ + db->nsessions++; + } + + /* + * don't forget logging + * logging API is unconditional, + * logging configuration check is done inside the inline function + */ + if(PREDICT_FALSE(nfv9_log_req != CACHE_ALLOC_NO_LOG_REQUIRED)) { + if(PREDICT_FALSE( dslite_entry_ptr->nf_logging_policy == + SESSION_LOG_ENABLE)) { + if(PREDICT_TRUE(db->dst_ipv4 || db->dst_port)) { + cnat_nfv9_ds_lite_log_session_create(db, + dslite_entry_ptr,NULL); + } + } else { + cnat_nfv9_ds_lite_mapping_create(db,dslite_entry_ptr +#ifndef NO_BULK_LOGGING + ,nfv9_log_req +#endif + ); + } + if(PREDICT_TRUE((dslite_entry_ptr->syslog_logging_policy != SESSION_LOG_ENABLE) || + (db->dst_ipv4 || db->dst_port))) { + cnat_syslog_ds_lite_mapping_create(db,dslite_entry_ptr,NULL +#ifndef NO_BULK_LOGGING + ,nfv9_log_req +#endif + ); + } + } + +#if 0 + if (PREDICT_FALSE(port_pair_type == PORT_PAIR)) { + cnat_main_db_entry_t *db2 = 0; + dslite_db_key_bucket_t new_ki = *ki; + u64 a, b, c; + + new_ki.k.k.port += 1; + ko.k.k.port += 1; + + CNAT_V4_GET_HASH(new_ki.k.key64, new_ki.bucket, + CNAT_MAIN_HASH_MASK); + + db2 = cnat_create_main_db_entry_and_hash(&new_ki, &ko, udb); + + translation_create_count ++; + db2->dslite_nat44_inst_id = dslite_id; + db2->entry_expires = cnat_current_time; + db2->flags |= CNAT_DB_FLAG_ALG_ENTRY; + udb->ntranslations += 1; +#ifndef NO_BULK_LOGGING + if(PREDICT_FALSE(nfv9_log_req == BULK_ALLOC_NOT_ATTEMPTED)) + cnat_nfv9_log_mapping_create(db2, my_vrfmap, nfv9_log_req); +#else + cnat_nfv9_log_mapping_create(db2, my_vrfmap); +#endif + } +#endif + return db; +} +#endif /* TOBE_PORTED */ + +#if 0 +/* TOBE_PORTED */ +uword +cnat_db_v2_node_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + return 0; +} +VLIB_REGISTER_NODE (cnat_db_v2_node) = { + .function = cnat_db_v2_node_fn, + .name = "vcgn-db-v2", + .vector_size = sizeof (u32), + .type = VLIB_NODE_TYPE_INTERNAL, + + .n_errors = ARRAY_LEN(cnat_db_v2_error_strings), + .error_strings = cnat_db_v2_error_strings, + + .n_next_nodes = CNAT_DB_V2_DROP, + + /* edit / add dispositions here */ + .next_nodes = { + [CNAT_DB_V2_DROP] = "error-drop", + }, +}; +#endif +void cnat_db_v2_init (void) +{ + + u32 i, n; + cnat_timeout_db_entry_t * tdb __attribute__((unused)); + + cgse_nat_db_entry_t *comb_db __attribute__((unused)); + cgse_nat_user_db_entry_t *comb_user __attribute__((unused)); + cgse_nat_session_db_entry_t *comb_session __attribute__((unused)); + + n = CNAT_DB_SIZE*1.15; /* add 15% LB margin */ + + /* + * We also make it multiple of NUM_BITS_IN_UWORD for better + * DB scanning algorithm + */ + if (n % NUM_BITS_IN_UWORD) + n += (NUM_BITS_IN_UWORD - (n % NUM_BITS_IN_UWORD)); + + pool_alloc(cgse_nat_db,n); + for(i=0; i< n; i++) { + pool_get(cgse_nat_db, comb_db); + } + + for(i=0; i< n; i++) { + pool_put(cgse_nat_db, cgse_nat_db + i); + } + + cnat_main_db = &cgse_nat_db->nat44_main_db; + + /* For Sessions */ + if(PLATFORM_DBL_SUPPORT) { + /* create session table for NAT44 and NAT64 itself */ + printf("DBL Support exist %d\n", PLATFORM_DBL_SUPPORT); + n = CNAT_SESSION_DB_SIZE * 1.15; /* add 15% LB margin */ + } else { + /* Create session table for NAT64 only */ + printf("DBL Support Not exist\n"); + n = NAT64_MAIN_DB_SIZE * 1.15; /* add 15% LB margin */ + } + + /* + * We also make it multiple of NUM_BITS_IN_UWORD for better + * DB scanning algorithm + */ + if (n % NUM_BITS_IN_UWORD) + n += (NUM_BITS_IN_UWORD - (n % NUM_BITS_IN_UWORD)); + + pool_alloc(cgse_session_db,n); + for(i=0; i< n; i++) { + pool_get(cgse_session_db, comb_session); + } + + for(i=0; i< n; i++) { + pool_put(cgse_session_db, cgse_session_db + i); + } + + cnat_session_db = &cgse_session_db->nat44_session_db; + + vec_validate(cnat_out2in_hash, CNAT_MAIN_HASH_MASK); + memset(cnat_out2in_hash, 0xff, CNAT_MAIN_HASH_SIZE*sizeof(index_slist_t)); + + vec_validate(cnat_in2out_hash, CNAT_MAIN_HASH_MASK); + memset(cnat_in2out_hash, 0xff, CNAT_MAIN_HASH_SIZE*sizeof(index_slist_t)); + + vec_validate(cnat_session_hash, CNAT_SESSION_HASH_MASK); + memset(cnat_session_hash, 0xff, CNAT_SESSION_HASH_SIZE*sizeof(index_slist_t)); + + n = CNAT_USER_DB_SIZE * 1.15; /* use hash size as db size for LB margin */ + if (n % NUM_BITS_IN_UWORD) + n += (NUM_BITS_IN_UWORD - (n % NUM_BITS_IN_UWORD)); + + pool_alloc(cgse_user_db,n); + for(i=0; i< n; i++) { + pool_get(cgse_user_db, comb_user); + } + + for(i=0; i< n; i++) { + pool_put(cgse_user_db, cgse_user_db + i); + } + + cnat_user_db = &cgse_user_db->nat44_user_db; + + vec_validate(cnat_user_hash, CNAT_USER_HASH_MASK); + memset(cnat_user_hash, 0xff, CNAT_USER_HASH_SIZE*sizeof(index_slist_t)); + + n = CNAT_TIMEOUT_HASH_SIZE; /* use hash size as db size for LB margin */ + for(i=0; i< n; i++) { + pool_get(cnat_timeout_db, tdb); + } + + for(i=0; i< n; i++) { + pool_put(cnat_timeout_db, cnat_timeout_db + i); + } + + vec_validate(cnat_timeout_hash, CNAT_TIMEOUT_HASH_MASK); + memset(cnat_timeout_hash, 0xff, CNAT_TIMEOUT_HASH_SIZE*sizeof(index_slist_t)); + +#ifdef TOBE_PORTED + for (i=0;i +#include + +#include "cnat_cli.h" + +u32 global_debug_flag = CNAT_DEBUG_NONE; +u16 debug_i_vrf = CNAT_DEBUG_NONE; +u32 debug_i_flag = CNAT_DEBUG_NONE; +u32 debug_i_addr_start = CNAT_DEBUG_NONE; +u32 debug_i_addr_end = CNAT_DEBUG_NONE; + +u16 debug_o_vrf = CNAT_DEBUG_NONE; +u32 debug_o_flag = CNAT_DEBUG_NONE; +u32 debug_o_addr_start = CNAT_DEBUG_NONE; +u32 debug_o_addr_end = CNAT_DEBUG_NONE; + +u32 udp_inside_checksum_disable = 0; +u32 udp_outside_checksum_disable = 0; +u32 udp_inside_packet_dump_enable = 0; +u32 udp_outside_packet_dump_enable = 0; + +u32 tcp_logging_enable_flag = 0; + +u32 icmp_debug_flag = 0; +u32 frag_debug_flag = 0; + +u32 nfv9_logging_debug_flag = 0; +u32 syslog_debug_flag = 0; + +u32 summary_stats_debug_flag = 0; + +/* + * By defaut we set the config debug level to 1 + */ +u32 config_debug_level = 1; + +#ifdef TOBE_PORTED +extern void show_bulk_port_stats(); +extern void clear_bulk_port_stats(); +extern void show_bulk_port_allocation(u16 in_vrfid, u32 inside_ip); +extern void set_bulk_size_to_all_vrfs(int bulk_size); + +u32 *cnat_debug_addr_list; + +extern int global_pd_dbg_lvl; +extern int global_pi_dbg_lvl; +extern int global_l2_dbg_lvl; +extern u32 cnat_pptp_debug_flag; +extern u32 cnat_pcp_debug_flag; + +void spp_api_cnat_get_cgn_db_summary +(spp_api_cnat_generic_command_request_t *); + +void spp_api_cnat_v4_debug_dummy_t_handler +(spp_api_cnat_v4_debug_dummy_t *mp) +{ + u32 arr[] = { DEBUG_DUMMY }; + spp_printf(CNAT_DUMMY_HANDLER_HIT, 1, arr); + if(global_pd_dbg_lvl) { + PLATFORM_DEBUG_PRINT("\n invalid debug command received: message id is 0\n"); + } + mp->rc = CNAT_ERR_INVALID_MSG_ID; + +} + +void spp_api_cnat_v4_debug_dummy_max_t_handler +(spp_api_cnat_v4_debug_dummy_max_t *mp) +{ + u32 arr[] = { DEBUG_DUMMY_MAX }; + spp_printf(CNAT_DUMMY_HANDLER_HIT, 1, arr); + if(global_pd_dbg_lvl) { + PLATFORM_DEBUG_PRINT("\n invalid debug command received: message id is out of range\n"); + } + mp->rc = CNAT_ERR_INVALID_MSG_ID; + +} + + +void spp_api_cnat_v4_debug_global_t_handler +(spp_api_cnat_v4_debug_global_t *mp) +{ + if ((mp->debug_flag == CNAT_DEBUG_GLOBAL_ERR) || + (mp->debug_flag == CNAT_DEBUG_GLOBAL_ALL) || + (mp->debug_flag == CNAT_DEBUG_NONE)) { + mp->rc = CNAT_SUCCESS; + global_debug_flag = mp->debug_flag; + return; + } + + mp->rc = CNAT_ERR_PARSER; + if(global_pd_dbg_lvl) { + PLATFORM_DEBUG_PRINT("invalid global debug flag %x\n", + mp->debug_flag); + } + return; +} + +void spp_node_print_cnat_counters() +{ + if (cnat_global_counters.nfv9_downstream_constipation_count) { + PLATFORM_DEBUG_PRINT("\nNF downstream constipation count: %llu\n", + cnat_global_counters.nfv9_downstream_constipation_count); + } + + if (xlat_global_counters.v4_to_v6_frag_invalid_uidb_drop_count || + xlat_global_counters.v6_to_v4_frag_invalid_uidb_drop_count || + xlat_global_counters.v4_to_v6_icmp_invalid_uidb_drop_count || + xlat_global_counters.v6_to_v4_icmp_invalid_uidb_drop_count || + xlat_global_counters.v4_to_v6_tcp_invalid_uidb_drop_count || + xlat_global_counters.v6_to_v4_tcp_invalid_uidb_drop_count || + xlat_global_counters.v4_to_v6_udp_invalid_uidb_drop_count || + xlat_global_counters.v6_to_v4_udp_invalid_uidb_drop_count || + xlat_global_counters.v4_to_v6_udp_crc_zero_invalid_uidb_drop_count) { + + PLATFORM_DEBUG_PRINT("\nMy_instance %d: v4_to_v6 frag invalid uidb drop count %lld", + my_instance_number, + xlat_global_counters.v4_to_v6_frag_invalid_uidb_drop_count); + + PLATFORM_DEBUG_PRINT("\nMy_instance %d: v6_to_v4 frag invalid uidb drop count %lld", + my_instance_number, + xlat_global_counters.v6_to_v4_frag_invalid_uidb_drop_count); + + PLATFORM_DEBUG_PRINT("\nMy_instance %d: v4_to_v6 icmp invalid uidb drop count %lld", + my_instance_number, + xlat_global_counters.v4_to_v6_icmp_invalid_uidb_drop_count); + + PLATFORM_DEBUG_PRINT("\nMy_instance %d: v6_to_v4 icmp invalid uidb drop count %lld", + my_instance_number, + xlat_global_counters.v6_to_v4_icmp_invalid_uidb_drop_count); + + PLATFORM_DEBUG_PRINT("\nMy_instance %d: v4_to_v6 tcp invalid uidb drop count %lld", + my_instance_number, + xlat_global_counters.v4_to_v6_tcp_invalid_uidb_drop_count); + + PLATFORM_DEBUG_PRINT("\nMy_instance %d: v6_to_v4 tcp invalid uidb drop count %lld", + my_instance_number, + xlat_global_counters.v6_to_v4_tcp_invalid_uidb_drop_count); + + PLATFORM_DEBUG_PRINT("\nMy_instance %d: v4_to_v6 udp invalid uidb drop count %lld", + my_instance_number, + xlat_global_counters.v4_to_v6_udp_invalid_uidb_drop_count); + + PLATFORM_DEBUG_PRINT("\nMy_instance %d: v6_to_v4 udp invalid uidb drop count %lld", + my_instance_number, + xlat_global_counters.v6_to_v4_udp_invalid_uidb_drop_count); + + PLATFORM_DEBUG_PRINT("\nMy_instance %d: v4_to_v6 udp crc0 invld uidb drop count %lld", + my_instance_number, + xlat_global_counters.v4_to_v6_udp_crc_zero_invalid_uidb_drop_count); + + PLATFORM_DEBUG_PRINT("\n"); + } + + +} + +void spp_log_p2mp_req(spp_api_cnat_p2mp_debug_request_t *mp) +{ + u8 i = 0; + u32 num_rec = spp_net_to_host_byte_order_32(&mp->param[i++]); + u32 err_c_num_args; + + while (num_rec--) { + u8 j = 0; + u16 err_c; + u16 num_args; + u32 argv[32]; + + err_c_num_args = spp_net_to_host_byte_order_32(&mp->param[i++]); + err_c = (err_c_num_args >> 16) & 0xFFFF; + num_args = err_c_num_args & 0xFFFF; + + num_args = (num_args <= 32) ? num_args : 32; + while (j < num_args) { + argv[j++] = spp_net_to_host_byte_order_32(&mp->param[i++]); + } + + i += ((num_args - 32) > 0) ? (num_args - 32) : 0; + spp_printf(err_c, num_args, argv); + } +} + +void nat64_debug_addr_pool_add_del() +{ + cnat_portmap_v2_t *my_pm = NULL; + cnat_portmap_v2_t *pm = NULL; + u32 len, i, pm_len; + + PLATFORM_DEBUG_PRINT("\n sizeof port_map =%d\n", sizeof( cnat_portmap_v2_t)); + len = 10; + PLATFORM_DEBUG_PRINT("\n adding 10 entries in vector 1-10\n "); + vec_add2(pm, my_pm, len); + pm = my_pm; + + PLATFORM_DEBUG_PRINT(" pm =%p , my_pm = %p\n", pm, my_pm); + for(i=0;iipv4_address = i+1; + my_pm++; + } + PLATFORM_DEBUG_PRINT(" pm =%p , my_pm = %p\n", pm, my_pm); + + pm_len = vec_len(pm); + PLATFORM_DEBUG_PRINT("\n printing vector contents : vec_len = %d \n", pm_len); + my_pm = pm; + for(i=0;iipv4_address); + my_pm++; + } + PLATFORM_DEBUG_PRINT(" pm =%p , my_pm = %p\n", pm, my_pm); + + PLATFORM_DEBUG_PRINT("\n adding 5 entries in vector 11-15\n "); + len = 5; + vec_add2(pm, my_pm, len); + + PLATFORM_DEBUG_PRINT(" pm =%p , my_pm = %p\n", pm, my_pm); + for(i=0;iipv4_address = 11+i; + my_pm++; + } + + PLATFORM_DEBUG_PRINT(" pm =%p , my_pm = %p\n", pm, my_pm); + pm_len = vec_len(pm); + PLATFORM_DEBUG_PRINT("\n printing vector contents : vec_len = %d \n", pm_len); + my_pm = pm; + for(i=0;iipv4_address); + my_pm++; + } + PLATFORM_DEBUG_PRINT(" pm =%p , my_pm = %p\n", pm, my_pm); + + PLATFORM_DEBUG_PRINT("\n adding 6 entries in vector 16-21\n "); + len = 6; + vec_add2(pm, my_pm, len); + PLATFORM_DEBUG_PRINT(" pm =%p , my_pm = %p\n", pm, my_pm); + for(i=0;iipv4_address = 16+i; + my_pm++; + } + + PLATFORM_DEBUG_PRINT(" pm =%p , my_pm = %p\n", pm, my_pm); + pm_len = vec_len(pm); + PLATFORM_DEBUG_PRINT("\n printing vector contents : vec_len = %d \n", pm_len); + my_pm = pm; + for(i=0;iipv4_address); + my_pm++; + } + + PLATFORM_DEBUG_PRINT(" pm =%p , my_pm = %p\n", pm, my_pm); + PLATFORM_DEBUG_PRINT("\nDeleting 7 entries starting from entry value=8\n"); + pm_len = vec_len(pm); + my_pm = pm; + PLATFORM_DEBUG_PRINT(" pm_len =%d\n", pm_len); + for(i=0;iipv4_address == 8){ + PLATFORM_DEBUG_PRINT("\n match found brraeaking..\n"); + break; + } + my_pm++; + } + + PLATFORM_DEBUG_PRINT(" pm =%p , my_pm = %p i= %d\n", pm, my_pm, i); +// vec_delete(pm, 7, my_pm); + vec_delete(pm, 7, i); + PLATFORM_DEBUG_PRINT(" pm =%p , my_pm = %p\n", pm, my_pm); + + PLATFORM_DEBUG_PRINT(" printing entries aftr deletion from 8-14\n"); + pm_len = vec_len(pm); + PLATFORM_DEBUG_PRINT("\n printing vector contents : vec_len = %d \n", pm_len); + my_pm = pm; + for(i=0;iipv4_address); + my_pm++; + } + + + PLATFORM_DEBUG_PRINT(" pm =%p , my_pm = %p\n", pm, my_pm); + + PLATFORM_DEBUG_PRINT("\nadding deleted items again 8-14\n"); + len =7; + vec_add2(pm, my_pm, len); + + PLATFORM_DEBUG_PRINT(" pm =%p , my_pm = %p\n", pm, my_pm); + for(i=0;iipv4_address = 8+i; + my_pm++; + } + + PLATFORM_DEBUG_PRINT(" pm =%p , my_pm = %p\n", pm, my_pm); + pm_len = vec_len(pm); + PLATFORM_DEBUG_PRINT("\n printing vector contents : vec_len = %d \n", pm_len); + my_pm = pm; + for(i=0;iipv4_address); + my_pm++; + } + PLATFORM_DEBUG_PRINT(" pm =%p , my_pm = %p\n", pm, my_pm); + PLATFORM_DEBUG_PRINT("\n"); +} + + +void uidb_mapping_dump_timeout() { + + u32 i; + + PLATFORM_DEBUG_PRINT("\nCGSE uidb mapping table \n"); + for(i = 0;i < 30;i++) { + PLATFORM_DEBUG_PRINT("%d ",*(cgse_uidb_index_cgse_id_mapping_ptr + i)); + } + +} + +void nat64_debug_dump_info(u32 debug_value) +{ + + switch(debug_value) { + + case 1 : + bib_add_v6_entry1(); + break; + + case 2 : + bib_add_v6_entry2(); + break; + + case 3 : + bib_add_v6_entry1_new(); + break; + + case 4 : + bib_add_v6_entry1_new_static(); + break; + + case 5 : + bib_add_v6_entry3(); + break; + + case 6 : + bib_add_v6_entry_new2(); + break; + + case 7 : + nat64_fill_table_entry(); + break; + + case 10 : + nat64_db_dump_main(); + break; + + case 11 : + nat64_db_dump_user(); + break; + + case 12 : + nat64_db_dump_session(); + break; + + case 13 : + nat64_dump_table(); + break; + + case 14 : + bib_del_v6_entry1_static(); + break; + + case 15 : + nat64_debug_addr_pool_add_del(); + break; + + case 16 : + nat64_db_dump_timeout(0); + break; + + case 17 : + uidb_mapping_dump_timeout(); + break; + + default : break; + } +} + + +void cnat_debug_flags_set (spp_api_cnat_p2mp_debug_request_t *mp) +{ + u32 debug_variable = spp_net_to_host_byte_order_32(&mp->param[0]); + u32 debug_value = spp_net_to_host_byte_order_32(&mp->param[1]); + + cnat_key_t t_key; + + switch (debug_variable) { + + case CNAT_DEBUG_FLAG_UDP_INSIDE_CHECKSUM_DISABLE: + udp_inside_checksum_disable = debug_value; + PLATFORM_DEBUG_PRINT("\nudp_inside_checksum_disable set to %d\n", debug_value); + break; + + case CNAT_DEBUG_FLAG_UDP_OUTSIDE_CHECKSUM_DISABLE: + udp_outside_checksum_disable = debug_value; + PLATFORM_DEBUG_PRINT("\nudp_outside_checksum_disable set to %d\n", debug_value); + break; + + case CNAT_DEBUG_FLAG_UDP_OUTSIDE_PKT_DUMP_ENABLE: + udp_outside_packet_dump_enable = debug_value; + PLATFORM_DEBUG_PRINT("\nudp_outside_packet_dump_enable set to %d\n", debug_value); + break; + + case CNAT_DEBUG_FLAG_UDP_INSIDE_PKT_DUMP_ENABLE: + udp_inside_packet_dump_enable = debug_value; + PLATFORM_DEBUG_PRINT("\nudp_inside_packet_dump_enable set to %d\n", debug_value); + break; + + case CNAT_DEBUG_FLAG_ICMP_PKT_DUMP_ENABLE: + icmp_debug_flag = debug_value; + PLATFORM_DEBUG_PRINT("\nicmp_debug_flag set to %d\n", debug_value); + break; + + case CNAT_DEBUG_FLAG_FRAG_PKT_DUMP_ENABLE: + frag_debug_flag = debug_value; + PLATFORM_DEBUG_PRINT("\nfrag_debug_flag set to %d\n", debug_value); + break; + + case CNAT_DEBUG_FLAG_XLAT_CONFIG_DEBUG_ENABLE: + xlat_config_debug_level = debug_value; + PLATFORM_DEBUG_PRINT("\nxlat_config_debug_level set to %d\n", debug_value); + break; + + case CNAT_DEBUG_FLAG_NAT64_CONFIG_DEBUG_ENABLE: + nat64_config_debug_level = debug_value; + PLATFORM_DEBUG_PRINT("\nnat64_config_debug_level set to %d\n", debug_value); + nat64_debug_dump_info(debug_value); + break; + + case CNAT_DEBUG_FLAG_NAT64_DATA_PATH_DEBUG_ENABLE: + nat64_data_path_debug_level = debug_value; + PLATFORM_DEBUG_PRINT("\nnat64_data_path_debug_level set to %d\n", debug_value); + break; + + case CNAT_DEBUG_FLAG_DSLITE_CONFIG_DEBUG_ENABLE: + ds_lite_config_debug_level = debug_value; + PLATFORM_DEBUG_PRINT("\nds_lite_config_debug_level set to %d\n", debug_value); + break; + + case CNAT_DEBUG_FLAG_XLAT_DATA_PATH_DEBUG_ENABLE: + xlat_data_path_debug_level = debug_value; + PLATFORM_DEBUG_PRINT("\nxlat_data_path_debug_level set to %d\n", debug_value); + break; + + case CNAT_DEBUG_FLAG_CONFIG_DEBUG_ENABLE: + config_debug_level = debug_value; + + PLATFORM_DEBUG_PRINT("\nconfig_debug_level set to %d\n", debug_value); + break; + + case CNAT_DEBUG_FLAG_CONFIG_PPTP_ENABLE: + cnat_pptp_debug_flag = debug_value; + + if(debug_value == 0) { + pptp_dump_counters(); + } + + PLATFORM_DEBUG_PRINT("\ncnat_pptp_debug_level set to %d\n", debug_value); + break; + + case CNAT_DEBUG_FLAG_CONFIG_PCP_ENABLE: + cnat_pcp_debug_flag = debug_value; + + if(debug_value == 0) { + pcp_dump_counters(); + } + PLATFORM_DEBUG_PRINT("\ncnat_pcp_debug_level set to %d\n", debug_value); + break; + + case CNAT_DEBUG_FLAG_GLOBAL_DEBUG_ALL_ENABLE: + global_debug_flag = debug_value; + PLATFORM_DEBUG_PRINT("\nglobal_debug_flag set to %d\n", debug_value); + break; + + case CNAT_DEBUG_FLAG_SUMMARY_STATS_DEBUG_ENABLE: + summary_stats_debug_flag = debug_value; + PLATFORM_DEBUG_PRINT("\nsummary_stats_debug_flag set to %d\n", debug_value); + break; + + case CNAT_DEBUG_FLAG_SHOW_DEBUG_ENABLE: + show_debug_level = debug_value; + PLATFORM_DEBUG_PRINT("\nshow_debug_level set to %d\n", debug_value); + break; + + case CNAT_DEBUG_FLAG_TCP_LOGGING_ENABLE: + tcp_debug_logging_enable_disable(debug_value); + break; + case CNAT_DEBUG_FLAG_V6RD_DATA_PATH_DEBUG_ENABLE: + v6rd_data_path_debug_level = debug_value; + PLATFORM_DEBUG_PRINT("\nv6rd_data_path_debug_level set to %d\n", debug_value); + break; + case CNAT_DEBUG_FLAG_V6RD_CONFIG_DEBUG_ENABLE: + v6rd_config_debug_level = debug_value; + PLATFORM_DEBUG_PRINT("\nv6rd_config_debug_level set to %d\n", debug_value); + break; + case CNAT_DEBUG_FLAG_V6RD_DEFRAG_DEBUG_ENABLE: + /* set debug atleast to 1, so that critical errors are always + * enabled + */ + v6rd_defrag_debug_level = debug_value ? debug_value : 1; + PLATFORM_DEBUG_PRINT("\nv6rd_config_debug_level set to %d\n", debug_value); + break; + + + case CNAT_DEBUG_SET_STATIC_PORT_RANGE: + PLATFORM_DEBUG_PRINT("\nChange Static Port Range from %d --> %d\n", + cnat_static_port_range, debug_value); + cnat_static_port_range = debug_value; + break; + + case CNAT_DEBUG_FLAG_DSLITE_DP_ENABLE: + PLATFORM_DEBUG_PRINT("\n Changing dslite debug flag from %d --> %d\n", + dslite_debug_level, debug_value); + dslite_debug_level = debug_value; + break; + + case CNAT_DEBUG_FLAG_NFV9_LOGGING_DUMP_ENABLE: + nfv9_logging_debug_flag = debug_value; + PLATFORM_DEBUG_PRINT("\nnfv9_logging_debug_flag set to %d\n", debug_value); + break; + + case CNAT_DEBUG_FLAG_SYSLOG_LOGGING_DUMP_ENABLE: + syslog_debug_flag = debug_value; + PLATFORM_DEBUG_PRINT("\nsyslog_debug_flag set to %d\n", debug_value); + break; + + case CNAT_DEBUG_FLAG_MAPE_CONFIG_DEBUG_ENABLE: + mape_config_debug_level = debug_value; + PLATFORM_DEBUG_PRINT("\nmape_config_debug_level set to %d\n", debug_value); + break; + + case CNAT_DEBUG_FLAG_MAPE_DATA_PATH_DEBUG_ENABLE: + mape_data_path_debug_level = debug_value; + PLATFORM_DEBUG_PRINT("\nmape_data_path_debug_level set to %d\n", debug_value); + break; + + case CNAT_DEBUG_FLAGS_DUMP: + default: + { + PLATFORM_DEBUG_PRINT("\nCurrent values of Debug Variables\n"); + PLATFORM_DEBUG_PRINT("\nTo modify an item chose its index and provide the value\n"); + PLATFORM_DEBUG_PRINT("\n%d: udp_inside_checksum_disable %d\n", + CNAT_DEBUG_FLAG_UDP_INSIDE_CHECKSUM_DISABLE, + udp_inside_checksum_disable); + PLATFORM_DEBUG_PRINT("%d: udp_outside_checksum_disable %d\n", + CNAT_DEBUG_FLAG_UDP_OUTSIDE_CHECKSUM_DISABLE, + udp_outside_checksum_disable); + PLATFORM_DEBUG_PRINT("%d: udp_inside_packet_dump_enable %d\n", + CNAT_DEBUG_FLAG_UDP_OUTSIDE_PKT_DUMP_ENABLE, + udp_inside_packet_dump_enable); + PLATFORM_DEBUG_PRINT("%d: udp_outside_packet_dump_enable %d\n", + CNAT_DEBUG_FLAG_UDP_INSIDE_PKT_DUMP_ENABLE, + udp_outside_packet_dump_enable); + PLATFORM_DEBUG_PRINT("%d: icmp_debug_flag %d\n", + CNAT_DEBUG_FLAG_ICMP_PKT_DUMP_ENABLE, + icmp_debug_flag); + PLATFORM_DEBUG_PRINT("%d: frag_debug_flag %d\n", + CNAT_DEBUG_FLAG_FRAG_PKT_DUMP_ENABLE, + frag_debug_flag); + PLATFORM_DEBUG_PRINT("%d: config_debug_level %d\n", + CNAT_DEBUG_FLAG_CONFIG_DEBUG_ENABLE, + config_debug_level); + PLATFORM_DEBUG_PRINT("%d: global_debug_flag %d\n", + CNAT_DEBUG_FLAG_GLOBAL_DEBUG_ALL_ENABLE, + global_debug_flag); + PLATFORM_DEBUG_PRINT("%d: summary_stats_debug_flag %d\n", + CNAT_DEBUG_FLAG_SUMMARY_STATS_DEBUG_ENABLE, + summary_stats_debug_flag); + PLATFORM_DEBUG_PRINT("%d: show_debug_level %d\n", + CNAT_DEBUG_FLAG_SHOW_DEBUG_ENABLE, + show_debug_level); + PLATFORM_DEBUG_PRINT("%d: xlat_config_debug_level %d\n", + CNAT_DEBUG_FLAG_XLAT_CONFIG_DEBUG_ENABLE, + xlat_config_debug_level); + PLATFORM_DEBUG_PRINT("%d: xlat_data_path_debug_level %d\n", + CNAT_DEBUG_FLAG_XLAT_DATA_PATH_DEBUG_ENABLE, + xlat_data_path_debug_level); + PLATFORM_DEBUG_PRINT("%d: tcp_logging_enable_flag %d\n", + CNAT_DEBUG_FLAG_TCP_LOGGING_ENABLE, + tcp_logging_enable_flag); + PLATFORM_DEBUG_PRINT(" tcp_logging_enable_options DISABLE %d, ENABLE %d, PKT_DUMP %d, SUMMARY_DUMP %d\n", + TCP_LOGGING_DISABLE, TCP_LOGGING_ENABLE, + TCP_LOGGING_PACKET_DUMP, TCP_LOGGING_SUMMARY_DUMP); + PLATFORM_DEBUG_PRINT("%d: nfv9_logging_debug_flag %d\n", + CNAT_DEBUG_FLAG_NFV9_LOGGING_DUMP_ENABLE, + nfv9_logging_debug_flag); + PLATFORM_DEBUG_PRINT("%d: syslog_debug_flag %d\n", + CNAT_DEBUG_FLAG_SYSLOG_LOGGING_DUMP_ENABLE, + syslog_debug_flag); + PLATFORM_DEBUG_PRINT("%d: cnat_static_port_range %d\n", + CNAT_DEBUG_SET_STATIC_PORT_RANGE, + cnat_static_port_range); + PLATFORM_DEBUG_PRINT("%d: v6rd_data_path_debug_level %d\n", + CNAT_DEBUG_FLAG_V6RD_DATA_PATH_DEBUG_ENABLE, + v6rd_data_path_debug_level); + PLATFORM_DEBUG_PRINT("%d: v6rd_config_debug_level %d\n", + CNAT_DEBUG_FLAG_V6RD_CONFIG_DEBUG_ENABLE, + v6rd_config_debug_level); + PLATFORM_DEBUG_PRINT("%d: v6rd_defrag_debug_level %d\n", + CNAT_DEBUG_FLAG_V6RD_DEFRAG_DEBUG_ENABLE, + v6rd_defrag_debug_level); + PLATFORM_DEBUG_PRINT("%d: nat64_stful_debug %d\n", + CNAT_DEBUG_FLAG_NAT64_CONFIG_DEBUG_ENABLE, + nat64_config_debug_level); + PLATFORM_DEBUG_PRINT("%d: nat64_data_path_debug_level %d\n", + CNAT_DEBUG_FLAG_NAT64_DATA_PATH_DEBUG_ENABLE, + nat64_data_path_debug_level); + PLATFORM_DEBUG_PRINT("%d: dslite_debug_level %d\n", + CNAT_DEBUG_FLAG_DSLITE_DP_ENABLE, + dslite_debug_level); + PLATFORM_DEBUG_PRINT("%d: ds_lite_config_debug_level %d\n", + CNAT_DEBUG_FLAG_DSLITE_CONFIG_DEBUG_ENABLE, + ds_lite_config_debug_level); + PLATFORM_DEBUG_PRINT("%d: mape_config_debug_level %d\n", + CNAT_DEBUG_FLAG_MAPE_CONFIG_DEBUG_ENABLE, + mape_config_debug_level); + PLATFORM_DEBUG_PRINT("%d: mape_data_path_debug_level %d\n", + CNAT_DEBUG_FLAG_MAPE_DATA_PATH_DEBUG_ENABLE, + mape_data_path_debug_level); + } + break; + } +} + +extern void dump_cnat_frag_stats(void); + +void spp_api_cnat_p2mp_debug_request_t_handler +(spp_api_cnat_p2mp_debug_request_t *mp) +{ + u16 command_type; + +/* + if (mp->core_num != my_instance_number) { + mp->rc = CNAT_NOT_THIS_CORE; + return; + } +*/ + + command_type = spp_net_to_host_byte_order_16(&mp->dump_type); + PLATFORM_DEBUG_PRINT("-->> Core%d: Received debug msg ... cmd type: %d\n", + my_instance_number, command_type); + + switch (command_type) { + + case CNAT_DEBUG_GENERIC_COMMAND_DUMP_POLICY: + PLATFORM_DEBUG_PRINT("Core%d: policy\n", my_instance_number); + cnat_db_dump_policy(); + break; + + case CNAT_DEBUG_GENERIC_COMMAND_DUMP_MAIN_DB: + PLATFORM_DEBUG_PRINT("Core%d: Main db\n", my_instance_number); + cnat_db_dump_main(); + break; + + case CNAT_DEBUG_GENERIC_COMMAND_DUMP_MAIN_DB_SUMMARY: + PLATFORM_DEBUG_PRINT("Core%d: Main db Summary\n", my_instance_number); + cnat_db_dump_main_summary(); + break; + + case CNAT_DEBUG_GENERIC_COMMAND_DUMP_USER_DB: + PLATFORM_DEBUG_PRINT("Core%d: User db\n", my_instance_number); + cnat_db_dump_user(); + break; + + case CNAT_DEBUG_GENERIC_COMMAND_DUMP_USER_DB_SUMMARY: + PLATFORM_DEBUG_PRINT("Core%d: User db Summary\n", my_instance_number); + cnat_db_dump_user_summary(); + break; + + case CNAT_DEBUG_GENERIC_COMMAND_DUMP_HASHES_DB: + PLATFORM_DEBUG_PRINT("Core%d: Hashes db\n", my_instance_number); + cnat_db_dump_hashes(); + break; + + case CNAT_DEBUG_GENERIC_COMMAND_DUMP_VRF_MAP: + PLATFORM_DEBUG_PRINT("Core%d: Vrf map \n", my_instance_number); + cnat_db_dump_portmaps(); + break; + + case CNAT_DEBUG_GENERIC_COMMAND_DUMP_SUMMARY_DB: + PLATFORM_DEBUG_PRINT("Core%d: dump summary DB \n", my_instance_number); + cnat_db_summary(); + break; + + case CNAT_DEBUG_GENERIC_COMMAND_DUMP_STATS: + PLATFORM_DEBUG_PRINT("Core%d: dump stats \n", my_instance_number); + spp_node_print_stats(1, NULL); + break; + + /* Currently does same as clear node ctr, may change */ + case CNAT_DEBUG_GENERIC_COMMAND_CLEAR_STATS: + PLATFORM_DEBUG_PRINT("Core%d: clear stats \n", my_instance_number); + spp_node_clear_stats(); + break; + + case CNAT_DEBUG_SPP_LOG: + PLATFORM_DEBUG_PRINT("Core%d: SPP LOG \n", my_instance_number); + spp_log_p2mp_req(mp); + break; + + case CNAT_DEBUG_GENERIC_COMMAND_DUMP_NODE_COUNTER: + PLATFORM_DEBUG_PRINT("Core%d: NODE Counter dump \n", my_instance_number); + spp_node_print_counters(); + break; + + case CNAT_DEBUG_GENERIC_COMMAND_CLEAR_NODE_COUNTER: + PLATFORM_DEBUG_PRINT("Core%d: clear node counter \n", my_instance_number); + spp_node_clear_stats(); + break; + + case CNAT_DEBUG_GENERIC_COMMAND_DUMP_CNAT_COUNTER: + PLATFORM_DEBUG_PRINT("Core%d: CNAT Counter dump \n", my_instance_number); + spp_node_print_cnat_counters(); + break; + + case CNAT_DEBUG_GENERIC_COMMAND_DUMP_VA: + PLATFORM_DEBUG_PRINT("Core%d: VA dump \n", my_instance_number); + { + int argc = 1; + u32 arg[2] = {spp_net_to_host_byte_order_32(&mp->param[0]), 0}; + + cnat_va_dump(argc, arg); + } + break; + + case CNAT_DEBUG_GENERIC_COMMAND_SHOW_CONFIG: + PLATFORM_DEBUG_PRINT("Core%d: Show config dump \n", my_instance_number); + { + int argc = 0; + unsigned long arg[3]; + + if (arg[argc++] = spp_net_to_host_byte_order_32(&mp->param[0])) { + if (arg[argc++] = spp_net_to_host_byte_order_32(&mp->param[1])) { + ; + } else { + argc--; + } + } + + cnat_show_cdb_command_v2(argc, arg); +/* + xlat_show_config(); + cnat_alg_show(); +*/ + v6rd_show_config(); + dslite_show_config(); + nat64_dump_table(); + mape_show_config(); + } + break; + + case CNAT_DEBUG_GENERIC_COMMAND_SHOW_NFV9: + PLATFORM_DEBUG_PRINT("Core%d: NFv9 dump \n", my_instance_number); + #if 0 /* Currently not calling this */ + cnat_nfv9_show_cmd(); + #endif + break; + + case CNAT_DEBUG_GENERIC_COMMAND_SHOW_IVRF: + PLATFORM_DEBUG_PRINT("Core%d: IVRF dump \n", my_instance_number); + { + int argc = 0; + unsigned long arg[3]; + + if (arg[argc++] = spp_net_to_host_byte_order_32(&mp->param[0])) { + if (arg[argc++] = spp_net_to_host_byte_order_32(&mp->param[1])) { + if (arg[argc++] = spp_net_to_host_byte_order_32(&mp->param[2])) { + ; + } else { + argc--; + } + } else { + argc--; + } + } + + + PLATFORM_DEBUG_PRINT("VRF: %d \n", spp_net_to_host_byte_order_32(&mp->param[0])); + PLATFORM_DEBUG_PRINT("2nd arg: %d \n", + spp_net_to_host_byte_order_32(&mp->param[1])); + + cnat_show_ivrf_command_v2(argc, arg); + } + break; + + case CNAT_DEBUG_GENERIC_COMMAND_SHOW_OVRF: + PLATFORM_DEBUG_PRINT("Core%d: OVRF dump \n", my_instance_number); + { + int argc = 0; + unsigned long arg[3]; + if (arg[argc++] = spp_net_to_host_byte_order_32(&mp->param[0])) { + if (arg[argc++] = spp_net_to_host_byte_order_32(&mp->param[1])) { + if (arg[argc++] = spp_net_to_host_byte_order_32(&mp->param[2])) { + ; + } else { + argc--; + } + } else { + argc--; + } + } + + PLATFORM_DEBUG_PRINT("VRF: %d \n", spp_net_to_host_byte_order_32(&mp->param[0])); + PLATFORM_DEBUG_PRINT("2nd arg: %d \n", + spp_net_to_host_byte_order_32(&mp->param[1])); + + cnat_show_ovrf_command_v2(argc, arg); + } + break; + + case CNAT_DEBUG_GENERIC_COMMAND_DEBUG_OPTIONS: + PLATFORM_DEBUG_PRINT("Core%d: Debug option dump \n", my_instance_number); + { + global_pd_dbg_lvl = 0; + global_pi_dbg_lvl = 0; + global_l2_dbg_lvl = 0; + + global_pd_dbg_lvl = + spp_net_to_host_byte_order_32(&mp->param[0]); + global_pi_dbg_lvl = + spp_net_to_host_byte_order_32(&mp->param[1]); + global_l2_dbg_lvl = + spp_net_to_host_byte_order_32(&mp->param[2]); + + PLATFORM_DEBUG_PRINT("global_pd_dbg_lvl: %d, global_pi_dbg_lvl: %d, global_l2_dbg_lvl: %d\n", + global_pd_dbg_lvl, global_pi_dbg_lvl, global_l2_dbg_lvl); + } + break; + + case CNAT_DEBUG_GENERIC_COMMAND_DUMP_DEBUG_LEVELS: + PLATFORM_DEBUG_PRINT("Core%d: PD Debug level: %d \n", my_instance_number, global_pd_dbg_lvl); + PLATFORM_DEBUG_PRINT("Core%d: PI Debug level: %d \n", my_instance_number, global_pi_dbg_lvl); + PLATFORM_DEBUG_PRINT("Core%d: L2 Debug level: %d \n", my_instance_number, global_l2_dbg_lvl); + break; + + case CNAT_DEBUG_GENERIC_COMMAND_DEBUG_FLAGS: + PLATFORM_DEBUG_PRINT("Core%d: Debug flags \n", my_instance_number); + cnat_debug_flags_set(mp); + break; + + case CNAT_READ_TEMP_SENSORS: + PLATFORM_INIT_TEMP_SENSORS(); + PLATFORM_READ_CPU_SENSORS(TEMPERATURE_SENSOR_TEST_MODE); + break; + + case CNAT_BLOCK_OCTEON_SENSOR_READ: + + PLATFORM_SET_TEMP_READ_BLOCK(temperature_read_blocked , mp); +#ifdef TARGET_RODDICK + temperature_read_blocked = + spp_net_to_host_byte_order_32(&mp->param[0]); +#endif + break; + + case CNAT_DEBUG_TIMEOUT_DB_SUMMARY: + cnat_db_dump_timeout(); + break; + + /* This option has to be removed later */ + case CNAT_DEBUG_SET_BULK_SIZE: + PLATFORM_DEBUG_PRINT("\nSetting bulk size to %d\n", + spp_net_to_host_byte_order_32(&mp->param[0])); + set_bulk_size_to_all_vrfs( + spp_net_to_host_byte_order_32(&mp->param[0])); + break; + + case CNAT_DEBUG_SHOW_BULK_STAT: + show_bulk_port_stats(); + break; + + case CNAT_DEBUG_CLEAR_BULK_STAT: + clear_bulk_port_stats(); + break; + + case CNAT_DEBUG_SHOW_BULK_ALLOC: + { + u16 in_vrfid = spp_net_to_host_byte_order_32(&mp->param[0]); + u32 inside_ip = spp_net_to_host_byte_order_32(&mp->param[1]); + show_bulk_port_allocation(in_vrfid, inside_ip); + } + break; + + case CNAT_DEBUG_NAT44_IN2OUT_FRAG_STATS: + dump_cnat_frag_stats(); + break; + + default: + mp->rc = CNAT_ERR_INVALID_MSG_ID; + break; + } + + mp->rc = CNAT_SUCCESS; + return; +} + + +void spp_api_cnat_v4_debug_in2out_private_addr_t_handler +(spp_api_cnat_v4_debug_in2out_private_addr_t *mp) +{ + u16 i_vrf; + u32 debug_flag; + u32 start_addr, end_addr; + + + start_addr = + spp_net_to_host_byte_order_32(&mp->start_addr); + end_addr = + spp_net_to_host_byte_order_32(&mp->end_addr); + i_vrf = + spp_net_to_host_byte_order_16(&mp->i_vrf); + debug_flag = + spp_net_to_host_byte_order_32(&mp->debug_flag); + + if ((i_vrf > MAX_UIDX) || (start_addr > end_addr) || + ((debug_flag != CNAT_DEBUG_NONE) && + ((debug_flag & CNAT_DEBUG_ALL) == CNAT_DEBUG_NONE))) { + mp->rc = CNAT_ERR_PARSER; + PLATFORM_DEBUG_PRINT("invalid debug ivrf 0x%x flag 0x%x " + "start addr 0x%x end addr 0x%x\n", + i_vrf, debug_flag, + start_addr, end_addr); + return; + } + + PLATFORM_DEBUG_PRINT("debug ivrf 0x%x flag 0x%x " + "start addr 0x%x end addr 0x%x\n", + i_vrf, debug_flag, + start_addr, end_addr); + + mp->rc = CNAT_SUCCESS; + debug_i_vrf = i_vrf; + debug_i_flag = debug_flag; + debug_i_addr_start = start_addr; + debug_i_addr_end = end_addr; + +} + +void spp_api_cnat_v4_debug_out2in_public_addr_t_handler +(spp_api_cnat_v4_debug_out2in_public_addr_t *mp) +{ + u16 o_vrf; + u32 debug_flag; + u32 start_addr, end_addr; + + start_addr = + spp_net_to_host_byte_order_32(&mp->start_addr); + end_addr = + spp_net_to_host_byte_order_32(&mp->end_addr); + o_vrf = + spp_net_to_host_byte_order_16(&mp->o_vrf); + debug_flag = + spp_net_to_host_byte_order_32(&mp->debug_flag); + + if ((o_vrf > MAX_UIDX) || (start_addr > end_addr) || + ((debug_flag != CNAT_DEBUG_NONE) && + ((debug_flag & CNAT_DEBUG_ALL) == CNAT_DEBUG_NONE))) { + mp->rc = CNAT_ERR_PARSER; + PLATFORM_DEBUG_PRINT("invalid debug ovrf 0x%x flag 0x%x " + "start addr 0x%x end addr 0x%x\n", + o_vrf, debug_flag, + start_addr, end_addr); + return; + } + + mp->rc = CNAT_SUCCESS; + debug_o_vrf = o_vrf; + debug_o_flag = debug_flag; + debug_o_addr_start = start_addr; + debug_o_addr_end = end_addr; + + PLATFORM_DEBUG_PRINT(" o2i debug currently is not supported\n"); +} + +void nat64_reset_session_expiry(nat64_bib_entry_t *db) +{ + NAT64_STFUL_DEBUG_PRINT(3, " invoking nat64_clean_bib_db_entry\n " ); + nat64_clean_bib_db_entry(db); + NAT64_STFUL_DEBUG_PRINT(3, "done with clean_bib_db_entry\n " ); +} + +void spp_api_nat64_clear_db_request_t_handler +(spp_api_nat64_clear_db_request_t *mp) +{ + u16 port, proto, flag; + u32 index; + u32 i; + nat64_bib_entry_t* db; + nat64_v6_key_t ki; + nat64_table_entry_t *my_nat64_table_db_ptr; + u16 nat64_id; + + NAT64_STFUL_FUNC_ENTER; + NAT64_STFUL_DEBUG_DUMP_MSG(mp); + + nat64_id = spp_net_to_host_byte_order_16(&mp->nat64_id); + my_nat64_table_db_ptr = nat64_table_ptr + nat64_id; + + port = spp_net_to_host_byte_order_16(&mp->port_num); + proto = mp->protocol; + + ki.vrf = nat64_id; + ki.vrf |= ((u16)proto << CNAT_PRO_SHIFT); + + for(i =0 ; i< 4 ; i++) + ki.ipv6[i] = spp_net_to_host_byte_order_32(&mp->ip_addr[i]); + + ki.port = port; + + flag = mp->flags; + + mp->rc = CNAT_SUCCESS; + + NAT64_STFUL_DEBUG_PRINT(3, "\n Nat64_id = %d, port =%d, \ + proto =%d, flags=0x%08X",\ + nat64_id, port, proto, flag); + + NAT64_STFUL_DEBUG_PRINT(3, "\n IPv6 Addr = %08X : %08X: %08X: %08X",\ + ki.ipv6[0], ki.ipv6[1], ki.ipv6[2], ki.ipv6[3]); + + if (flag == CNAT_DB_CLEAR_SPECIFIC) { + NAT64_STFUL_DEBUG_PRINT(3, "\n clear specific \n"); + + db = nat64_bib_db_lookup_entry(&ki); + if (db == NULL) { + NAT64_STFUL_DEBUG_PRINT(3, "\n clear specific - not present\n"); + mp->rc = CNAT_NOT_FOUND_ANY; + return; + } + + if( !(db->flags & CNAT_DB_NAT64_FLAG) || + (db->nat64_inst_id != nat64_id)) + return; + + + nat64_reset_session_expiry(db); + return; + } + + pool_header_t *p = pool_header(nat64_bib_db); + + for(index = 0; index < vec_len(nat64_bib_db); index++) { + + /* check is it nat44, if yes skip , do it n nat44 as well */ + + if (PREDICT_FALSE(!clib_bitmap_get(p->free_bitmap, index))) { + db = nat64_bib_db + index; + + if( !(db->flags & CNAT_DB_NAT64_FLAG) || + (db->nat64_inst_id != nat64_id)) + continue; + + if (flag == CNAT_DB_CLEAR_ALL) { + nat64_reset_session_expiry(db); + continue; + } + + if (flag & CNAT_DB_CLEAR_ADDR) { + if ((db->v6_in_key.ipv6[0] != ki.ipv6[0]) || + (db->v6_in_key.ipv6[1] != ki.ipv6[1]) || + (db->v6_in_key.ipv6[2] != ki.ipv6[2]) || + (db->v6_in_key.ipv6[3] != ki.ipv6[3])){ + NAT64_STFUL_DEBUG_PRINT(3, "\n%s:%d\n", __FUNCTION__, \ + __LINE__ ); + continue; + } + } + + if (flag & CNAT_DB_CLEAR_PROTO) { + if (((db->v6_in_key.vrf & CNAT_PRO_MASK) >> CNAT_PRO_SHIFT) + != proto) { + NAT64_STFUL_DEBUG_PRINT(3, "\n%s:%d\n", __FUNCTION__, \ + __LINE__ ); + continue; + } + } + + if (flag & CNAT_DB_CLEAR_PORT) { + if (db->v6_in_key.port != port) { + NAT64_STFUL_DEBUG_PRINT(3, "\n%s:%d\n", __FUNCTION__, \ + __LINE__ ); + continue; + } + } + + NAT64_STFUL_DEBUG_PRINT(3, "\n%s:%d\n", __FUNCTION__, \ + __LINE__ ); + /* + * Delete if the db entry matches and it is not a + */ + nat64_reset_session_expiry(db); + } + } +} + +void inline cnat_clear_session_db(cnat_main_db_entry_t *db) +{ + if(PREDICT_FALSE(db->nsessions > 1)) { + u32 session_index = db->session_head_index; + cnat_session_entry_t *sdb; + do { + sdb = cnat_session_db + session_index; + if(PREDICT_FALSE(!sdb)) { + //TO DO: Debug msg? + break; + } + sdb->entry_expires = 0; + session_index = sdb->main_list.next; + } while(session_index != db->session_head_index + && db->session_head_index != EMPTY); + } + return; +} + +#ifdef CGSE_DS_LITE +extern dslite_table_entry_t dslite_table_array[]; + +void spp_api_ds_lite_clear_db_request_t_handler +(spp_api_ds_lite_clear_db_request_t *mp) +{ + u16 port, proto, flag; + u32 index; + u32 i; + cnat_main_db_entry_t *db; + cnat_user_db_entry_t *udb; + dslite_key_t ki; + dslite_table_entry_t *my_table_db_ptr; + u16 id; + u16 i_vrf; + + + id = spp_net_to_host_byte_order_16(&mp->ds_lite_id); + id = DS_LITE_CONFIG_TO_ARRAY_ID(id); + + my_table_db_ptr = &dslite_table_array[id]; + i_vrf = my_table_db_ptr->i_vrf; + + port = spp_net_to_host_byte_order_16(&mp->port_num); + proto = mp->protocol; + + ki.ipv4_key.k.vrf = i_vrf; + ki.ipv4_key.k.vrf |= ((u16)proto << CNAT_PRO_SHIFT); + + for(i =0 ; i< 4 ; i++) + ki.ipv6[i] = spp_net_to_host_byte_order_32(&mp->ip_addr[i]); + + ki.ipv4_key.k.port = port; + + flag = mp->flags; + + mp->rc = CNAT_SUCCESS; + + DSLITE_PRINTF(3, "\n dslite id = %d, port =%d" + "proto =%d, flags=0x%08X",\ + id, port, proto, flag); + + DSLITE_PRINTF(3, "\n IPv6 Addr = %08X : %08X: %08X: %08X",\ + ki.ipv6[0], ki.ipv6[1], ki.ipv6[2], ki.ipv6[3]); + + if (flag == CNAT_DB_CLEAR_SPECIFIC) { + DSLITE_PRINTF(3, "\n Clear specific NOT supported for DS Lite \n"); + return; + } + + pool_header_t *p = pool_header(cnat_main_db); + + for(index = 0; index < vec_len(cnat_main_db); index++) { + + /* check is it dslite entry, if not skip */ + + if (PREDICT_FALSE(!clib_bitmap_get(p->free_bitmap, index))) { + db = cnat_main_db + index; + + if( !(db->flags & CNAT_DB_DSLITE_FLAG) || + ((db->in2out_key.k.vrf & CNAT_VRF_MASK) != i_vrf) || + (db->flags & CNAT_DB_FLAG_STATIC_PORT)) { + continue; + } + + if (flag == CNAT_DB_CLEAR_ALL) { + + /* + * Make the entry time as very old (0), and wait + * for a timeout to auto-expire the entry. + */ + db->entry_expires = 0; + /* Handle sessions as well.. */ + cnat_clear_session_db(db); + continue; + } + + if (flag & CNAT_DB_CLEAR_ADDR) { + udb = cnat_user_db + db->user_index; + if(PREDICT_FALSE(!udb)) { + continue; + } + if ((udb->ipv6[0] != ki.ipv6[0]) || + (udb->ipv6[1] != ki.ipv6[1]) || + (udb->ipv6[2] != ki.ipv6[2]) || + (udb->ipv6[3] != ki.ipv6[3])) { + continue; + } + } + + if (flag & CNAT_DB_CLEAR_PROTO) { + if (((db->in2out_key.k.vrf & CNAT_PRO_MASK) >> CNAT_PRO_SHIFT) + != proto) { + continue; + } + } + + if (flag & CNAT_DB_CLEAR_PORT) { + if (db->in2out_key.k.port != port) { + continue; + } + } + + /* + * Mark for expiry in the next round of DB scan + */ + db->entry_expires = 0; + /* Handle sessions as well.. */ + cnat_clear_session_db(db); + } + } +} +#endif /* #ifdef CGSE_DS_LITE */ + +void spp_api_cnat_clear_db_request_t_handler +(spp_api_cnat_clear_db_request_t *mp) +{ + u16 i_vrf, port, proto, flag; + u32 ip_addr, index; + u64 a,b,c; + cnat_main_db_entry_t * db; + cnat_db_key_bucket_t ki; + +#if defined(TARGET_LINUX_UDVR) || defined(CNAT_PG) + i_vrf = mp->inside_vrf; + ip_addr = mp->ip_addr; + port = mp->port_num; + proto = mp->protocol; +#else + i_vrf = spp_net_to_host_byte_order_16(&mp->inside_vrf); + ip_addr = spp_net_to_host_byte_order_32(&mp->ip_addr); + port = spp_net_to_host_byte_order_16(&mp->port_num); + proto = spp_net_to_host_byte_order_16(&mp->protocol); +#endif + + + + ki.k.k.vrf = i_vrf; + ki.k.k.vrf |= ((u16)proto << CNAT_PRO_SHIFT); + ki.k.k.ipv4 = ip_addr; + ki.k.k.port = port; + + flag = mp->wildcard; + + mp->rc = CNAT_SUCCESS; + + if (flag == CNAT_DB_CLEAR_SPECIFIC) { + CNAT_V4_GET_HASH(ki.k.key64, + ki.bucket, + CNAT_MAIN_HASH_MASK); + index = cnat_in2out_hash[ki.bucket].next; + if (PREDICT_TRUE(index == EMPTY)) { + mp->rc = CNAT_NOT_FOUND_ANY; + return; + } + + do { + db = cnat_main_db + index; + + /* + * Delete if the db entry matches and it is not a + * STATIC port entry + */ + if ((db->in2out_key.key64 == ki.k.key64) && + !(db->flags & CNAT_DB_FLAG_STATIC_PORT) && + !(db->flags & CNAT_DB_NAT64_FLAG) && + !(db->flags & CNAT_DB_DSLITE_FLAG)) { + + /* + * Make the entry time as very old (0), and wait + * for a timeout to auto-expire the entry. + */ + db->entry_expires = 0; + /* Handle sessions as well.. */ + cnat_clear_session_db(db); + return; + } + index = db->in2out_hash.next; + } while (index != EMPTY); + + mp->rc = CNAT_NOT_FOUND_ANY; + return; + } + + pool_header_t *p = vec_header(cnat_main_db, sizeof(pool_header_t)); + + for(index = 0; index < vec_len(cnat_main_db); index++) { + + if (PREDICT_TRUE(!clib_bitmap_get(p->free_bitmap, index))) { + db = cnat_main_db + index; + + if(PREDICT_FALSE(db->flags & CNAT_DB_NAT64_FLAG)) { + continue; + } + + if(PREDICT_FALSE(db->flags & CNAT_DB_DSLITE_FLAG)) { + continue; + } + + if (flag == CNAT_DB_CLEAR_ALL) { + if (!(db->flags & CNAT_DB_FLAG_STATIC_PORT)) { + db->entry_expires = 0; + /* Handle sessions as well.. */ + cnat_clear_session_db(db); + } + continue; + } + + if (flag & CNAT_DB_CLEAR_VRF) { + if (((db->in2out_key.k.vrf & CNAT_VRF_MASK) != i_vrf)) { + continue; + } + } + + if (flag & CNAT_DB_CLEAR_ADDR) { + if ((db->in2out_key.k.ipv4 != ip_addr)) { + continue; + } + } + + if (flag & CNAT_DB_CLEAR_PROTO) { + if (((db->in2out_key.k.vrf & CNAT_PRO_MASK) >> CNAT_PRO_SHIFT) + != proto) { + continue; + } + } + + if (flag & CNAT_DB_CLEAR_PORT) { + if (db->in2out_key.k.port != port) { + continue; + } + } + + /* + * Delete if the db entry matches and it is not a + * STATIC port entry + */ + if (!(db->flags & CNAT_DB_FLAG_STATIC_PORT)) { + db->entry_expires = 0; + /* Handle sessions as well.. */ + cnat_clear_session_db(db); + } + } + } +} + +void +spp_api_cnat_generic_command_debug (cnat_generic_command_resp *mp_resp) +{ +#ifdef SHOW_DEBUG + u32 i, j; + + i = spp_net_to_host_byte_order_32(&(mp_resp->num_bytes)); + + PLATFORM_DEBUG_PRINT("\nNum_Bytes %d\n", i); + + for (j = 0; j < i; j++) { + PLATFORM_DEBUG_PRINT("0x%02X ", mp_resp->raw_data[j]); + if ((j % 16) == 15) { + PLATFORM_DEBUG_PRINT("\n"); + } + } +#endif +} + +/* + * The following commands implements command to dump the + * user-db information + * port-map information + * for a give user source IP address + * + * The format of the output is: + * Word 0: Address of udb + * Word 1: udb->translation_list_head_index + * Word 2: + * Bytes 0..1: udb->ntranslations + * Bytes 2..2: udb->icmp_msg_coung + * Bytes 3..3: udb->unused + * Word 3: udb->portmap_index + * Word 4: udb->key.k.ipv4 + * Word 5: + * Bytes 0..1: udb->key.k.port = 0 + * Bytes 2..3: udb->key.k.vrf + * Word 6: udb->user_hash + * Word 7: Address of my_pm + * Word 8: my_pm->status + * Word 9: my_pm->inuse + * Word A: my_pm->delete_time + * Word B: my_pm->ipv4_address + */ +void spp_api_cnat_generic_command_user_db_pm +(spp_api_cnat_generic_command_request_t *mp) +{ + u32 i; + cnat_db_key_bucket_t u_ki; + u16 my_vrfmap_index; + u32 *result_array; + cnat_generic_command_resp *mp_resp; + cnat_user_db_entry_t *udb; + cnat_user_db_entry_t *mp_udb; + cnat_vrfmap_t *my_vrfmap; + cnat_portmap_v2_t *pm; + cnat_portmap_v2_t *my_pm; + + /* + * Request structure is used to send the response + */ + mp_resp = (cnat_generic_command_resp *) mp; + + u_ki.k.k.vrf = spp_net_to_host_byte_order_32(&mp->params[1]); + u_ki.k.k.ipv4 = spp_net_to_host_byte_order_32(&mp->params[2]); + u_ki.k.k.port = 0; + + udb = cnat_user_db_lookup_entry(&u_ki); + + if (!udb) { + mp_resp->num_bytes = spp_host_to_net_byte_order_32(0); + goto no_udb_found; + } + + result_array = (u32 *) (&(mp_resp->raw_data[0])); + + i = 0; + result_array[i++] = spp_host_to_net_byte_order_32((u32) udb); + + mp_udb = (cnat_user_db_entry_t *) &(result_array[i]); + + /* + * Align the entry to the next 4 byte boundary + */ + i = i + ((sizeof(cnat_user_db_entry_t)+3)/4); + + /* + * Fill in the UDB information + */ + mp_udb->translation_list_head_index = + spp_host_to_net_byte_order_32(udb->translation_list_head_index); + mp_udb->ntranslations = + spp_host_to_net_byte_order_16(udb->ntranslations); + mp_udb->icmp_msg_count = udb->icmp_msg_count; + mp_udb->flags = udb->flags; + mp_udb->portmap_index = + spp_host_to_net_byte_order_32(udb->portmap_index); + mp_udb->key.k.ipv4 = + spp_host_to_net_byte_order_32(udb->key.k.ipv4); + mp_udb->key.k.port = + spp_host_to_net_byte_order_16(udb->key.k.port); + mp_udb->key.k.vrf = + spp_host_to_net_byte_order_16(udb->key.k.vrf); + mp_udb->user_hash.next = + spp_host_to_net_byte_order_32(udb->user_hash.next); + + my_vrfmap_index = vrf_map_array[u_ki.k.k.vrf]; + my_vrfmap = cnat_map_by_vrf + my_vrfmap_index; + pm = my_vrfmap->portmap_list; + my_pm = pm + udb->portmap_index; + + /* + * Fill in the port_map information + */ + result_array[i++] = spp_host_to_net_byte_order_32((u32) my_pm); + result_array[i++] = spp_host_to_net_byte_order_32(my_pm->inuse); + result_array[i++] = spp_host_to_net_byte_order_32(my_pm->delete_time); + result_array[i++] = spp_host_to_net_byte_order_32(my_pm->ipv4_address); + + mp_resp->num_bytes = spp_host_to_net_byte_order_32(i*4); + +no_udb_found: + spp_api_cnat_generic_command_debug(mp_resp); +} + +/* + * The following commands implements command to dump the + * DB usage stats for + * main-db + * user-db + * in2out hash + * out2in hash + * + * The format of the output is: + * Word 0: Main-DB - Total + * Word 1: Main-DB - Active + * Word 2: Main-DB - Free + * Word 3: User-DB - Total + * Word 4: User-DB - Active + * Word 5: User-DB - Free + * Word 6: Hash In2Out - Size + * Word 7: Hash In2Out - Used + * Word 8: Hash In2Out - Used Percentage + * Word 9: Hash Out2In - Size + * Word A: Hash Out2In - Used + * Word B: Hash Out2In - Used Percentage + */ +void spp_api_cnat_generic_command_db_summary +(spp_api_cnat_generic_command_request_t *mp) +{ + u32 count1, count2, count3; + u32 i = 0; + u32 k = 0; + cnat_generic_command_resp *mp_resp; + u32 *result_array; + + /* + * Request structure is used to send the response + */ + mp_resp = (cnat_generic_command_resp *) mp; + result_array = (u32 *) (&(mp_resp->raw_data[0])); + + /* + * Find entries free and used in main-db + */ + count1 = vec_len(cnat_main_db); + count2 = db_free_entry(cnat_main_db); + count3 = count1 - count2; + + *(result_array + i++) = spp_host_to_net_byte_order_32(count1); + *(result_array + i++) = spp_host_to_net_byte_order_32(count3); + *(result_array + i++) = spp_host_to_net_byte_order_32(count2); + + /* + * Find entries free and used in user-db + */ + count1 = vec_len(cnat_user_db); + count2 = db_free_entry(cnat_user_db); + count3 = count1 - count2; + + *(result_array + i++) = spp_host_to_net_byte_order_32(count1); + *(result_array + i++) = spp_host_to_net_byte_order_32(count3); + *(result_array + i++) = spp_host_to_net_byte_order_32(count2); + + /* + * Find entries used in in2out and out2in hash tables + * and percentage utilization. + */ + count1 = count2 = 0; + for (k = 0; k < CNAT_MAIN_HASH_SIZE; k++) { + if(cnat_in2out_hash[k].next != ~0) count1++; + if(cnat_out2in_hash[k].next != ~0) count2++; + + } + + count3 = count1*100/CNAT_MAIN_HASH_SIZE; + + *(result_array + i++) = spp_host_to_net_byte_order_32(CNAT_MAIN_HASH_SIZE); + *(result_array + i++) = spp_host_to_net_byte_order_32(count1); + *(result_array + i++) = spp_host_to_net_byte_order_32(count3); + + count3 = count2*100/CNAT_MAIN_HASH_SIZE; + + *(result_array + i++) = spp_host_to_net_byte_order_32(CNAT_MAIN_HASH_SIZE); + *(result_array + i++) = spp_host_to_net_byte_order_32(count2); + *(result_array + i++) = spp_host_to_net_byte_order_32(count3); + + mp_resp->num_bytes = spp_host_to_net_byte_order_32(i*4); + + spp_api_cnat_generic_command_debug(mp_resp); +} + +/* + * The following commands implements generic commands such as: + * + * Command 1: + * Reads num_bytes octets from a start_locn + * generic command 0 0 0 0 0 + * + * Command 2: + * Writes upto 8 octets from a start_locn + * generic command 0 0 0 0 0 + * + * Command 3: + * Dump the db summary stats + * generic command + * + * Command 4: + * Dump the user db entry + * generic command + * + * The following structures are referenced by this command: + * typedef struct _spp_api_cnat_generic_command_request { + * u16 _spp_msg_id; + * u8 rc; + * u8 core_num; + * u32 params[8]; + * } spp_api_cnat_generic_command_request_t; + * + * typedef struct { + * u16 spp_msg_id; + * u8 rc; + * u8 core; + * u32 num_bytes; + * u8 raw_data[0]; + * } cnat_generic_command_resp; + * + */ +void spp_api_cnat_generic_command_request_t_handler +(spp_api_cnat_generic_command_request_t *mp) +{ + cnat_generic_command_resp *resp_ptr; + u32 command_type, start_locn, num_bytes; + + command_type = spp_net_to_host_byte_order_32(&mp->params[0]); + resp_ptr = (cnat_generic_command_resp *) mp; + + switch (command_type) { + case CNAT_DEBUG_GENERIC_COMMAND_READ_MEM: + start_locn = spp_net_to_host_byte_order_32(&mp->params[1]); + num_bytes = spp_net_to_host_byte_order_32(&mp->params[2]); + clib_memcpy(&(resp_ptr->raw_data[0]), (u8 *) start_locn, num_bytes); + resp_ptr->num_bytes = spp_host_to_net_byte_order_32(num_bytes); + +#ifdef SHOW_DEBUG + { + u32 i; + + for (i = 0; i < num_bytes; i++) { + PLATFORM_DEBUG_PRINT("0x%02X ", resp_ptr->raw_data[i]); + if ((i % 16) == 15) { + PLATFORM_DEBUG_PRINT("\n"); + } + } + } +#endif + break; + + case CNAT_DEBUG_GENERIC_COMMAND_WRITE_MEM: + start_locn = spp_net_to_host_byte_order_32(&mp->params[1]); + num_bytes = spp_net_to_host_byte_order_32(&mp->params[2]); + + if (num_bytes > sizeof(u64)) { + mp->rc = CNAT_ERR_INVALID_MSG_SIZE; + return; + } + + clib_memcpy((u8 *) start_locn, &(mp->params[3]), num_bytes); + resp_ptr->num_bytes = 0; + break; + + case CNAT_DEBUG_GENERIC_COMMAND_DB_SUMMARY: + spp_api_cnat_generic_command_db_summary(mp); + break; + + case CNAT_DEBUG_GENERIC_COMMAND_USER_DB_PM: + spp_api_cnat_generic_command_user_db_pm(mp); + break; + + case CNAT_DEBUG_GET_CGN_DB_SUMMARY: + spp_api_cnat_get_cgn_db_summary(mp); + break; + + default: + mp->rc = CNAT_ERR_INVALID_MSG_ID; + break; + } +} + + +static int cnat_debug_init (void *notused) +{ + spp_msg_api_set_handler(SPP_API_CNAT_V4_DEBUG_DUMMY, + spp_api_cnat_v4_debug_dummy_t_handler); + + spp_msg_api_set_handler(SPP_API_CNAT_V4_DEBUG_DUMMY_MAX, + spp_api_cnat_v4_debug_dummy_max_t_handler); + + spp_msg_api_set_handler(SPP_API_CNAT_V4_DEBUG_GLOBAL, + spp_api_cnat_v4_debug_global_t_handler); + + spp_msg_api_set_handler(SPP_API_CNAT_V4_DEBUG_IN2OUT_PRIVATE_ADDR, + spp_api_cnat_v4_debug_in2out_private_addr_t_handler); + + spp_msg_api_set_handler(SPP_API_CNAT_V4_DEBUG_OUT2IN_PUBLIC_ADDR, + spp_api_cnat_v4_debug_out2in_public_addr_t_handler); + + spp_msg_api_set_handler(SPP_API_CNAT_CLEAR_DB_REQUEST, + spp_api_cnat_clear_db_request_t_handler); + + spp_msg_api_set_handler(SPP_API_CNAT_GENERIC_COMMAND_REQUEST, + spp_api_cnat_generic_command_request_t_handler); + + spp_msg_api_set_handler(SPP_API_CNAT_P2MP_DEBUG_REQUEST, + spp_api_cnat_p2mp_debug_request_t_handler); + + spp_msg_api_set_handler(SPP_API_NAT64_CLEAR_DB_REQUEST, + spp_api_nat64_clear_db_request_t_handler); + + spp_msg_api_set_handler(SPP_API_DS_LITE_CLEAR_DB_REQUEST, + spp_api_ds_lite_clear_db_request_t_handler); + + return 0; +} + +/* +************************ +* spp_api_cnat_get_cgn_db_summary +* This is for finding out the per core CPU users and utilization +************************ +*/ + +void spp_api_cnat_get_cgn_db_summary +(spp_api_cnat_generic_command_request_t *mp) +{ + u32 total_db_entries, total_free_entries, used_entries; + u32 i = 0; + cnat_generic_command_resp *mp_resp; + u32 *result_array; + + /* + * Request structure is used to send the response + */ + mp_resp = (cnat_generic_command_resp *) mp; + result_array = (u32 *) (&(mp_resp->raw_data[0])); + + /* + * Find entries free and used in main-db + */ + total_db_entries = vec_len(cnat_main_db); + total_free_entries = db_free_entry(cnat_main_db); + used_entries = total_db_entries - total_free_entries; + + *(result_array + i++) = spp_host_to_net_byte_order_32(total_db_entries); + *(result_array + i++) = spp_host_to_net_byte_order_32(used_entries); + *(result_array + i++) = spp_host_to_net_byte_order_32(total_free_entries); + + /* + * Find entries free and used in user-db + */ + total_db_entries = vec_len(cnat_user_db); + total_free_entries = db_free_entry(cnat_user_db); + used_entries = total_db_entries - total_free_entries; + + *(result_array + i++) = spp_host_to_net_byte_order_32(total_db_entries); + *(result_array + i++) = spp_host_to_net_byte_order_32(used_entries); + *(result_array + i++) = spp_host_to_net_byte_order_32(total_free_entries); + + mp_resp->num_bytes = spp_host_to_net_byte_order_32(i*sizeof(u32)); +} + +SPP_INIT_FUNCTION(cnat_debug_init); +#endif /* TOBE_PORTED */ diff --git a/plugins/vcgn-plugin/vcgn/cnat_global.c b/plugins/vcgn-plugin/vcgn/cnat_global.c new file mode 100644 index 00000000..71770834 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_global.c @@ -0,0 +1,79 @@ +/* + *------------------------------------------------------------------ + * cnat_global.c - global variables + * + * Copyright (c) 2008-2009, 2012 Cisco and/or its affiliates. + * 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. + *------------------------------------------------------------------ + */ + +/* gloable variables */ + +#include +#include +#include +#include + +#include "dslite_defs.h" +#include "tcp_header_definitions.h" +u32 cnat_current_time; +u8 nfv9_configured = 0; +/* ctx/sf alloc error counters */ +u32 null_enq_pkt; +u32 null_deq_pkt; + +u32 null_enq_ctx; +u32 null_deq_ctx; + +u32 null_enq_wqe; +u32 null_deq_wqe; + +u32 ctx_alloc_errs; +u32 sf_alloc_errs; + +u32 rcv_pkt_errs; + +/* TOBE_PORTED : Remove following once we bring DSLite */ +u32 dslite_config_debug_level = 1; +u32 dslite_data_path_debug_level = 1; +u32 dslite_defrag_debug_level = 1; +u32 dslite_debug_level = 1; + +dslite_table_entry_t *dslite_table_db_ptr; + +/* + * ipv4_decr_ttl_n_calc_csum() + * - It decrements the TTL and calculates the incremental IPv4 checksum + */ + +/* TOBE_PORTED: Following is in cnat_util.c */ +always_inline __attribute__((unused)) +void ipv4_decr_ttl_n_calc_csum(ipv4_header *ipv4) +{ + u32 checksum; + u16 old; + u16 ttl; + + ttl = ipv4->ttl; + old = clib_net_to_host_u16(ttl); + + /* Decrement TTL */ + ipv4->ttl--; + + /* Calculate incremental checksum */ + checksum = old + (~clib_net_to_host_u16(ttl) & 0xFFFF); + checksum += clib_net_to_host_u16(ipv4->checksum); + checksum = (checksum & 0xFFFF) + (checksum >> 16); + ipv4->checksum = clib_host_to_net_u32(checksum + (checksum >> 16)); +} + diff --git a/plugins/vcgn-plugin/vcgn/cnat_global.h b/plugins/vcgn-plugin/vcgn/cnat_global.h new file mode 100644 index 00000000..823a4797 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_global.h @@ -0,0 +1,87 @@ +/* + *------------------------------------------------------------------ + * cnat_global.h - global definition and variables + * to be used by non cnat files + * + * Copyright (c) 2007-2012 Cisco and/or its affiliates. + * 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 __CNAT_GLOBAL_H__ +#define __CNAT_GLOBAL_H__ + +/* gloable variables */ + +extern u8 cnat_db_init_done; +extern u32 cnat_current_time; +extern u64 in2out_drops_port_limit_exceeded; +extern u64 in2out_drops_system_limit_reached; +extern u64 in2out_drops_resource_depletion; +extern u64 no_translation_entry_drops; +extern u8 nfv9_configured; +extern u32 translation_create_count; +extern u32 translation_create_rate; + +extern u32 translation_delete_count; +extern u32 translation_delete_rate; + +extern u32 in2out_forwarding_count; +extern u32 in2out_forwarding_rate; + +extern u32 out2in_forwarding_count; +extern u32 out2in_forwarding_rate; + +extern u32 total_address_pool_allocated; + +extern u32 nat44_active_translations; + +#if 1 //DSLITE_DEF +extern u32 dslite_translation_create_rate; +extern u32 dslite_translation_delete_rate; +extern u32 dslite_translation_create_count; +extern u32 dslite_in2out_forwarding_count; +extern u32 dslite_in2out_forwarding_count; +extern u32 dslite_out2in_forwarding_rate; +#endif +/* sf/ctx allocation error collection declarations */ +#define COLLECT_FREQ_FACTOR 100 +#define NUM_SECONDS_TO_WAIT 10 +#define COUNTER_BUFFER_SIZE 25 + +extern u32 null_enq_pkt; +extern u32 null_deq_pkt; + +extern u32 null_enq_ctx; +extern u32 null_deq_ctx; + +extern u32 null_enq_wqe; +extern u32 null_deq_wqe; + +extern u32 ctx_alloc_errs; +extern u32 sf_alloc_errs; + +extern u32 rcv_pkt_errs; + +struct counter_array_t { + u32 sf_error_counter; + u32 ctx_error_counter; + u32 timestamp; +} counter_array_t; + +#define COUNTER_BUFFER_SIZE 25 +struct counter_array_t err_cnt_arr[COUNTER_BUFFER_SIZE]; + +//#define DISABLE_ICMP_THROTTLE_FOR_DEBUG_PURPOSE + +#endif /*__CNAT_GLOBAL_H__*/ diff --git a/plugins/vcgn-plugin/vcgn/cnat_ipv4_icmp.h b/plugins/vcgn-plugin/vcgn/cnat_ipv4_icmp.h new file mode 100644 index 00000000..664b62ac --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_ipv4_icmp.h @@ -0,0 +1,60 @@ +/* + *----------------------------------------------------------------------------- + * + * Filename: cnat_ipv4_icmp.h + * + * Description: common functions for icmp node + * + * Assumptions and Constraints: + * + * Copyright (c) 2000-2009, 2014 Cisco and/or its affiliates. + * 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 __CNAT_IPV4_ICMP_H__ +#define __CNAT_IPV4_ICMP_H__ + +#include "tcp_header_definitions.h" +#include "cnat_db.h" +#include "cnat_v4_functions.h" +#include "cnat_global.h" +#include "cnat_config.h" + +typedef struct { + icmp_v4_t *icmp; + ipv4_header *em_ip; + u16 *em_port; + u16 *em_l4_checksum; +} icmp_em_ip_info; + +extern void swap_ip_src_icmp_id(ipv4_header *ip, + icmp_v4_t *icmp, + cnat_main_db_entry_t *db, + u16 vrf); + +extern void swap_ip_dst_icmp_id(ipv4_header *ip, + icmp_v4_t *icmp, + cnat_main_db_entry_t *db, + u16 vrf); + +extern void swap_ip_src_emip_dst(ipv4_header *ip, + icmp_em_ip_info *icmp_info, + cnat_main_db_entry_t *db, u16 vrf); + +extern void swap_ip_dst_emip_src(ipv4_header *ip, + icmp_em_ip_info *icmp_info, + cnat_main_db_entry_t *db, u16 vrf); + + +#endif /* __CNAT_IPV4_ICMP_H__ */ diff --git a/plugins/vcgn-plugin/vcgn/cnat_ipv4_icmp_error_inside_input.c b/plugins/vcgn-plugin/vcgn/cnat_ipv4_icmp_error_inside_input.c new file mode 100644 index 00000000..218d7e53 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_ipv4_icmp_error_inside_input.c @@ -0,0 +1,476 @@ +/* + *--------------------------------------------------------------------------- + * cnat_ipv4_icmp_error_inside_input.c - cnat_ipv4_icmp_error_inside_input node pipeline stage functions + * + * Copyright (c) 2008-2014 Cisco and/or its affiliates. + * 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 +#include +#include +#include + +#include "cnat_ipv4_icmp.h" + +#define foreach_cnat_ipv4_icmp_e_inside_input_error \ +_(CNAT_V4_ICMP_E_I2O_T_PKT, "cnat v4 icmp_e i2o packet transmit") \ +_(CNAT_V4_ICMP_E_I2O_D_PKT, "cnat v4 icmp_e i2o packet drop") \ +_(CNAT_V4_ICMP_E_I2O_TTL_DROP, "cnat v4 icmp_e i2o ttl drop") + +typedef enum { +#define _(sym,str) sym, + foreach_cnat_ipv4_icmp_e_inside_input_error +#undef _ + CNAT_IPV4_ICMP_E_INSIDE_INPUT_N_ERROR, +} cnat_ipv4_icmp_e_inside_input_t; + +static char * cnat_ipv4_icmp_e_inside_input_error_strings[] = { +#define _(sym,string) string, + foreach_cnat_ipv4_icmp_e_inside_input_error +#undef _ +}; + +typedef struct { + u32 cached_next_index; + /* $$$$ add data here */ + + /* convenience variables */ + vlib_main_t * vlib_main; + vnet_main_t * vnet_main; +} cnat_ipv4_icmp_e_inside_input_main_t; + +typedef enum { + CNAT_V4_ICMP_E_I2O_T, + CNAT_V4_ICMP_E_I2O_D, + CNAT_V4_ICMP_E_I2O_NEXT, +} cnat_ipv4_icmp_e_inside_input_next_t; + +cnat_ipv4_icmp_e_inside_input_main_t cnat_ipv4_icmp_e_inside_input_main; +vlib_node_registration_t cnat_ipv4_icmp_e_inside_input_node; + +#define NSTAGES 5 + +inline void swap_ip_src_emip_dst(ipv4_header *ip, + icmp_em_ip_info *icmp_info, + cnat_main_db_entry_t *db, u16 vrf) +{ + icmp_v4_t *icmp; + ipv4_header *em_ip; + u16 *em_port; + u32 old_ip; + u16 old_port; + u16 old_ip_checksum; + + /* + * declear variable + */ + CNAT_UPDATE_L3_CHECKSUM_DECLARE + CNAT_UPDATE_ICMP_ERR_CHECKSUM_DECLARE + + /* + * fix inner layer ip & l4 checksum + */ + em_ip = icmp_info->em_ip; + em_port = icmp_info->em_port; + + CNAT_UPDATE_L3_CHECKSUM(((u16)(db->in2out_key.k.ipv4)), + ((u16)(db->in2out_key.k.ipv4 >> 16)), + (clib_net_to_host_u16(em_ip->checksum)), + ((u16)(db->out2in_key.k.ipv4)), + ((u16)(db->out2in_key.k.ipv4 >> 16))) + + old_ip = clib_net_to_host_u32(em_ip->dest_addr); + old_port = clib_net_to_host_u16(*em_port); + old_ip_checksum = clib_net_to_host_u16(em_ip->checksum); + + em_ip->dest_addr = + clib_host_to_net_u32(db->out2in_key.k.ipv4); + em_ip->checksum = + clib_host_to_net_u16(new_l3_c); + *em_port = + clib_host_to_net_u16(db->out2in_key.k.port); + + /* + * fix outter layer ip & icmp checksum + */ + icmp = icmp_info->icmp; + CNAT_UPDATE_ICMP_ERR_CHECKSUM(((u16)(old_ip & 0xFFFF)), + ((u16)(old_ip >> 16)), + (old_port), + (old_ip_checksum), + (clib_net_to_host_u16(icmp->checksum)), + ((u16)(db->out2in_key.k.ipv4 & 0xffff)), + ((u16)(db->out2in_key.k.ipv4 >> 16)), + ((u16)(db->out2in_key.k.port)), + ((u16)(new_l3_c))) + + icmp->checksum = + clib_host_to_net_u16(new_icmp_c); + + old_ip = clib_net_to_host_u32(ip->src_addr); + + ip->src_addr = + clib_host_to_net_u32(db->out2in_key.k.ipv4); + + CNAT_UPDATE_L3_CHECKSUM(((u16)(old_ip & 0xFFFF)), + ((u16)(old_ip >> 16)), + (clib_net_to_host_u16(ip->checksum)), + ((u16)(db->out2in_key.k.ipv4)), + ((u16)(db->out2in_key.k.ipv4 >> 16))) + ip->checksum = + clib_host_to_net_u16(new_l3_c); + +#if 0 + if(is_static_dest_nat_enabled(vrf) == CNAT_SUCCESS) { + /* + * fix inner layer ip & l4 checksum + */ + em_snat_ip = icmp_info->em_ip; + em_snat_port = icmp_info->em_port; + + old_ip = spp_net_to_host_byte_order_32(&(em_snat_ip->src_addr)); + old_port = spp_net_to_host_byte_order_16(em_snat_port); + old_ip_checksum = spp_net_to_host_byte_order_16(&(em_snat_ip->checksum)); + direction = 0; + if(cnat_static_dest_db_get_translation(em_snat_ip->src_addr, &postmap_ip, vrf, direction) == CNAT_SUCCESS) { + old_postmap_ip = spp_net_to_host_byte_order_32(&postmap_ip); + + CNAT_UPDATE_L3_CHECKSUM(((u16)(old_ip)), + ((u16)(old_ip >> 16)), + (spp_net_to_host_byte_order_16(&(em_snat_ip->checksum))), + ((u16)(old_postmap_ip)), + ((u16)(old_postmap_ip >> 16))) + em_snat_ip->src_addr = postmap_ip; + em_snat_ip->checksum = + spp_host_to_net_byte_order_16(new_l3_c); + + /* + * fix outter layer ip & icmp checksum + */ + icmp = icmp_info->icmp; + CNAT_UPDATE_ICMP_ERR_CHECKSUM(((u16)(old_ip & 0xFFFF)), + ((u16)(old_ip >> 16)), + (old_port), + (old_ip_checksum), + (spp_net_to_host_byte_order_16(&(icmp->checksum))), + ((u16)(old_postmap_ip & 0xffff)), + ((u16)(old_postmap_ip >> 16)), + ((u16)(old_port)), + ((u16)(new_l3_c))) + + icmp->checksum = + spp_host_to_net_byte_order_16(new_icmp_c); + + } + } + + if(is_static_dest_nat_enabled(vrf) == CNAT_SUCCESS) { + direction = 0; + if(cnat_static_dest_db_get_translation(ip->dest_addr, &postmap_ip, vrf, direction) == CNAT_SUCCESS) { + + old_ip = spp_net_to_host_byte_order_32(&(ip->dest_addr)); + old_postmap_ip = spp_net_to_host_byte_order_32(&postmap_ip); + + CNAT_UPDATE_L3_CHECKSUM(((u16)(old_ip & 0xFFFF)), + ((u16)(old_ip >> 16)), + (spp_net_to_host_byte_order_16(&(ip->checksum))), + ((u16)(old_postmap_ip & 0xFFFF)), + ((u16)(old_postmap_ip >> 16))) + ip->dest_addr = postmap_ip; + + ip->checksum = + clib_host_to_net_u16(new_l3_c); + } + } +#endif /* if 0 */ + +} + +/* + * Use the generic buffer metadata + first line of packet data prefetch + * stage function from . This is usually a Good Idea. + */ +#define stage0 generic_stage0 + + +static inline void +stage1(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) +{ + u64 a, b, c; + u32 bucket; + u8 *prefetch_target; + + vlib_buffer_t * b0 = vlib_get_buffer (vm, buffer_index); + ipv4_header *ip = vlib_buffer_get_current (b0); + u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; + icmp_v4_t *icmp = (icmp_v4_t *)((u8*)ip + ipv4_hdr_len); + ipv4_header *em_ip = (ipv4_header*)((u8*)icmp + 8); /* embedded pkt's v4 hdr */ + u8 em_ip_hdr_len = (em_ip->version_hdr_len_words & 0xf) << 2; + + u64 tmp = 0; + u32 protocol = CNAT_ICMP; + + /* Check L4 header for embedded packet */ + if (em_ip->protocol == TCP_PROT) { + tcp_hdr_type *tcp = (tcp_hdr_type*)((u8 *)em_ip + em_ip_hdr_len); + vnet_buffer(b0)->vcgn_uii.key.k.port = + clib_net_to_host_u16(tcp->dest_port); + protocol = CNAT_TCP; + + } else if (em_ip->protocol == UDP_PROT) { + udp_hdr_type_t *udp = (udp_hdr_type_t *)((u8 *)em_ip + em_ip_hdr_len); + vnet_buffer(b0)->vcgn_uii.key.k.port = + clib_net_to_host_u16(udp->dest_port); + protocol = CNAT_UDP; + + } else { + icmp_v4_t *icmp = (icmp_v4_t*)((u8 *)em_ip + em_ip_hdr_len); + vnet_buffer(b0)->vcgn_uii.key.k.port = + clib_net_to_host_u16(icmp->identifier); + + if (PREDICT_FALSE((icmp->type != ICMPV4_ECHOREPLY) && + (icmp->type != ICMPV4_ECHO))) { + /* + * Try to set invalid protocol for these cases, so that + * hash lookup does not return valid main_db. This approach + * may optimize the regular cases with valid protocols + * as it avoids one more check for regular cases in stage3 + */ + protocol = CNAT_INVALID_PROTO; + } + } + + tmp = vnet_buffer(b0)->vcgn_uii.key.k.ipv4 = + clib_net_to_host_u32(em_ip->dest_addr); + + tmp |= ((u64)vnet_buffer(b0)->vcgn_uii.key.k.port) << 32; + + PLATFORM_CNAT_SET_RX_VRF(vnet_buffer(b0)->sw_if_index[VLIB_RX], + vnet_buffer(b0)->vcgn_uii.key.k.vrf, + protocol) + tmp |= ((u64)vnet_buffer(b0)->vcgn_uii.key.k.vrf) << 48; + + CNAT_V4_GET_HASH(tmp, bucket, CNAT_MAIN_HASH_MASK) + + prefetch_target = (u8 *)(&cnat_in2out_hash[bucket]); + vnet_buffer(b0)->vcgn_uii.bucket = bucket; + + /* Prefetch the hash bucket */ + CLIB_PREFETCH(prefetch_target, CLIB_CACHE_LINE_BYTES, LOAD); +} + +#define SPP_LOG2_CACHE_LINE_BYTES 6 +#define SPP_CACHE_LINE_BYTES (1 << SPP_LOG2_CACHE_LINE_BYTES) + +static inline void +stage2(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) +{ + vlib_buffer_t * b0 = vlib_get_buffer(vm, buffer_index); + uword prefetch_target0, prefetch_target1; + u32 bucket = vnet_buffer(b0)->vcgn_uii.bucket; + + /* read the hash bucket */ + u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket + = cnat_in2out_hash[bucket].next; + + if (PREDICT_TRUE(db_index != EMPTY)) { + /* + * Prefetch database keys. We save space by not cache-line + * aligning the DB entries. We don't want to waste LSU + * bandwidth prefetching stuff we won't need. + */ + prefetch_target0 = (uword)(cnat_main_db + db_index); + CLIB_PREFETCH((void*)prefetch_target0, CLIB_CACHE_LINE_BYTES, LOAD); + /* Just beyond DB key #2 */ + prefetch_target1 = prefetch_target0 + + STRUCT_OFFSET_OF(cnat_main_db_entry_t, user_ports); + /* If the targets are in different lines, do the second prefetch */ + if (PREDICT_FALSE((prefetch_target0 & ~(SPP_CACHE_LINE_BYTES-1)) != + (prefetch_target1 & ~(SPP_CACHE_LINE_BYTES-1)))) { + CLIB_PREFETCH((void *)prefetch_target1, CLIB_CACHE_LINE_BYTES, LOAD); + } + } +} + +static inline void +stage3(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) +{ + cnat_main_db_entry_t *db; + vlib_buffer_t * b0 = vlib_get_buffer(vm, buffer_index); + u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket; + + /* + * Note: if the search already failed (empty bucket), + * the answer is already in the pipeline context structure + */ + if (PREDICT_TRUE(db_index != EMPTY)) { + + /* + * Note: hash collisions suck. We can't easily prefetch around them. + * The first trip around the track will be fast. After that, maybe + * not so much... + */ + do { + db = cnat_main_db + db_index; + if (PREDICT_TRUE(db->in2out_key.key64 == + vnet_buffer(b0)->vcgn_uii.key.key64)) { + break; + } + db_index = db->in2out_hash.next; + } while (db_index != EMPTY); + + /* Stick the answer back into the pipeline context structure */ + vnet_buffer(b0)->vcgn_uii.bucket = db_index; + } +} + + + +static inline u32 last_stage (vlib_main_t *vm, vlib_node_runtime_t *node, + u32 bi) +{ + vlib_buffer_t *b0 = vlib_get_buffer (vm, bi); + u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket; + int disposition = CNAT_V4_ICMP_E_I2O_T; + int counter = CNAT_V4_ICMP_E_I2O_T_PKT; + + ipv4_header *ip = (ipv4_header *)vlib_buffer_get_current(b0); + u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; + icmp_v4_t *icmp = (icmp_v4_t *)((u8*)ip + ipv4_hdr_len); + ipv4_header *em_ip = (ipv4_header*)((u8*)icmp + 8); /* embedded pkt's v4 hdr */ + u8 em_ip_hdr_len = (em_ip->version_hdr_len_words & 0xf) << 2; + vlib_node_t *n = vlib_get_node (vm, cnat_ipv4_icmp_e_inside_input_node.index); + u32 node_counter_base_index = n->error_heap_index; + vlib_error_main_t * em = &vm->error_main; + cnat_main_db_entry_t *db = NULL; + icmp_em_ip_info icmp_info; + + if (PLATFORM_HANDLE_TTL_DECREMENT) { + if (PREDICT_FALSE(ip->ttl <= 1)) { + /* + * As it is ICMP error packet with TTL <= 1, + * let's drop the packet (no need to genereate + * another ICMP error). + */ + + disposition = CNAT_V4_ICMP_E_I2O_D; + counter = CNAT_V4_ICMP_E_I2O_TTL_DROP; + + goto drop_pkt; + } + } + + if (PREDICT_TRUE(db_index != EMPTY)) { + icmp_info.em_ip = em_ip; + icmp_info.icmp = icmp; + //icmp_info.em_port = vnet_buffer(b0)->vcgn_uii.key.k.port; + + /* Note: This could have been done in stage1 itself, + * but we need to introduce one u16 * in vnet_buffer_opaque_t + * Since this flow is expected to be very rare in actual + * deployment scenario, we may afford to do these steps here + * as well. Lets confirm during core review. */ + if (em_ip->protocol == TCP_PROT) { + tcp_hdr_type *tcp = (tcp_hdr_type*)((u8 *)em_ip + em_ip_hdr_len); + icmp_info.em_port = &(tcp->dest_port); + } else if (em_ip->protocol == UDP_PROT) { + udp_hdr_type_t *udp = (udp_hdr_type_t *) + ((u8 *)em_ip + em_ip_hdr_len); + icmp_info.em_port = &(udp->dest_port); + } else { + icmp_v4_t *icmp_inner = (icmp_v4_t*)((u8 *)em_ip + em_ip_hdr_len); + icmp_info.em_port = &(icmp_inner->identifier); + } + + db = cnat_main_db + db_index; + /* + * 1. update dst addr:dst port of embedded ip pkt + * update src addr of icmp pkt + * 2. fix udp/tcp/ip checksum of embedded pkt + * fix icmp, ip check of icmp pkt + * don need to update the timer + */ + + if (PREDICT_FALSE(icmp_debug_flag)) { + printf("\nDUMPING ICMP PKT BEFORE\n"); + print_icmp_pkt(ip); + } + + if (PLATFORM_HANDLE_TTL_DECREMENT) { + /* + * Decrement TTL and update IPv4 checksum + */ + ipv4_decr_ttl_n_calc_csum(ip); + } + + swap_ip_src_emip_dst(ip, &icmp_info, + db, db->in2out_key.k.vrf); + + if (PREDICT_FALSE(icmp_debug_flag)) { + printf("\nDUMPING ICMP PKT AFTER\n"); + print_icmp_pkt(ip); + } + in2out_forwarding_count++; + + } else { + disposition = CNAT_V4_ICMP_E_I2O_D; + counter = CNAT_V4_ICMP_E_I2O_D_PKT; + } + +drop_pkt: + + em->counters[node_counter_base_index + counter] += 1; + return disposition; +} + +#include + +static uword cnat_ipv4_icmp_e_inside_input_node_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + return dispatch_pipeline (vm, node, frame); +} + + +VLIB_REGISTER_NODE (cnat_ipv4_icmp_e_inside_input_node) = { + .function = cnat_ipv4_icmp_e_inside_input_node_fn, + .name = "vcgn-v4-icmp-e-i2o", + .vector_size = sizeof (u32), + .type = VLIB_NODE_TYPE_INTERNAL, + + .n_errors = ARRAY_LEN(cnat_ipv4_icmp_e_inside_input_error_strings), + .error_strings = cnat_ipv4_icmp_e_inside_input_error_strings, + + .n_next_nodes = CNAT_V4_ICMP_E_I2O_NEXT, + + /* edit / add dispositions here */ + .next_nodes = { + [CNAT_V4_ICMP_E_I2O_T] = "ip4-input", + [CNAT_V4_ICMP_E_I2O_D] = "error-drop", + }, +}; + +clib_error_t *cnat_ipv4_icmp_e_inside_input_init (vlib_main_t *vm) +{ + cnat_ipv4_icmp_e_inside_input_main_t * mp = &cnat_ipv4_icmp_e_inside_input_main; + + mp->vlib_main = vm; + mp->vnet_main = vnet_get_main(); + + return 0; +} + +VLIB_INIT_FUNCTION (cnat_ipv4_icmp_e_inside_input_init); diff --git a/plugins/vcgn-plugin/vcgn/cnat_ipv4_icmp_error_outside_input.c b/plugins/vcgn-plugin/vcgn/cnat_ipv4_icmp_error_outside_input.c new file mode 100644 index 00000000..f25f4d02 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_ipv4_icmp_error_outside_input.c @@ -0,0 +1,452 @@ +/* + *--------------------------------------------------------------------------- + * cnat_ipv4_icmp_error_outside_input.c - cnat_ipv4_icmp_error_outside_input node pipeline stage functions + * + * Copyright (c) 2008-2014 Cisco and/or its affiliates. + * 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 +#include +#include +#include + +#include "cnat_ipv4_icmp.h" + +#define foreach_cnat_ipv4_icmp_e_outside_input_error \ +_(CNAT_V4_ICMP_E_O2I_T_PKT, "cnat v4 icmp_e o2i packet transmit") \ +_(CNAT_V4_ICMP_E_O2I_D_PKT, "cnat v4 icmp_e o2i packet drop") \ +_(CNAT_V4_ICMP_E_O2I_TTL_DROP, "cnat v4 icmp_e o2i ttl drop") + +typedef enum { +#define _(sym,str) sym, + foreach_cnat_ipv4_icmp_e_outside_input_error +#undef _ + CNAT_IPV4_ICMP_E_OUTSIDE_INPUT_N_ERROR, +} cnat_ipv4_icmp_e_outside_input_t; + +static char * cnat_ipv4_icmp_e_outside_input_error_strings[] = { +#define _(sym,string) string, + foreach_cnat_ipv4_icmp_e_outside_input_error +#undef _ +}; + +typedef struct { + u32 cached_next_index; + /* $$$$ add data here */ + + /* convenience variables */ + vlib_main_t * vlib_main; + vnet_main_t * vnet_main; +} cnat_ipv4_icmp_e_outside_input_main_t; + +typedef enum { + CNAT_V4_ICMP_E_O2I_T, + CNAT_V4_ICMP_E_O2I_D, + CNAT_V4_ICMP_E_O2I_NEXT, +} cnat_ipv4_icmp_e_outside_input_next_t; + +cnat_ipv4_icmp_e_outside_input_main_t cnat_ipv4_icmp_e_outside_input_main; +vlib_node_registration_t cnat_ipv4_icmp_e_outside_input_node; + +#define NSTAGES 5 + +inline void swap_ip_dst_emip_src(ipv4_header *ip, + icmp_em_ip_info *icmp_info, + cnat_main_db_entry_t *db, u16 vrf) +{ + icmp_v4_t *icmp; + ipv4_header *em_ip; + u16 *em_port; + u32 old_ip; + u16 old_port; + u16 old_ip_checksum; + + /* + * declear variable + */ + CNAT_UPDATE_L3_CHECKSUM_DECLARE + CNAT_UPDATE_ICMP_ERR_CHECKSUM_DECLARE + + /* + * fix inner layer ip & l4 checksum + */ + em_ip = icmp_info->em_ip; + em_port = icmp_info->em_port; + + CNAT_UPDATE_L3_CHECKSUM(((u16)(db->out2in_key.k.ipv4)), + ((u16)(db->out2in_key.k.ipv4 >> 16)), + (clib_net_to_host_u16(em_ip->checksum)), + ((u16)(db->in2out_key.k.ipv4)), + ((u16)(db->in2out_key.k.ipv4 >> 16))) + + old_ip = clib_net_to_host_u32(em_ip->src_addr); + old_port = clib_net_to_host_u16(*em_port); + old_ip_checksum = clib_net_to_host_u16(em_ip->checksum); + + em_ip->src_addr = + clib_host_to_net_u32(db->in2out_key.k.ipv4); + em_ip->checksum = + clib_host_to_net_u16(new_l3_c); + *em_port = + clib_host_to_net_u16(db->in2out_key.k.port); + + /* + * fix outter layer ip & icmp checksum + */ + icmp = icmp_info->icmp; + CNAT_UPDATE_ICMP_ERR_CHECKSUM(((u16)(old_ip & 0xFFFF)), + ((u16)(old_ip >> 16)), + (old_port), + (old_ip_checksum), + (clib_net_to_host_u16(icmp->checksum)), + ((u16)(db->in2out_key.k.ipv4 & 0xffff)), + ((u16)(db->in2out_key.k.ipv4 >> 16)), + ((u16)(db->in2out_key.k.port)), + ((u16)(new_l3_c))) + + icmp->checksum = + clib_host_to_net_u16(new_icmp_c); + + old_ip = clib_net_to_host_u32(ip->dest_addr); + + ip->dest_addr = + clib_host_to_net_u32(db->in2out_key.k.ipv4); + + CNAT_UPDATE_L3_CHECKSUM(((u16)(old_ip & 0xFFFF)), + ((u16)(old_ip >> 16)), + (clib_net_to_host_u16(ip->checksum)), + ((u16)(db->in2out_key.k.ipv4)), + ((u16)(db->in2out_key.k.ipv4 >> 16))) + ip->checksum = + clib_host_to_net_u16(new_l3_c); + +#if 0 + if(is_static_dest_nat_enabled(vrf) == CNAT_SUCCESS) { + /* + * fix inner layer ip & l4 checksum + */ + em_snat_ip = icmp_info->em_ip; + em_snat_port = icmp_info->em_port; + + old_ip = spp_net_to_host_byte_order_32(&(em_snat_ip->dest_addr)); + old_port = spp_net_to_host_byte_order_16(em_snat_port); + old_ip_checksum = spp_net_to_host_byte_order_16(&(em_snat_ip->checksum)); + direction = 1; + if(cnat_static_dest_db_get_translation(em_snat_ip->dest_addr, &postmap_ip, vrf, direction) == CNAT_SUCCESS) { + old_postmap_ip = spp_net_to_host_byte_order_32(&postmap_ip); + + CNAT_UPDATE_L3_CHECKSUM(((u16)(old_ip)), + ((u16)(old_ip >> 16)), + (spp_net_to_host_byte_order_16(&(em_snat_ip->checksum))), + ((u16)(old_postmap_ip)), + ((u16)(old_postmap_ip >> 16))) + em_snat_ip->dest_addr = postmap_ip; + em_snat_ip->checksum = + spp_host_to_net_byte_order_16(new_l3_c); + + /* + * fix outter layer ip & icmp checksum + */ + icmp = icmp_info->icmp; + CNAT_UPDATE_ICMP_ERR_CHECKSUM(((u16)(old_ip & 0xFFFF)), + ((u16)(old_ip >> 16)), + (old_port), + (old_ip_checksum), + (spp_net_to_host_byte_order_16(&(icmp->checksum))), + ((u16)(old_postmap_ip & 0xffff)), + ((u16)(old_postmap_ip >> 16)), + ((u16)(old_port)), + ((u16)(new_l3_c))) + + icmp->checksum = + spp_host_to_net_byte_order_16(new_icmp_c); + + } + } + + if(is_static_dest_nat_enabled(vrf) == CNAT_SUCCESS) { + direction = 1; + if(cnat_static_dest_db_get_translation(ip->src_addr, &postmap_ip, vrf, direction) == CNAT_SUCCESS) { + CNAT_UPDATE_L3_CHECKSUM_DECLARE + + old_ip = spp_net_to_host_byte_order_32(&(ip->src_addr)); + old_postmap_ip = spp_net_to_host_byte_order_32(&postmap_ip); + + CNAT_UPDATE_L3_CHECKSUM(((u16)(old_ip & 0xFFFF)), + ((u16)(old_ip >> 16)), + (spp_net_to_host_byte_order_16(&(ip->checksum))), + ((u16)(old_postmap_ip & 0xFFFF)), + ((u16)(old_postmap_ip >> 16))) + ip->checksum = + spp_host_to_net_byte_order_16(new_l3_c); + ip->src_addr = postmap_ip; + } + } +#endif /* if 0 */ +} + +/* + * Use the generic buffer metadata + first line of packet data prefetch + * stage function from . This is usually a Good Idea. + */ +#define stage0 generic_stage0 + + +static inline void +stage1(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) +{ + u64 a, b, c; + u32 bucket; + u8 *prefetch_target; + + vlib_buffer_t * b0 = vlib_get_buffer (vm, buffer_index); + ipv4_header *ip = vlib_buffer_get_current (b0); + u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; + icmp_v4_t *icmp = (icmp_v4_t *)((u8*)ip + ipv4_hdr_len); + ipv4_header *em_ip = (ipv4_header*)((u8*)icmp + 8); /* embedded pkt's v4 hdr */ + u8 em_ip_hdr_len = (em_ip->version_hdr_len_words & 0xf) << 2; + + u64 tmp = 0; + u32 protocol = CNAT_ICMP; + + /* Check L4 header for embedded packet */ + if (em_ip->protocol == TCP_PROT) { + tcp_hdr_type *tcp = (tcp_hdr_type*)((u8 *)em_ip + em_ip_hdr_len); + vnet_buffer(b0)->vcgn_uii.key.k.port = + clib_net_to_host_u16(tcp->src_port); + protocol = CNAT_TCP; + + } else if (em_ip->protocol == UDP_PROT) { + udp_hdr_type_t *udp = (udp_hdr_type_t *)((u8 *)em_ip + em_ip_hdr_len); + vnet_buffer(b0)->vcgn_uii.key.k.port = + clib_net_to_host_u16(udp->src_port); + protocol = CNAT_UDP; + + } else { + icmp_v4_t *icmp = (icmp_v4_t*)((u8 *)em_ip + em_ip_hdr_len); + vnet_buffer(b0)->vcgn_uii.key.k.port = + clib_net_to_host_u16(icmp->identifier); + + if (PREDICT_FALSE((icmp->type != ICMPV4_ECHOREPLY) && + (icmp->type != ICMPV4_ECHO))) { + /* + * Try to set invalid protocol for these cases, so that + * hash lookup does not return valid main_db. This approach + * may optimize the regular cases with valid protocols + * as it avoids one more check for regular cases in stage3 + */ + protocol = CNAT_INVALID_PROTO; + } + } + + tmp = vnet_buffer(b0)->vcgn_uii.key.k.ipv4 = + clib_net_to_host_u32(em_ip->src_addr); + + tmp |= ((u64)vnet_buffer(b0)->vcgn_uii.key.k.port) << 32; + + PLATFORM_CNAT_SET_RX_VRF(vnet_buffer(b0)->sw_if_index[VLIB_RX], + vnet_buffer(b0)->vcgn_uii.key.k.vrf, + protocol) + tmp |= ((u64)vnet_buffer(b0)->vcgn_uii.key.k.vrf) << 48; + + CNAT_V4_GET_HASH(tmp, bucket, CNAT_MAIN_HASH_MASK) + + prefetch_target = (u8 *)(&cnat_out2in_hash[bucket]); + vnet_buffer(b0)->vcgn_uii.bucket = bucket; + + /* Prefetch the hash bucket */ + CLIB_PREFETCH(prefetch_target, CLIB_CACHE_LINE_BYTES, LOAD); +} + + +#define SPP_LOG2_CACHE_LINE_BYTES 6 +#define SPP_CACHE_LINE_BYTES (1 << SPP_LOG2_CACHE_LINE_BYTES) + +static inline void +stage2(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) +{ + vlib_buffer_t * b0 = vlib_get_buffer(vm, buffer_index); + uword prefetch_target0, prefetch_target1; + u32 bucket = vnet_buffer(b0)->vcgn_uii.bucket; + + /* read the hash bucket */ + u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket + = cnat_out2in_hash[bucket].next; + + if (PREDICT_TRUE(db_index != EMPTY)) { + /* + * Prefetch database keys. We save space by not cache-line + * aligning the DB entries. We don't want to waste LSU + * bandwidth prefetching stuff we won't need. + */ + prefetch_target0 = (uword)(cnat_main_db + db_index); + CLIB_PREFETCH((void*)prefetch_target0, CLIB_CACHE_LINE_BYTES, LOAD); + /* Just beyond DB key #2 */ + prefetch_target1 = prefetch_target0 + + STRUCT_OFFSET_OF(cnat_main_db_entry_t, user_ports); + /* If the targets are in different lines, do the second prefetch */ + if (PREDICT_FALSE((prefetch_target0 & ~(SPP_CACHE_LINE_BYTES-1)) != + (prefetch_target1 & ~(SPP_CACHE_LINE_BYTES-1)))) { + CLIB_PREFETCH((void *)prefetch_target1, CLIB_CACHE_LINE_BYTES, LOAD); + } + } +} + + +static inline void +stage3(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) +{ + cnat_main_db_entry_t *db; + vlib_buffer_t * b0 = vlib_get_buffer(vm, buffer_index); + u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket; + + /* + * Note: if the search already failed (empty bucket), + * the answer is already in the pipeline context structure + */ + if (PREDICT_TRUE(db_index != EMPTY)) { + + /* + * Note: hash collisions suck. We can't easily prefetch around them. + * The first trip around the track will be fast. After that, maybe + * not so much... + */ + do { + db = cnat_main_db + db_index; + if (PREDICT_TRUE(db->out2in_key.key64 == + vnet_buffer(b0)->vcgn_uii.key.key64)) { + break; + } + db_index = db->out2in_hash.next; + } while (db_index != EMPTY); + + /* Stick the answer back into the pipeline context structure */ + vnet_buffer(b0)->vcgn_uii.bucket = db_index; + } +} + +static inline u32 last_stage (vlib_main_t *vm, vlib_node_runtime_t *node, + u32 bi) +{ + vlib_buffer_t *b0 = vlib_get_buffer (vm, bi); + u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket; + int disposition = CNAT_V4_ICMP_E_O2I_T; + int counter = CNAT_V4_ICMP_E_O2I_T_PKT; + + ipv4_header *ip = (ipv4_header *)vlib_buffer_get_current(b0); + u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; + icmp_v4_t *icmp = (icmp_v4_t *)((u8*)ip + ipv4_hdr_len); + ipv4_header *em_ip = (ipv4_header*)((u8*)icmp + 8); /* embedded pkt's v4 hdr */ + u8 em_ip_hdr_len = (em_ip->version_hdr_len_words & 0xf) << 2; + vlib_node_t *n = vlib_get_node (vm, cnat_ipv4_icmp_e_outside_input_node.index); + u32 node_counter_base_index = n->error_heap_index; + vlib_error_main_t * em = &vm->error_main; + cnat_main_db_entry_t *db = NULL; + icmp_em_ip_info icmp_info; + + + if (PREDICT_TRUE(db_index != EMPTY)) { + + icmp_info.em_ip = em_ip; + icmp_info.icmp = icmp; + + /* Note: This could have been done in stage1 itself, + * but we need to introduce one u16 * in vnet_buffer_opaque_t + * Since this flow is expected to be very rare in actual + * deployment scenario, we may afford to do these steps here + * as well. Lets confirm during core review. */ + + if (em_ip->protocol == TCP_PROT) { + tcp_hdr_type *tcp = (tcp_hdr_type*)((u8 *)em_ip + em_ip_hdr_len); + icmp_info.em_port = &(tcp->src_port); + } else if (em_ip->protocol == UDP_PROT) { + udp_hdr_type_t *udp = (udp_hdr_type_t *) + ((u8 *)em_ip + em_ip_hdr_len); + icmp_info.em_port = &(udp->src_port); + } else { + icmp_v4_t *icmp_inner = (icmp_v4_t*)((u8 *)em_ip + em_ip_hdr_len); + icmp_info.em_port = &(icmp_inner->identifier); + } + + db = cnat_main_db + db_index; + + if (PREDICT_FALSE(icmp_debug_flag)) { + printf("\nDUMPING ICMP PKT BEFORE\n"); + print_icmp_pkt(ip); + } + + if (PLATFORM_HANDLE_TTL_DECREMENT) { + /* + * Decrement TTL and update IPv4 checksum + */ + ipv4_decr_ttl_n_calc_csum(ip); + } + + swap_ip_dst_emip_src(ip, &icmp_info, + db, db->in2out_key.k.vrf); + + if (PREDICT_FALSE(icmp_debug_flag)) { + printf("\nDUMPING ICMP PKT AFTER\n"); + print_icmp_pkt(ip); + } + + } else { + disposition = CNAT_V4_ICMP_E_O2I_D; + counter = CNAT_V4_ICMP_E_O2I_D_PKT; + } + + em->counters[node_counter_base_index + counter] += 1; + return disposition; +} + +#include + +static uword cnat_ipv4_icmp_e_outside_input_node_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + return dispatch_pipeline (vm, node, frame); +} + + +VLIB_REGISTER_NODE (cnat_ipv4_icmp_e_outside_input_node) = { + .function = cnat_ipv4_icmp_e_outside_input_node_fn, + .name = "vcgn-v4-icmp-e-o2i", + .vector_size = sizeof (u32), + .type = VLIB_NODE_TYPE_INTERNAL, + + .n_errors = ARRAY_LEN(cnat_ipv4_icmp_e_outside_input_error_strings), + .error_strings = cnat_ipv4_icmp_e_outside_input_error_strings, + + .n_next_nodes = CNAT_V4_ICMP_E_O2I_NEXT, + + /* edit / add dispositions here */ + .next_nodes = { + [CNAT_V4_ICMP_E_O2I_T] = "ip4-input", + [CNAT_V4_ICMP_E_O2I_D] = "error-drop", + }, +}; + +clib_error_t *cnat_ipv4_icmp_e_outside_input_init (vlib_main_t *vm) +{ + cnat_ipv4_icmp_e_outside_input_main_t * mp = &cnat_ipv4_icmp_e_outside_input_main; + + mp->vlib_main = vm; + mp->vnet_main = vnet_get_main(); + + return 0; +} + +VLIB_INIT_FUNCTION (cnat_ipv4_icmp_e_outside_input_init); diff --git a/plugins/vcgn-plugin/vcgn/cnat_ipv4_icmp_query_inside_input.c b/plugins/vcgn-plugin/vcgn/cnat_ipv4_icmp_query_inside_input.c new file mode 100644 index 00000000..1b9f0266 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_ipv4_icmp_query_inside_input.c @@ -0,0 +1,404 @@ +/* + *--------------------------------------------------------------------------- + * cnat_ipv4_icmp_query_inside_input.c - cnat_ipv4_icmp_query_inside_input node pipeline stage functions + * + * + * Copyright (c) 2008-2014 Cisco and/or its affiliates. + * 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 +#include +#include +#include + +#include "cnat_ipv4_icmp.h" + +#define foreach_cnat_ipv4_icmp_q_inside_input_error \ +_(CNAT_V4_ICMP_Q_I2O_T_PKT, "cnat v4 icmp_q i2o packet transmit") \ +_(CNAT_V4_ICMP_Q_I2O_MISS_PKT, "cnat v4 icmp_q i2o db miss") \ +_(CNAT_V4_ICMP_Q_I2O_TTL_GEN, "cnat v4 icmp_q i2o ttl generate") \ +_(CNAT_V4_ICMP_Q_I2O_TTL_DROP, "cnat v4 icmp_q i2o ttl drop") \ +_(CNAT_V4_ICMP_Q_I2O_NO_SESSION_DROP, "cnat v4 icmp_q i2o no session drop") + +typedef enum { +#define _(sym,str) sym, + foreach_cnat_ipv4_icmp_q_inside_input_error +#undef _ + CNAT_IPV4_ICMP_Q_INSIDE_INPUT_N_ERROR, +} cnat_ipv4_icmp_q_inside_input_t; + +static char * cnat_ipv4_icmp_q_inside_input_error_strings[] = { +#define _(sym,string) string, + foreach_cnat_ipv4_icmp_q_inside_input_error +#undef _ +}; + +typedef struct { + u32 cached_next_index; + /* $$$$ add data here */ + + /* convenience variables */ + vlib_main_t * vlib_main; + vnet_main_t * vnet_main; +} cnat_ipv4_icmp_q_inside_input_main_t; + +typedef enum { + CNAT_V4_ICMP_Q_I2O_T, + CNAT_V4_ICMP_Q_I2O_E, + CNAT_V4_ICMP_Q_I2O_D, + CNAT_V4_ICMP_Q_I2O_NEXT, +} cnat_ipv4_icmp_q_inside_input_next_t; + +cnat_ipv4_icmp_q_inside_input_main_t cnat_ipv4_icmp_q_inside_input_main; +vlib_node_registration_t cnat_ipv4_icmp_q_inside_input_node; + +#define NSTAGES 5 + +inline void swap_ip_src_icmp_id(ipv4_header *ip, + icmp_v4_t *icmp, + cnat_main_db_entry_t *db, u16 vrf) +{ +#if 0 + u32 postmap_ip; + u8 direction; + u32 old_ip; + u32 old_postmap_ip; + + + if(is_static_dest_nat_enabled(vrf) == CNAT_SUCCESS) { + direction = 0; + if(cnat_static_dest_db_get_translation(ip->dest_addr, &postmap_ip, vrf, direction) == CNAT_SUCCESS) { + CNAT_UPDATE_L3_CHECKSUM_DECLARE + + old_ip = spp_net_to_host_byte_order_32(&(ip->dest_addr)); + old_postmap_ip = spp_net_to_host_byte_order_32(&postmap_ip); + + CNAT_UPDATE_L3_CHECKSUM(((u16)(old_ip & 0xFFFF)), + ((u16)(old_ip >> 16)), + (spp_net_to_host_byte_order_16(&(ip->checksum))), + ((u16)(old_postmap_ip & 0xFFFF)), + ((u16)(old_postmap_ip >> 16))) + ip->dest_addr = postmap_ip; + + ip->checksum = + spp_host_to_net_byte_order_16(new_l3_c); + } + } +#endif /* if 0 */ + /* + * declare variable + */ + CNAT_UPDATE_L3_L4_CHECKSUM_DECLARE + /* + * calculate checksum + */ + CNAT_UPDATE_L3_ICMP_CHECKSUM(((u16)(db->in2out_key.k.ipv4)), + ((u16)(db->in2out_key.k.ipv4 >> 16)), + (db->in2out_key.k.port), + (clib_net_to_host_u16(ip->checksum)), + (clib_net_to_host_u16(icmp->checksum)), + ((u16)(db->out2in_key.k.ipv4)), + ((u16)(db->out2in_key.k.ipv4 >> 16)), + (db->out2in_key.k.port)) + //set ip header + ip->src_addr = + clib_host_to_net_u32(db->out2in_key.k.ipv4); + ip->checksum = + clib_host_to_net_u16(new_l3_c); + + //set icmp header + icmp->identifier = + clib_host_to_net_u16(db->out2in_key.k.port); + icmp->checksum = + clib_host_to_net_u16(new_l4_c); +} + +/* + * Use the generic buffer metadata + first line of packet data prefetch + * stage function from . This is usually a Good Idea. + */ +#define stage0 generic_stage0 + +static inline void +stage1(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) +{ + u64 a, b, c; + u32 bucket; + u8 *prefetch_target; + + vlib_buffer_t * b0 = vlib_get_buffer (vm, buffer_index); + ipv4_header *ip = vlib_buffer_get_current (b0); + u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; + icmp_v4_t *icmp = (icmp_v4_t *)((u8*)ip + ipv4_hdr_len); + + u64 tmp = 0; + tmp = vnet_buffer(b0)->vcgn_uii.key.k.ipv4 = + clib_net_to_host_u32(ip->src_addr); + vnet_buffer(b0)->vcgn_uii.key.k.port = + clib_net_to_host_u16 (icmp->identifier); + + tmp |= ((u64)vnet_buffer(b0)->vcgn_uii.key.k.port) << 32; + + PLATFORM_CNAT_SET_RX_VRF(vnet_buffer(b0)->sw_if_index[VLIB_RX], + vnet_buffer(b0)->vcgn_uii.key.k.vrf, + CNAT_ICMP) + tmp |= ((u64)vnet_buffer(b0)->vcgn_uii.key.k.vrf) << 48; + + CNAT_V4_GET_HASH(tmp, bucket, CNAT_MAIN_HASH_MASK) + + prefetch_target = (u8 *)(&cnat_in2out_hash[bucket]); + vnet_buffer(b0)->vcgn_uii.bucket = bucket; + + /* Prefetch the hash bucket */ + CLIB_PREFETCH(prefetch_target, CLIB_CACHE_LINE_BYTES, LOAD); +} + +#define SPP_LOG2_CACHE_LINE_BYTES 6 +#define SPP_CACHE_LINE_BYTES (1 << SPP_LOG2_CACHE_LINE_BYTES) + +static inline void +stage2(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) +{ + vlib_buffer_t * b0 = vlib_get_buffer(vm, buffer_index); + uword prefetch_target0, prefetch_target1; + u32 bucket = vnet_buffer(b0)->vcgn_uii.bucket; + + /* read the hash bucket */ + u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket + = cnat_in2out_hash[bucket].next; + + if (PREDICT_TRUE(db_index != EMPTY)) { + /* + * Prefetch database keys. We save space by not cache-line + * aligning the DB entries. We don't want to waste LSU + * bandwidth prefetching stuff we won't need. + */ + prefetch_target0 = (uword)(cnat_main_db + db_index); + CLIB_PREFETCH((void*)prefetch_target0, CLIB_CACHE_LINE_BYTES, LOAD); + /* Just beyond DB key #2 */ + prefetch_target1 = prefetch_target0 + + STRUCT_OFFSET_OF(cnat_main_db_entry_t, user_ports); + /* If the targets are in different lines, do the second prefetch */ + if (PREDICT_FALSE((prefetch_target0 & ~(SPP_CACHE_LINE_BYTES-1)) != + (prefetch_target1 & ~(SPP_CACHE_LINE_BYTES-1)))) { + CLIB_PREFETCH((void *)prefetch_target1, CLIB_CACHE_LINE_BYTES, LOAD); + } + } +} + +static inline void +stage3(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) +{ + cnat_main_db_entry_t *db; + vlib_buffer_t * b0 = vlib_get_buffer(vm, buffer_index); + u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket; + + /* + * Note: if the search already failed (empty bucket), + * the answer is already in the pipeline context structure + */ + if (PREDICT_TRUE(db_index != EMPTY)) { + + /* + * Note: hash collisions suck. We can't easily prefetch around them. + * The first trip around the track will be fast. After that, maybe + * not so much... + */ + do { + db = cnat_main_db + db_index; + if (PREDICT_TRUE(db->in2out_key.key64 == + vnet_buffer(b0)->vcgn_uii.key.key64)) { + break; + } + db_index = db->in2out_hash.next; + } while (db_index != EMPTY); + + /* Stick the answer back into the pipeline context structure */ + vnet_buffer(b0)->vcgn_uii.bucket = db_index; + } +} + +static inline u32 last_stage (vlib_main_t *vm, vlib_node_runtime_t *node, + u32 bi) +{ + vlib_buffer_t *b0 = vlib_get_buffer (vm, bi); + u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket; + spp_ctx_t *ctx = (spp_ctx_t *) &vnet_buffer(b0)->vcgn_uii; + int disposition = CNAT_V4_ICMP_Q_I2O_T; + int counter = CNAT_V4_ICMP_Q_I2O_T_PKT; + + ipv4_header *ip = (ipv4_header *)vlib_buffer_get_current(b0); + u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; + icmp_v4_t *icmp = (icmp_v4_t *)((u8*)ip + ipv4_hdr_len); + vlib_node_t *n = vlib_get_node (vm, cnat_ipv4_icmp_q_inside_input_node.index); + u32 node_counter_base_index = n->error_heap_index; + vlib_error_main_t * em = &vm->error_main; + cnat_session_entry_t *session_db = NULL; + cnat_main_db_entry_t *db = NULL; + cnat_key_t dest_info; + + if (PLATFORM_HANDLE_TTL_DECREMENT) { + if (PREDICT_FALSE(ip->ttl <= 1)) { + /* Try to generate ICMP error msg, as TTL is <= 1 */ + + if (icmpv4_generate_with_throttling + (ctx, ip, ctx->ru.rx.uidb_index)) { + + /* Generated ICMP */ + disposition = CNAT_V4_ICMP_Q_I2O_T; + counter = CNAT_V4_ICMP_Q_I2O_TTL_GEN; + } else { + /* Could not generated ICMP - drop the packet */ + disposition = CNAT_V4_ICMP_Q_I2O_D; + counter = CNAT_V4_ICMP_Q_I2O_TTL_DROP; + } + goto drop_pkt; + } + } + + if (PREDICT_TRUE(db_index != EMPTY)) { + db = cnat_main_db + db_index; + dest_info.k.port = 0; + dest_info.k.ipv4 = clib_net_to_host_u32(ip->dest_addr); + + if(PREDICT_TRUE(!PLATFORM_DBL_SUPPORT)) { + + /* No DBL support, so just update the destn and proceed */ + db->dst_ipv4 = dest_info.k.ipv4; + db->dst_port = dest_info.k.port; + goto update_pkt; + } + + if(PREDICT_FALSE(db->dst_ipv4 != dest_info.k.ipv4)) { + if(PREDICT_TRUE(db->nsessions == 1)) { + /* Handle one to 2 dest scenarion */ + dest_info.k.vrf = db->in2out_key.k.vrf; + session_db = cnat_handle_1to2_session(db, &dest_info); + + if(PREDICT_FALSE(session_db == NULL)) { + disposition = CNAT_V4_ICMP_Q_I2O_D; + counter = CNAT_V4_ICMP_Q_I2O_NO_SESSION_DROP; + goto drop_pkt; + } + } else if (PREDICT_FALSE(db->nsessions == 0)) { + /* Should be a static entry + * Note this session as the first session and log + */ + cnat_add_dest_n_log(db, &dest_info); + } else { /* Many translations exist already */ + dest_info.k.vrf = db->in2out_key.k.vrf; + /* If session already exists, + * cnat_create_session_db_entry will return the existing db + * else create a new db + * If could not create, return NULL + */ + session_db = cnat_create_session_db_entry(&dest_info, + db, TRUE); + + if(PREDICT_FALSE(session_db == NULL)) { + disposition = CNAT_V4_ICMP_Q_I2O_D; + counter = CNAT_V4_ICMP_Q_I2O_NO_SESSION_DROP; + goto drop_pkt; + } + } + } + +update_pkt: + + if (PREDICT_FALSE(icmp_debug_flag)) { + printf("\nDUMPING ICMP PKT BEFORE\n"); + print_icmp_pkt(ip); + } + + if (PLATFORM_HANDLE_TTL_DECREMENT) { + /* + * Decrement TTL and update IPv4 checksum + */ + ipv4_decr_ttl_n_calc_csum(ip); + } + + /* + * 1. update src ipv4 addr and src icmp identifier + * 2. update ipv4 checksum and icmp checksum + */ + swap_ip_src_icmp_id(ip, icmp, db, db->in2out_key.k.vrf); + + if (PREDICT_FALSE(icmp_debug_flag)) { + printf("\nDUMPING ICMP PKT AFTER\n"); + print_icmp_pkt(ip); + } + + /* + * update db counter, timer + */ + + if(PREDICT_FALSE(session_db != 0)) { + CNAT_DB_TIMEOUT_RST(session_db); + } else { + CNAT_DB_TIMEOUT_RST(db); + } + db->in2out_pkts++; + in2out_forwarding_count++; + + } else { + disposition = CNAT_V4_ICMP_Q_I2O_E; + counter = CNAT_V4_ICMP_Q_I2O_MISS_PKT; + } + +drop_pkt: + + em->counters[node_counter_base_index + counter] += 1; + return disposition; +} + +#include + +static uword cnat_ipv4_icmp_q_inside_input_node_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + return dispatch_pipeline (vm, node, frame); +} + + +VLIB_REGISTER_NODE (cnat_ipv4_icmp_q_inside_input_node) = { + .function = cnat_ipv4_icmp_q_inside_input_node_fn, + .name = "vcgn-v4-icmp-q-i2o", + .vector_size = sizeof (u32), + .type = VLIB_NODE_TYPE_INTERNAL, + + .n_errors = ARRAY_LEN(cnat_ipv4_icmp_q_inside_input_error_strings), + .error_strings = cnat_ipv4_icmp_q_inside_input_error_strings, + + .n_next_nodes = CNAT_V4_ICMP_Q_I2O_NEXT, + + /* edit / add dispositions here */ + .next_nodes = { + [CNAT_V4_ICMP_Q_I2O_E] = "vcgn-v4-icmp-q-i2o-e", + [CNAT_V4_ICMP_Q_I2O_T] = "ip4-input", + [CNAT_V4_ICMP_Q_I2O_D] = "error-drop", + }, +}; + +clib_error_t *cnat_ipv4_icmp_q_inside_input_init (vlib_main_t *vm) +{ + cnat_ipv4_icmp_q_inside_input_main_t * mp = &cnat_ipv4_icmp_q_inside_input_main; + + mp->vlib_main = vm; + mp->vnet_main = vnet_get_main(); + + return 0; +} + +VLIB_INIT_FUNCTION (cnat_ipv4_icmp_q_inside_input_init); diff --git a/plugins/vcgn-plugin/vcgn/cnat_ipv4_icmp_query_inside_input_exception.c b/plugins/vcgn-plugin/vcgn/cnat_ipv4_icmp_query_inside_input_exception.c new file mode 100644 index 00000000..9b5e280e --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_ipv4_icmp_query_inside_input_exception.c @@ -0,0 +1,235 @@ +/* + *--------------------------------------------------------------------------- + * cnat_ipv4_icmp_query_inside_input_exception.c - cnat_ipv4_icmp_query_inside_input_exception node pipeline stage functions + * + * Copyright (c) 2008-2014 Cisco and/or its affiliates. + * 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 +#include +#include +#include + +#include "cnat_ipv4_icmp.h" + +#define foreach_cnat_ipv4_icmp_q_inside_input_exc_error \ +_(CNAT_V4_ICMP_Q_I2O_E_T_PKT, "v4 icmp query i2o-e transmit") \ +_(CNAT_V4_ICMP_Q_I2O_E_G_PKT, "v4 icmp query i2o-e gen icmp msg") \ +_(CNAT_V4_ICMP_Q_I2O_E_D_PKT, "v4 icmp query i2o-e pkt drop") \ +_(CNAT_V4_ICMP_Q_I2O_E_DC_PKT, "v4 icmp query i2o-e drop (no config)") \ +_(CNAT_V4_ICMP_Q_I2O_E_DR_PKT, "v4 icmp query i2o-e drop (not in run state)") \ +_(CNAT_V4_ICMP_Q_I2O_E_DD_PKT, "v4 icmp query i2o-e drop (no direct port)") \ +_(CNAT_V4_ICMP_Q_I2O_E_DA_PKT, "v4 icmp query i2o-e drop (no any port)") \ +_(CNAT_V4_ICMP_Q_I2O_E_DO_PKT, "v4 icmp query i2o-e drop (out of port limit)") \ +_(CNAT_V4_ICMP_Q_I2O_E_DS_PKT, "v4 icmp query i2o_e drop (out of session db)") + +typedef enum { +#define _(sym,str) sym, + foreach_cnat_ipv4_icmp_q_inside_input_exc_error +#undef _ + CNAT_IPV4_ICMP_Q_INSIDE_INPUT_EXCEPTIONS_N_ERROR, +} cnat_ipv4_icmp_q_inside_input_exc_error_t; + + +static char * cnat_ipv4_icmp_q_inside_input_exc_error_strings[] = { +#define _(sym,string) string, + foreach_cnat_ipv4_icmp_q_inside_input_exc_error +#undef _ +}; + +typedef struct { + u32 cached_next_index; + /* $$$$ add data here */ + + /* convenience variables */ + vlib_main_t * vlib_main; + vnet_main_t * vnet_main; +} cnat_ipv4_icmp_q_inside_input_exc_main_t; + +typedef enum { + CNAT_V4_ICMP_Q_E_I2O_T, + //CNAT_V4_ICMP_Q_E_I2O_GEN, + CNAT_V4_ICMP_Q_E_I2O_D, + CNAT_V4_ICMP_Q_E_I2O_NEXT, +} cnat_ipv4_icmp_q_inside_input_exc_next_t; + +#define CNAT_V4_ICMP_Q_E_I2O_GEN CNAT_V4_ICMP_Q_E_I2O_T + +cnat_ipv4_icmp_q_inside_input_exc_main_t cnat_ipv4_icmp_q_inside_input_exc_main; +vlib_node_registration_t cnat_ipv4_icmp_q_inside_input_exc_node; + +#define NSTAGES 2 + +/* + * Use the generic buffer metadata + first line of packet data prefetch + * stage function from . This is usually a Good Idea. + */ +#define stage0 generic_stage0 + +static inline u32 last_stage (vlib_main_t *vm, vlib_node_runtime_t *node, + u32 bi) +{ + vlib_buffer_t *b0 = vlib_get_buffer (vm, bi); + int disposition = CNAT_V4_ICMP_Q_E_I2O_T; + int counter = CNAT_V4_ICMP_Q_I2O_E_T_PKT; + + ipv4_header *ip = (ipv4_header *)vlib_buffer_get_current(b0); + u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; + icmp_v4_t *icmp = (icmp_v4_t *)((u8*)ip + ipv4_hdr_len); + vlib_node_t *n = vlib_get_node (vm, cnat_ipv4_icmp_q_inside_input_exc_node.index); + u32 node_counter_base_index = n->error_heap_index; + vlib_error_main_t * em = &vm->error_main; + + cnat_key_t dest_info; + cnat_gen_icmp_info info; + cnat_db_key_bucket_t ki; + cnat_main_db_entry_t *db = NULL; + + PLATFORM_CNAT_SET_RX_VRF(vnet_buffer(b0)->sw_if_index[VLIB_RX], + ki.k.k.vrf, CNAT_ICMP) + + ki.k.k.ipv4 = + clib_net_to_host_u32(ip->src_addr); + ki.k.k.port = + clib_net_to_host_u16(icmp->identifier); + + dest_info.k.port = 0; + dest_info.k.ipv4 = clib_net_to_host_u32(ip->dest_addr); + PLATFORM_CNAT_SET_RX_VRF(vnet_buffer(b0)->sw_if_index[VLIB_RX], + dest_info.k.vrf, CNAT_ICMP) + + db = cnat_get_main_db_entry_v2(&ki, PORT_SINGLE, PORT_TYPE_DYNAMIC, + &info, &dest_info); + if (PREDICT_TRUE(db != 0)) { + + if (PREDICT_FALSE(icmp_debug_flag)) { + printf("\nDUMPING ICMP PKT BEFORE\n"); + print_icmp_pkt(ip); + } + + if (PLATFORM_HANDLE_TTL_DECREMENT) { + /* + * Decrement TTL and update IPv4 checksum + */ + ipv4_decr_ttl_n_calc_csum(ip); + } + + /* + * step 6 do nat before fwd pkt + */ + swap_ip_src_icmp_id(ip, icmp, db, db->in2out_key.k.vrf); + + if (PREDICT_FALSE(icmp_debug_flag)) { + printf("\nDUMPING ICMP PKT AFTER\n"); + print_icmp_pkt(ip); + } + + /* + * update db for this pkt + */ + CNAT_DB_UPDATE_IN2OUT_TIMER + in2out_forwarding_count++; + + } else { + switch (info.error) { + case (CNAT_NO_VRF_RUN): + counter = CNAT_V4_ICMP_Q_I2O_E_DR_PKT; + break; + case (CNAT_OUT_LIMIT): + counter = CNAT_V4_ICMP_Q_I2O_E_DO_PKT; + break; + case (CNAT_NO_PORT_ANY): + case (CNAT_NO_POOL_ANY): + case (CNAT_BAD_INUSE_ANY): + case (CNAT_NOT_FOUND_ANY): + counter = CNAT_V4_ICMP_Q_I2O_E_DA_PKT; + break; + case (CNAT_INV_PORT_DIRECT): + case (CNAT_DEL_PORT_DIRECT): + case (CNAT_BAD_INUSE_DIRECT): + case (CNAT_NOT_FOUND_DIRECT): + counter = CNAT_V4_ICMP_Q_I2O_E_DD_PKT; + break; + case (CNAT_ERR_NO_SESSION_DB): + counter = CNAT_V4_ICMP_Q_I2O_E_DS_PKT; + break; + default: + counter = CNAT_V4_ICMP_Q_I2O_E_DC_PKT; + break; + } + /* + * send to icmp msg generate node + */ + if (info.gen_icmp_msg == CNAT_ICMP_MSG) { + #if 0 + u32 *fd = (u32*)ctx->feature_data; + fd[0] = info.svi_addr; + fd[1] = CNAT_ICMP_DEST_UNREACHABLE; + #endif + disposition = CNAT_V4_ICMP_Q_E_I2O_GEN; + counter = CNAT_V4_ICMP_Q_I2O_E_G_PKT; + } else { + disposition = CNAT_V4_ICMP_Q_E_I2O_D; + counter = CNAT_V4_ICMP_Q_I2O_E_D_PKT; + } + DEBUG_I2O_DROP(CNAT_DEBUG_DROP_ICMP) + } + + em->counters[node_counter_base_index + counter] += 1; + + return disposition; +} + +#include + +static uword cnat_ipv4_icmp_q_inside_input_exc_node_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + return dispatch_pipeline (vm, node, frame); +} + +VLIB_REGISTER_NODE (cnat_ipv4_icmp_q_inside_input_exc_node) = { + .function = cnat_ipv4_icmp_q_inside_input_exc_node_fn, + .name = "vcgn-v4-icmp-q-i2o-e", + .vector_size = sizeof (u32), + .type = VLIB_NODE_TYPE_INTERNAL, + + .n_errors = ARRAY_LEN(cnat_ipv4_icmp_q_inside_input_exc_error_strings), + .error_strings = cnat_ipv4_icmp_q_inside_input_exc_error_strings, + + .n_next_nodes = CNAT_V4_ICMP_Q_E_I2O_NEXT, + + /* edit / add dispositions here */ + .next_nodes = { + //[CNAT_V4_ICMP_Q_E_I2O_GEN] = "icmp_msg_gen", /* Currently it will go + //to ip4-input node. We have to port icmp msg generator node */ + [CNAT_V4_ICMP_Q_E_I2O_T] = "ip4-input", + [CNAT_V4_ICMP_Q_E_I2O_D] = "error-drop", + }, +}; + + +clib_error_t *cnat_ipv4_icmp_q_inside_input_exc_init (vlib_main_t *vm) +{ + cnat_ipv4_icmp_q_inside_input_exc_main_t * mp = &cnat_ipv4_icmp_q_inside_input_exc_main; + + mp->vlib_main = vm; + mp->vnet_main = vnet_get_main(); + + return 0; +} + +VLIB_INIT_FUNCTION (cnat_ipv4_icmp_q_inside_input_exc_init); diff --git a/plugins/vcgn-plugin/vcgn/cnat_ipv4_icmp_query_outside_input.c b/plugins/vcgn-plugin/vcgn/cnat_ipv4_icmp_query_outside_input.c new file mode 100644 index 00000000..2c05e0b4 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_ipv4_icmp_query_outside_input.c @@ -0,0 +1,381 @@ +/* + *--------------------------------------------------------------------------- + * cnat_ipv4_icmp_query_outside_input.c - cnat_ipv4_icmp_query_outside_input node pipeline stage functions + * + * + * Copyright (c) 2008-2014 Cisco and/or its affiliates. + * 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 +#include +#include +#include + +#include "cnat_ipv4_icmp.h" + +#define foreach_cnat_ipv4_icmp_q_outside_input_error \ +_(CNAT_V4_ICMP_Q_O2I_T_PKT, "cnat v4 icmp_q o2i packet transmit") \ +_(CNAT_V4_ICMP_Q_O2I_MISS_PKT, "cnat v4 icmp_q o2i drop") \ +_(CNAT_V4_ICMP_Q_O2I_TTL_GEN, "cnat v4 icmp_q o2i ttl generate") \ +_(CNAT_V4_ICMP_Q_O2I_TTL_DROP, "cnat v4 icmp_q o2i ttl drop") \ +_(CNAT_V4_ICMP_Q_O2I_NO_SESSION_DROP, "cnat v4 icmp_q o2i no session drop") + +typedef enum { +#define _(sym,str) sym, + foreach_cnat_ipv4_icmp_q_outside_input_error +#undef _ + CNAT_IPV4_ICMP_Q_OUTSIDE_INPUT_N_ERROR, +} cnat_ipv4_icmp_q_outside_input_t; + +static char * cnat_ipv4_icmp_q_outside_input_error_strings[] = { +#define _(sym,string) string, + foreach_cnat_ipv4_icmp_q_outside_input_error +#undef _ +}; + +typedef struct { + u32 cached_next_index; + /* $$$$ add data here */ + + /* convenience variables */ + vlib_main_t * vlib_main; + vnet_main_t * vnet_main; +} cnat_ipv4_icmp_q_outside_input_main_t; + +typedef enum { + CNAT_V4_ICMP_Q_O2I_T, + CNAT_V4_ICMP_Q_O2I_D, + CNAT_V4_ICMP_Q_O2I_NEXT, +} cnat_ipv4_icmp_q_outside_input_next_t; + +cnat_ipv4_icmp_q_outside_input_main_t cnat_ipv4_icmp_q_outside_input_main; +vlib_node_registration_t cnat_ipv4_icmp_q_outside_input_node; + +#define NSTAGES 5 + +inline void swap_ip_dst_icmp_id(ipv4_header *ip, + icmp_v4_t *icmp, + cnat_main_db_entry_t *db, u16 vrf) +{ +#if 0 + u32 postmap_ip; + u8 direction; + u32 old_ip; + u32 old_postmap_ip; + + if(is_static_dest_nat_enabled(vrf) == CNAT_SUCCESS) { + direction = 1; + if(cnat_static_dest_db_get_translation(ip->src_addr, &postmap_ip, vrf, direction) == CNAT_SUCCESS) { + CNAT_UPDATE_L3_CHECKSUM_DECLARE + + old_ip = spp_net_to_host_byte_order_32(&(ip->src_addr)); + old_postmap_ip = spp_net_to_host_byte_order_32(&postmap_ip); + + CNAT_UPDATE_L3_CHECKSUM(((u16)(old_ip & 0xFFFF)), + ((u16)(old_ip >> 16)), + (spp_net_to_host_byte_order_16(&(ip->checksum))), + ((u16)(old_postmap_ip & 0xFFFF)), + ((u16)(old_postmap_ip >> 16))) + ip->checksum = + spp_host_to_net_byte_order_16(new_l3_c); + ip->src_addr = postmap_ip; + } + } +#endif /* if 0 */ + /* + * declare variable + */ + CNAT_UPDATE_L3_L4_CHECKSUM_DECLARE + /* + * calculate checksum + */ + CNAT_UPDATE_L3_ICMP_CHECKSUM(((u16)(db->out2in_key.k.ipv4)), + ((u16)(db->out2in_key.k.ipv4 >> 16)), + (db->out2in_key.k.port), + (clib_net_to_host_u16(ip->checksum)), + (clib_net_to_host_u16(icmp->checksum)), + ((u16)(db->in2out_key.k.ipv4)), + ((u16)(db->in2out_key.k.ipv4 >> 16)), + (db->in2out_key.k.port)) + //set ip header + ip->dest_addr = + clib_host_to_net_u32(db->in2out_key.k.ipv4); + ip->checksum = + clib_host_to_net_u16(new_l3_c); + + //set icmp header + icmp->identifier = + clib_host_to_net_u16(db->in2out_key.k.port); + icmp->checksum = + clib_host_to_net_u16(new_l4_c); +} + +/* + * Use the generic buffer metadata + first line of packet data prefetch + * stage function from . This is usually a Good Idea. + */ +#define stage0 generic_stage0 + +static inline void +stage1(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) +{ + u64 a, b, c; + u32 bucket; + u8 *prefetch_target; + + vlib_buffer_t * b0 = vlib_get_buffer (vm, buffer_index); + ipv4_header *ip = vlib_buffer_get_current (b0); + u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; + icmp_v4_t *icmp = (icmp_v4_t *)((u8*)ip + ipv4_hdr_len); + + u64 tmp = 0; + tmp = vnet_buffer(b0)->vcgn_uii.key.k.ipv4 = + clib_net_to_host_u32(ip->dest_addr); + vnet_buffer(b0)->vcgn_uii.key.k.port = + clib_net_to_host_u16 (icmp->identifier); + + tmp |= ((u64)vnet_buffer(b0)->vcgn_uii.key.k.port) << 32; + + PLATFORM_CNAT_SET_RX_VRF(vnet_buffer(b0)->sw_if_index[VLIB_RX], + vnet_buffer(b0)->vcgn_uii.key.k.vrf, + CNAT_ICMP) + tmp |= ((u64)vnet_buffer(b0)->vcgn_uii.key.k.vrf) << 48; + + CNAT_V4_GET_HASH(tmp, bucket, CNAT_MAIN_HASH_MASK) + + prefetch_target = (u8 *)(&cnat_out2in_hash[bucket]); + vnet_buffer(b0)->vcgn_uii.bucket = bucket; + + /* Prefetch the hash bucket */ + CLIB_PREFETCH(prefetch_target, CLIB_CACHE_LINE_BYTES, LOAD); +} + +#define SPP_LOG2_CACHE_LINE_BYTES 6 +#define SPP_CACHE_LINE_BYTES (1 << SPP_LOG2_CACHE_LINE_BYTES) + +static inline void +stage2(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) +{ + vlib_buffer_t * b0 = vlib_get_buffer(vm, buffer_index); + uword prefetch_target0, prefetch_target1; + u32 bucket = vnet_buffer(b0)->vcgn_uii.bucket; + + /* read the hash bucket */ + u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket + = cnat_out2in_hash[bucket].next; + + if (PREDICT_TRUE(db_index != EMPTY)) { + /* + * Prefetch database keys. We save space by not cache-line + * aligning the DB entries. We don't want to waste LSU + * bandwidth prefetching stuff we won't need. + */ + prefetch_target0 = (uword)(cnat_main_db + db_index); + CLIB_PREFETCH((void*)prefetch_target0, CLIB_CACHE_LINE_BYTES, LOAD); + /* Just beyond DB key #2 */ + prefetch_target1 = prefetch_target0 + + STRUCT_OFFSET_OF(cnat_main_db_entry_t, user_ports); + /* If the targets are in different lines, do the second prefetch */ + if (PREDICT_FALSE((prefetch_target0 & ~(SPP_CACHE_LINE_BYTES-1)) != + (prefetch_target1 & ~(SPP_CACHE_LINE_BYTES-1)))) { + CLIB_PREFETCH((void *)prefetch_target1, CLIB_CACHE_LINE_BYTES, LOAD); + } + } +} + +static inline void +stage3(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) +{ + cnat_main_db_entry_t *db; + vlib_buffer_t * b0 = vlib_get_buffer(vm, buffer_index); + u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket; + + /* + * Note: if the search already failed (empty bucket), + * the answer is already in the pipeline context structure + */ + if (PREDICT_TRUE(db_index != EMPTY)) { + + /* + * Note: hash collisions suck. We can't easily prefetch around them. + * The first trip around the track will be fast. After that, maybe + * not so much... + */ + do { + db = cnat_main_db + db_index; + if (PREDICT_TRUE(db->out2in_key.key64 == + vnet_buffer(b0)->vcgn_uii.key.key64)) { + break; + } + db_index = db->out2in_hash.next; + } while (db_index != EMPTY); + + /* Stick the answer back into the pipeline context structure */ + vnet_buffer(b0)->vcgn_uii.bucket = db_index; + } +} + + +static inline u32 last_stage (vlib_main_t *vm, vlib_node_runtime_t *node, + u32 bi) +{ + + vlib_buffer_t *b0 = vlib_get_buffer (vm, bi); + u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket; + int disposition = CNAT_V4_ICMP_Q_O2I_T; + int counter = CNAT_V4_ICMP_Q_O2I_T_PKT; + + ipv4_header *ip = (ipv4_header *)vlib_buffer_get_current(b0); + u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; + icmp_v4_t *icmp = (icmp_v4_t *)((u8*)ip + ipv4_hdr_len); + vlib_node_t *n = vlib_get_node (vm, cnat_ipv4_icmp_q_outside_input_node.index); + u32 node_counter_base_index = n->error_heap_index; + vlib_error_main_t * em = &vm->error_main; + cnat_session_entry_t *session_db = NULL; + cnat_main_db_entry_t *db = NULL; + cnat_key_t dest_info; + cnat_vrfmap_t * vrf_map_p __attribute__((unused)) = NULL; + u32 vrf_index __attribute__((unused)) = 0; + + if (PREDICT_TRUE(db_index != EMPTY)) { + + db = cnat_main_db + db_index; + dest_info.k.port = 0; + dest_info.k.ipv4 = clib_net_to_host_u32(ip->src_addr); + + if (PREDICT_FALSE(icmp_debug_flag)) { + printf("\nDUMPING ICMP PKT BEFORE\n"); + print_icmp_pkt(ip); + } + + vrf_map_p = cnat_map_by_vrf + db->vrfmap_index; + vrf_index = (db->in2out_key.k.vrf & CNAT_VRF_MASK); + + if(PREDICT_TRUE(!PLATFORM_DBL_SUPPORT)) { + + /* No DBL support, so just update the destn and proceed */ + db->dst_ipv4 = dest_info.k.ipv4; + db->dst_port = dest_info.k.port; + goto update_pkt; + } + + if(PREDICT_FALSE(db->dst_ipv4 != dest_info.k.ipv4)) { + + if(PREDICT_TRUE(db->nsessions == 1)) { + /* Handle one to 2 dest scenarion */ + dest_info.k.vrf = db->in2out_key.k.vrf; + session_db = cnat_handle_1to2_session(db, &dest_info); + + if(PREDICT_FALSE(session_db == NULL)) { + disposition = CNAT_V4_ICMP_Q_O2I_D; + counter = CNAT_V4_ICMP_Q_O2I_NO_SESSION_DROP; + goto drop_pkt; + } + } else if (PREDICT_FALSE(db->nsessions == 0)) { + /* Should be a static entry + * Note this session as the first session and log + */ + cnat_add_dest_n_log(db, &dest_info); + } else { /* Many translations exist already */ + dest_info.k.vrf = db->in2out_key.k.vrf; + /* If session already exists, + * cnat_create_session_db_entry will return the existing db + * else create a new db + * If could not create, return NULL + */ + session_db = cnat_create_session_db_entry(&dest_info, + db, TRUE); + + if(PREDICT_FALSE(session_db == NULL)) { + disposition = CNAT_V4_ICMP_Q_O2I_D; + counter = CNAT_V4_ICMP_Q_O2I_NO_SESSION_DROP; + goto drop_pkt; + } + } + } + +update_pkt: + + if (PLATFORM_HANDLE_TTL_DECREMENT) { + /* + * Decrement TTL and update IPv4 checksum + */ + ipv4_decr_ttl_n_calc_csum(ip); + } + + /* + * 1. update dest ipv4 addr and icmp id + * 2. update ipv4 checksum and icmp checksum + */ + swap_ip_dst_icmp_id(ip, icmp, db, db->in2out_key.k.vrf); + + if (PREDICT_FALSE(icmp_debug_flag)) { + printf("\nDUMPING ICMP PKT AFTER\n"); + print_icmp_pkt(ip); + } + + db->out2in_pkts++; + + //nat44_dslite_global_stats[dslite_flag].out2in_forwarding_count++; + + } else { + disposition = CNAT_V4_ICMP_Q_O2I_D; + counter = CNAT_V4_ICMP_Q_O2I_MISS_PKT; + } + +drop_pkt: + em->counters[node_counter_base_index + counter] += 1; + return disposition; + +} + +#include + +static uword cnat_ipv4_icmp_q_outside_input_node_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + return dispatch_pipeline (vm, node, frame); +} + + +VLIB_REGISTER_NODE (cnat_ipv4_icmp_q_outside_input_node) = { + .function = cnat_ipv4_icmp_q_outside_input_node_fn, + .name = "vcgn-v4-icmp-q-o2i", + .vector_size = sizeof (u32), + .type = VLIB_NODE_TYPE_INTERNAL, + + .n_errors = ARRAY_LEN(cnat_ipv4_icmp_q_outside_input_error_strings), + .error_strings = cnat_ipv4_icmp_q_outside_input_error_strings, + + .n_next_nodes = CNAT_V4_ICMP_Q_O2I_NEXT, + + /* edit / add dispositions here */ + .next_nodes = { + [CNAT_V4_ICMP_Q_O2I_T] = "ip4-input", + [CNAT_V4_ICMP_Q_O2I_D] = "error-drop", + }, +}; + +clib_error_t *cnat_ipv4_icmp_q_outside_input_init (vlib_main_t *vm) +{ + cnat_ipv4_icmp_q_outside_input_main_t * mp = &cnat_ipv4_icmp_q_outside_input_main; + + mp->vlib_main = vm; + mp->vnet_main = vnet_get_main(); + + return 0; +} + +VLIB_INIT_FUNCTION (cnat_ipv4_icmp_q_outside_input_init); diff --git a/plugins/vcgn-plugin/vcgn/cnat_ipv4_tcp_inside_input.c b/plugins/vcgn-plugin/vcgn/cnat_ipv4_tcp_inside_input.c new file mode 100644 index 00000000..5bea7073 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_ipv4_tcp_inside_input.c @@ -0,0 +1,424 @@ +/* + *--------------------------------------------------------------------------- + * cnat_ipv4_tcp_inside_input.c - cnat_ipv4_tcp_inside_input node pipeline + * stage functions + * + * + * Copyright (c) 2008-2014 Cisco and/or its affiliates. + * 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 +#include +#include +#include + +#include "cnat_db.h" +#include "tcp_header_definitions.h" +#include "cnat_config.h" +#include "cnat_global.h" +#include "cnat_v4_functions.h" + +#define foreach_cnat_ipv4_tcp_inside_input_error \ +_(CNAT_V4_TCP_I2O_PKT_IN, "tcp i2o packets received") \ +_(CNAT_V4_TCP_I2O_PKT_T, "tcp i2o packets natted") \ +_(CNAT_V4_TCP_I2O_EXCEPTION, "packets to tcp i2o exception") \ +_(CNAT_V4_TCP_I2O_TTL_GEN, "generated TTL expiry ICMP packets") \ +_(CNAT_V4_TCP_I2O_TTL_GEN_DROP, "could not generate TTL expiry ICMP packets") \ +_(CNAT_V4_TCP_I2O_SESSION_DROP, "could not generate session") \ +_(CNAT_V4_UDP_I2O_FRAG_DROP, "non-first fragment drop") + +typedef enum { +#define _(sym,str) sym, + foreach_cnat_ipv4_tcp_inside_input_error +#undef _ + CNAT_IPV4_TCP_INSIDE_INPUT_N_ERROR, +} cnat_ipv4_tcp_inside_input_t; + +static char * cnat_ipv4_tcp_inside_input_error_strings[] = { +#define _(sym,string) string, + foreach_cnat_ipv4_tcp_inside_input_error +#undef _ +}; + +typedef struct { + u32 cached_next_index; + /* $$$$ add data here */ + + /* convenience variables */ + vlib_main_t * vlib_main; + vnet_main_t * vnet_main; +} cnat_ipv4_tcp_inside_input_main_t; + +typedef enum { + CNAT_V4_TCP_I2O_E, + CNAT_V4_TCP_I2O_T, + CNAT_V4_TCP_I2O_D, + CNAT_V4_TCP_I2O_NEXT, +} cnat_ipv4_tcp_inside_input_next_t; + +#define CNAT_REWRITE_OUTPUT CNAT_V4_TCP_I2O_T +#define CNAT_V4_ICMP_GEN CNAT_V4_TCP_I2O_D + +//#define CNAT_V4_TCP_I2O_E CNAT_V4_TCP_I2O_D //remove it once exception node is created +cnat_ipv4_tcp_inside_input_main_t cnat_ipv4_tcp_inside_input_main; +vlib_node_registration_t cnat_ipv4_tcp_inside_input_node; + +#define NSTAGES 6 + +/* + * Use the generic buffer metadata + first line of packet data prefetch + * stage function from . This is usually a Good Idea. + */ +#define stage0 generic_stage0 + + +static inline void +stage1(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) +{ + u64 a, b, c; + u32 bucket; + u8 *prefetch_target; + //cnat_feature_data_t *fd = (cnat_feature_data_t *)ctx->feature_data; + + + vlib_buffer_t * b0 = vlib_get_buffer (vm, buffer_index); + ipv4_header *ip = vlib_buffer_get_current (b0); + u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; + tcp_hdr_type *tcp = (tcp_hdr_type *)((u8*)ip + ipv4_hdr_len); + + u64 tmp = 0; + tmp = vnet_buffer(b0)->vcgn_uii.key.k.ipv4 = + clib_net_to_host_u32(ip->src_addr); + vnet_buffer(b0)->vcgn_uii.key.k.port = + clib_net_to_host_u16 (tcp->src_port); + + tmp |= ((u64)vnet_buffer(b0)->vcgn_uii.key.k.port) << 32; + + PLATFORM_CNAT_SET_RX_VRF(vnet_buffer(b0)->sw_if_index[VLIB_RX], + vnet_buffer(b0)->vcgn_uii.key.k.vrf, + CNAT_TCP) + tmp |= ((u64)vnet_buffer(b0)->vcgn_uii.key.k.vrf) << 48; + + CNAT_V4_GET_HASH(tmp, bucket, CNAT_MAIN_HASH_MASK) + + prefetch_target = (u8 *)(&cnat_in2out_hash[bucket]); + vnet_buffer(b0)->vcgn_uii.bucket = bucket; + + /* Prefetch the hash bucket */ + CLIB_PREFETCH(prefetch_target, CLIB_CACHE_LINE_BYTES, LOAD); +} + +static inline void +stage2(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) +{ /* nothing */ } + + +#define SPP_LOG2_CACHE_LINE_BYTES 6 +#define SPP_CACHE_LINE_BYTES (1 << SPP_LOG2_CACHE_LINE_BYTES) + +static inline void +stage3(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) +{ + vlib_buffer_t * b0 = vlib_get_buffer(vm, buffer_index); + uword prefetch_target0, prefetch_target1; + u32 bucket = vnet_buffer(b0)->vcgn_uii.bucket; + + /* read the hash bucket */ + u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket + = cnat_in2out_hash[bucket].next; + + if (PREDICT_TRUE(db_index != EMPTY)) { + /* + * Prefetch database keys. We save space by not cache-line + * aligning the DB entries. We don't want to waste LSU + * bandwidth prefetching stuff we won't need. + */ + prefetch_target0 = (uword)(cnat_main_db + db_index); + CLIB_PREFETCH((void*)prefetch_target0, CLIB_CACHE_LINE_BYTES, LOAD); + /* Just beyond DB key #2 */ + prefetch_target1 = prefetch_target0 + + STRUCT_OFFSET_OF(cnat_main_db_entry_t, user_ports); + /* If the targets are in different lines, do the second prefetch */ + if (PREDICT_FALSE((prefetch_target0 & ~(SPP_CACHE_LINE_BYTES-1)) != + (prefetch_target1 & ~(SPP_CACHE_LINE_BYTES-1)))) { + CLIB_PREFETCH((void *)prefetch_target1, CLIB_CACHE_LINE_BYTES, LOAD); + } + } +} + +static inline void +stage4(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) +{ + cnat_main_db_entry_t *db; + vlib_buffer_t * b0 = vlib_get_buffer(vm, buffer_index); + u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket; + + /* + * Note: if the search already failed (empty bucket), + * the answer is already in the pipeline context structure + */ + if (PREDICT_TRUE(db_index != EMPTY)) { + + /* + * Note: hash collisions suck. We can't easily prefetch around them. + * The first trip around the track will be fast. After that, maybe + * not so much... + */ + do { + db = cnat_main_db + db_index; + if (PREDICT_TRUE(db->in2out_key.key64 == + vnet_buffer(b0)->vcgn_uii.key.key64)) { + break; + } + db_index = db->in2out_hash.next; + } while (db_index != EMPTY); + + /* Stick the answer back into the pipeline context structure */ + vnet_buffer(b0)->vcgn_uii.bucket = db_index; + } +} + + +static inline u32 last_stage (vlib_main_t *vm, vlib_node_runtime_t *node, + u32 bi) +{ + vlib_buffer_t *b0 = vlib_get_buffer (vm, bi); + u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket; + spp_ctx_t *ctx = (spp_ctx_t *) &vnet_buffer(b0)->vcgn_uii; + int disposition = CNAT_V4_TCP_I2O_T; + int counter = CNAT_V4_TCP_I2O_PKT_T; + + ipv4_header *ip = (ipv4_header *)vlib_buffer_get_current(b0); + u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; + tcp_hdr_type *tcp = (tcp_hdr_type *)((u8*)ip + ipv4_hdr_len); + vlib_node_t *n = vlib_get_node (vm, cnat_ipv4_tcp_inside_input_node.index); + u32 node_counter_base_index = n->error_heap_index; + vlib_error_main_t * em = &vm->error_main; + cnat_session_entry_t *session_db = NULL; + cnat_main_db_entry_t *db = NULL; + cnat_key_t dest_info; + u32 window; + u8 scale; + + + INCREMENT_NODE_COUNTER(CNAT_V4_TCP_I2O_PKT_IN); + + if (PLATFORM_HANDLE_TTL_DECREMENT) { + if (PREDICT_FALSE(ip->ttl <= 1)) { + /* Try to generate ICMP error msg, as TTL is <= 1 */ + + if (icmpv4_generate_with_throttling + (ctx, ip, ctx->ru.rx.uidb_index)) { + + /* Generated ICMP */ + disposition = CNAT_REWRITE_OUTPUT; + counter = CNAT_V4_TCP_I2O_TTL_GEN; + } else { + /* Could not generated ICMP - drop the packet */ + disposition = CNAT_V4_TCP_I2O_D; + counter = CNAT_V4_TCP_I2O_TTL_GEN_DROP; + } + goto drop_pkt; + } + } + + if (PREDICT_FALSE(db_index == EMPTY)) { + /* Deleted fragment code from here */ + disposition = CNAT_V4_TCP_I2O_E; + counter = CNAT_V4_TCP_I2O_EXCEPTION; + } else { + db = cnat_main_db + db_index; + + /* Handle destination sessions */ + dest_info.k.port = clib_net_to_host_u16(tcp->dest_port); + dest_info.k.ipv4 = clib_net_to_host_u32(ip->dest_addr); + + if(PREDICT_TRUE(!PLATFORM_DBL_SUPPORT)) { + + /* No DBL support, so just update the destn and proceed */ + db->dst_ipv4 = dest_info.k.ipv4; + db->dst_port = dest_info.k.port; + goto update_pkt; + } + + if(PREDICT_FALSE(db->dst_ipv4 != dest_info.k.ipv4 || + db->dst_port != dest_info.k.port)) { + if(PREDICT_TRUE(db->nsessions == 0)) { + /* Should be a static entry + * Note this session as the first session and log + */ + cnat_add_dest_n_log(db, &dest_info); + } else if(PREDICT_FALSE(db->nsessions == 1)) { + /* Destn is not same as in main db. Multiple session + * scenario + */ + dest_info.k.vrf = db->in2out_key.k.vrf; + session_db = cnat_handle_1to2_session(db, &dest_info); + if(PREDICT_FALSE(session_db == NULL)) { + disposition = CNAT_V4_TCP_I2O_D; + counter = CNAT_V4_TCP_I2O_SESSION_DROP; + goto drop_pkt; + } + } else { /* There are already multiple destinations */ + dest_info.k.vrf = db->in2out_key.k.vrf; + /* If session already exists, + * cnat_create_session_db_entry will return the existing db + * else create a new db + * If could not create, return NULL + */ + session_db = cnat_create_session_db_entry(&dest_info, + db, TRUE); + if(PREDICT_FALSE(session_db == NULL)) { + disposition = CNAT_V4_TCP_I2O_D; + counter = CNAT_V4_TCP_I2O_SESSION_DROP; + goto drop_pkt; + } + } + if(PREDICT_TRUE(session_db != 0)) { + /* Have to repeat the window size check for new destinations */ + window = (u32)clib_net_to_host_u16(tcp->window_size); + window = window << session_db->scale; + if(PREDICT_TRUE(!session_db->window)) { + calculate_window_scale(tcp, &scale); + session_db->scale = scale; + session_db->window = window; + } else if (PREDICT_FALSE(session_db->window < + window)) { + /* Update the db entry with window option from packet */ + session_db->window = window; + } else { + /* Do nothing */ + } + session_db->tcp_seq_num = clib_net_to_host_u32(tcp->seq_num); + session_db->ack_no = clib_net_to_host_u32(tcp->ack_num); +#if DEBUG > 1 + printf("\n In2out SDB stages seq no = %u," + " ack no = %u, window = %u\n", + session_db->tcp_seq_num, + session_db->ack_no, + session_db->window); +#endif + + } + } else { + //Update the seq no and ack no for subsequent communication + //after connection establishment + //No need to update window here. Window is already updated + //during connection establishment + window = (u32)clib_net_to_host_u16(tcp->window_size); + window = window << db->scale; + if(PREDICT_FALSE(!ALG_ENABLED_DB(db))) { + //This check is done since proto_data is part of union in main + //db entry + db->proto_data.tcp_seq_chk.seq_no = + clib_net_to_host_u32(tcp->seq_num); + db->proto_data.tcp_seq_chk.ack_no = + clib_net_to_host_u32(tcp->ack_num); + } + if (PREDICT_FALSE(db->diff_window < window)) { + /* Update the db entry with window option from packet */ + db->diff_window = window; + } +#if DEBUG > 1 + printf("\n In2out MainDB seq no = %u," + "\n ack no = %u\n", + db->proto_data.tcp_seq_chk.seq_no, + db->proto_data.tcp_seq_chk.ack_no); + printf("\n In2out MAINDB window = %u\n", + db->diff_window); +#endif + } +update_pkt: + + counter = CNAT_V4_TCP_I2O_PKT_T; + disposition = CNAT_V4_TCP_I2O_T; + + /* NO FRAGMENT & ALG HANDLING. DELETING THE CODE */ + + if (PLATFORM_HANDLE_TTL_DECREMENT) { + /* + * Decrement TTL and update IPv4 checksum + */ + ipv4_decr_ttl_n_calc_csum(ip); + } + + tcp_in2out_nat_mss_n_checksum(ip, + tcp, + db->out2in_key.k.ipv4, + db->out2in_key.k.port, + db + /*, db->in2out_key.k.vrf */); + + /* update transaltion counters */ + db->in2out_pkts++; + in2out_forwarding_count++; + + /* update the timer for good mode, or evil mode dst_ip match */ + + if(PREDICT_FALSE(session_db != NULL)) { + V4_TCP_UPDATE_SESSION_DB_FLAG(session_db, tcp); + CNAT_DB_TIMEOUT_RST(session_db); + } else { + V4_TCP_UPDATE_SESSION_FLAG(db, tcp); + CNAT_DB_TIMEOUT_RST(db); + } + } + +drop_pkt: + + em->counters[node_counter_base_index + counter] += 1; + return disposition; +} + +#include + +static uword cnat_ipv4_tcp_inside_input_node_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + return dispatch_pipeline (vm, node, frame); +} + + +VLIB_REGISTER_NODE (cnat_ipv4_tcp_inside_input_node) = { + .function = cnat_ipv4_tcp_inside_input_node_fn, + .name = "vcgn-v4-tcp-i2o", + .vector_size = sizeof (u32), + .type = VLIB_NODE_TYPE_INTERNAL, + + .n_errors = ARRAY_LEN(cnat_ipv4_tcp_inside_input_error_strings), + .error_strings = cnat_ipv4_tcp_inside_input_error_strings, + + .n_next_nodes = CNAT_V4_TCP_I2O_NEXT, + + /* edit / add dispositions here */ + .next_nodes = { + [CNAT_V4_TCP_I2O_E] = "vcgn-v4-tcp-i2o-e", + [CNAT_V4_TCP_I2O_T] = "ip4-input", + [CNAT_V4_TCP_I2O_D] = "error-drop", + }, +}; + +clib_error_t *cnat_ipv4_tcp_inside_input_init (vlib_main_t *vm) +{ + cnat_ipv4_tcp_inside_input_main_t * mp = &cnat_ipv4_tcp_inside_input_main; + + mp->vlib_main = vm; + mp->vnet_main = vnet_get_main(); + + return 0; +} + +VLIB_INIT_FUNCTION (cnat_ipv4_tcp_inside_input_init); diff --git a/plugins/vcgn-plugin/vcgn/cnat_ipv4_tcp_inside_input_exceptions.c b/plugins/vcgn-plugin/vcgn/cnat_ipv4_tcp_inside_input_exceptions.c new file mode 100644 index 00000000..bc1bebb0 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_ipv4_tcp_inside_input_exceptions.c @@ -0,0 +1,314 @@ +/* + *--------------------------------------------------------------------------- + * cnat_ipv4_tcp_inside_input_exceptions.c - + * cnat_ipv4_tcp_inside_input_exceptions node pipeline stage functions + * + * + * Copyright (c) 2008-2014 Cisco and/or its affiliates. + * 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 +#include +#include +#include + +#include "cnat_db.h" +#include "tcp_header_definitions.h" +#include "cnat_config.h" +#include "cnat_global.h" +#include "cnat_v4_functions.h" + + +#define foreach_cnat_ipv4_tcp_inside_input_exc_error \ +_(CNAT_V4_TCP_I2O_E_T_PKT, "v4 tcp i2o-e transmit natted pkt") \ +_(CNAT_V4_TCP_I2O_E_D_NON_SYN_PKT, "v4 tcp i2o-e non syn drop") \ +_(CNAT_V4_TCP_I2O_E_D_INVALID_PKT, "v4 tcp i2o-e invalid pkt drop") \ +_(CNAT_V4_TCP_I2O_E_DROP, "v4 tcp i2o-e drop") \ +_(CNAT_V4_TCP_I2O_E_GEN_ICMP, "v4 tcp i2o-e gen icmp msg") \ +_(CNAT_V4_TCP_I2O_E_D_NO_SESSION, "v4 tcp i2o-e no session db entry drop") + +typedef enum { +#define _(sym,str) sym, + foreach_cnat_ipv4_tcp_inside_input_exc_error +#undef _ + CNAT_IPV4_TCP_INSIDE_INPUT_EXCEPTIONS_N_ERROR, +} cnat_ipv4_tcp_inside_input_exc_error_t; + + +static char * cnat_ipv4_tcp_inside_input_exc_error_strings[] = { +#define _(sym,string) string, + foreach_cnat_ipv4_tcp_inside_input_exc_error +#undef _ +}; + +typedef struct { + u32 cached_next_index; + /* $$$$ add data here */ + + /* convenience variables */ + vlib_main_t * vlib_main; + vnet_main_t * vnet_main; +} cnat_ipv4_tcp_inside_input_exc_main_t; + +typedef enum { + CNAT_V4_TCP_I2O_E_T, + //CNAT_V4_TCP_I2O_E_ICMP, + CNAT_V4_TCP_I2O_E_D, + CNAT_V4_TCP_I2O_E_NEXT, +} cnat_ipv4_udp_inside_input_exc_next_t; + +#define CNAT_V4_TCP_I2O_E_ICMP CNAT_V4_TCP_I2O_E_D + +cnat_ipv4_tcp_inside_input_exc_main_t cnat_ipv4_tcp_inside_input_exc_main; +vlib_node_registration_t cnat_ipv4_tcp_inside_input_exc_node; + +#define NSTAGES 2 + +/* + * Use the generic buffer metadata + first line of packet data prefetch + * stage function from . This is usually a Good Idea. + */ +#define stage0 generic_stage0 + + +static inline u32 last_stage (vlib_main_t *vm, vlib_node_runtime_t *node, + u32 bi) +{ + vlib_buffer_t *b0 = vlib_get_buffer (vm, bi); + vlib_node_t *n = + vlib_get_node (vm, cnat_ipv4_tcp_inside_input_exc_node.index); + u32 node_counter_base_index = n->error_heap_index; + vlib_error_main_t * em = &vm->error_main; + + cnat_gen_icmp_info info; + cnat_db_key_bucket_t ki; + cnat_main_db_entry_t *db = NULL; + ipv4_header *ip = (ipv4_header *)vlib_buffer_get_current(b0); + u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; + tcp_hdr_type *tcp = (tcp_hdr_type *)((u8*)ip + ipv4_hdr_len); + int disposition = CNAT_V4_TCP_I2O_E_T; + int counter = CNAT_V4_TCP_I2O_E_T_PKT; + cnat_key_t dest_info; + u32 window; + u8 scale; + + window = (u32)clib_net_to_host_u16(tcp->window_size); + calculate_window_scale(tcp, &scale); + + dest_info.k.port = clib_net_to_host_u16(tcp->dest_port); + dest_info.k.ipv4 = clib_net_to_host_u32(ip->dest_addr); + + PLATFORM_CNAT_SET_RX_VRF(vnet_buffer(b0)->sw_if_index[VLIB_RX], + dest_info.k.vrf, CNAT_TCP) + + /* for TCP if not SYN or if src_port is 0, silently drop the packet */ + if (PREDICT_FALSE(!((tcp->flags & TCP_FLAG_SYN) && (tcp->src_port)))) { + + /* + * If the packet is dropped due to both reasons, + * count it as invalid packet drop + */ + if (!tcp->src_port) { + counter = CNAT_V4_TCP_I2O_E_D_INVALID_PKT; + } else { + counter = CNAT_V4_TCP_I2O_E_D_NON_SYN_PKT; + } + disposition = CNAT_V4_TCP_I2O_E_D; + goto in2out_e; + } + + PLATFORM_CNAT_SET_RX_VRF(vnet_buffer(b0)->sw_if_index[VLIB_RX], + ki.k.k.vrf, CNAT_TCP) + + ki.k.k.ipv4 = clib_net_to_host_u32(ip->src_addr); + ki.k.k.port = clib_net_to_host_u16(tcp->src_port); + + db = cnat_get_main_db_entry_v2(&ki, PORT_SINGLE, PORT_TYPE_DYNAMIC, &info, + &dest_info); + + +#if DEBUG > 1 + if(PREDICT_TRUE(db)) { + printf("create db %x ip %x->%x port %x->%x dst_ip %x\n", db, + db->in2out_key.k.ipv4, db->out2in_key.k.ipv4, + db->in2out_key.k.port, db->out2in_key.k.port, db->dst_ipv4); + } +#endif + + + if (PREDICT_FALSE(db == 0)) { + /* failed to create new db entry due to either no more port, or user limit reached, + * need to generate ICMP type=3,code=13 msg here, + */ + + /* + * we rate limit the icmp msg per private user, + * so we don't flood a user with icmp msg + * in case the per user port limit reached + */ + if (PREDICT_TRUE(info.gen_icmp_msg == CNAT_ICMP_MSG)) { + /* KEEPING THINGS COMMENTED HERE..MAY NEED TO REVISIT AGAIN */ + #if 0 + u32 *fd = (u32*)ctx->feature_data; + fd[0] = info.svi_addr; + fd[1] = CNAT_ICMP_DEST_UNREACHABLE; + + /* + * Let's reverse the direction from i2o to o2i. + * This will help using the correct VRF in the fib lookup (AVSM) + * especially for the o2i_vrf_override case + */ + ctx->ru.rx.direction = 0; // 0 - o2i, 1 - i2o + #endif + disposition = CNAT_V4_TCP_I2O_E_ICMP; + counter = CNAT_V4_TCP_I2O_E_GEN_ICMP; + + } else { + disposition = CNAT_V4_TCP_I2O_E_D; + counter = CNAT_V4_TCP_I2O_E_DROP; + } + //DEBUG_I2O_DROP(CNAT_DEBUG_DROP_TCP) + } else { + + if (PLATFORM_HANDLE_TTL_DECREMENT) { + /* + * Decrement TTL and update IPv4 checksum + */ + ipv4_decr_ttl_n_calc_csum(ip); + } + + /* NAT the packet and fix checksum */ + + tcp_in2out_nat_mss_n_checksum(ip, + tcp, + db->out2in_key.k.ipv4, + db->out2in_key.k.port, + db + /*, db->in2out_key.k.vrf */); + + /* this must be inside to outside SYN, do mss here */ + + /* update translation counters */ + db->in2out_pkts++; + + /* set keepalive timer */ + + if(PREDICT_TRUE((dest_info.k.ipv4 == db->dst_ipv4) && + (dest_info.k.port == db->dst_port))) { + if(PREDICT_FALSE(!ALG_ENABLED_DB(db))) { + //This check is done since proto_data is part of union in main + //db entry + + db->proto_data.tcp_seq_chk.seq_no = + clib_net_to_host_u32(tcp->seq_num); + db->proto_data.tcp_seq_chk.ack_no = + clib_net_to_host_u32(tcp->ack_num); + db->scale = scale; + db->diff_window = window; + } +#if DEBUG > 1 + PLATFORM_DEBUG_PRINT("\nMain DB seq no = %u," + "ack no = %u, window = %u," + "scale = %u", + db->proto_data.tcp_seq_chk.seq_no, + db->proto_data.tcp_seq_chk.ack_no, + db->diff_window + db->scale); +#endif + V4_TCP_UPDATE_SESSION_FLAG(db, tcp); + /* Check timeout db if there is config for this */ + (void) query_and_update_db_timeout((void *)db, MAIN_DB_TYPE); + db->entry_expires = cnat_current_time; + } else { + /* Got to find out the session entry corresponding to this..*/ + cnat_session_entry_t *sdb; + sdb = cnat_session_db_lookup_entry( + &dest_info, db - cnat_main_db); + if(PREDICT_FALSE(sdb == NULL)) { + disposition = CNAT_V4_TCP_I2O_E_D; + counter = CNAT_V4_TCP_I2O_E_D_NO_SESSION; + goto in2out_e; + } + sdb->tcp_seq_num = clib_net_to_host_u32(tcp->seq_num); + sdb->ack_no = clib_net_to_host_u32(tcp->ack_num); + sdb->scale = scale; + sdb->window = window; + +#if DEBUG > 1 + PLATFORM_DEBUG_PRINT("\nSDB seq no = %u, ack no = %u, window = %u" + "\nSDB scale = %u" , + sdb->tcp_seq_num, + sdb->ack_no, + sdb->window, + sdb->scale); +#endif + V4_TCP_UPDATE_SESSION_DB_FLAG(sdb, tcp); + /* Check timeout db if there is config for this */ + (void) query_and_update_db_timeout((void *)sdb, SESSION_DB_TYPE); + sdb->entry_expires = cnat_current_time; + } + + //PLATFORM_CNAT_SET_TX_VRF(ctx,db->out2in_key.k.vrf) + + counter = CNAT_V4_TCP_I2O_E_T_PKT; + in2out_forwarding_count++; + } + +in2out_e: + + em->counters[node_counter_base_index + counter] += 1; + + return disposition; +} + +#include + +static uword cnat_ipv4_tcp_inside_input_exc_node_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + return dispatch_pipeline (vm, node, frame); +} + +VLIB_REGISTER_NODE (cnat_ipv4_tcp_inside_input_exc_node) = { + .function = cnat_ipv4_tcp_inside_input_exc_node_fn, + .name = "vcgn-v4-tcp-i2o-e", + .vector_size = sizeof (u32), + .type = VLIB_NODE_TYPE_INTERNAL, + + .n_errors = ARRAY_LEN(cnat_ipv4_tcp_inside_input_exc_error_strings), + .error_strings = cnat_ipv4_tcp_inside_input_exc_error_strings, + + .n_next_nodes = CNAT_V4_TCP_I2O_E_NEXT, + + /* edit / add dispositions here */ + .next_nodes = { + [CNAT_V4_TCP_I2O_E_T] = "ip4-input", + [CNAT_V4_TCP_I2O_E_D] = "error-drop", + }, +}; + + +clib_error_t *cnat_ipv4_tcp_inside_input_exc_init (vlib_main_t *vm) +{ + cnat_ipv4_tcp_inside_input_exc_main_t * mp = &cnat_ipv4_tcp_inside_input_exc_main; + + mp->vlib_main = vm; + mp->vnet_main = vnet_get_main(); + + return 0; +} + +VLIB_INIT_FUNCTION (cnat_ipv4_tcp_inside_input_exc_init); diff --git a/plugins/vcgn-plugin/vcgn/cnat_ipv4_tcp_outside_input.c b/plugins/vcgn-plugin/vcgn/cnat_ipv4_tcp_outside_input.c new file mode 100644 index 00000000..bcf132b1 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_ipv4_tcp_outside_input.c @@ -0,0 +1,382 @@ +/* + *--------------------------------------------------------------------------- + * cnat_ipv4_tcp_outside_input.c - cnat_v4_tcp_out2in node pipeline stage functions + * + * + * Copyright (c) 2008-2014 Cisco and/or its affiliates. + * 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 +#include +#include +#include + +#include "cnat_db.h" +#include "tcp_header_definitions.h" +#include "cnat_config.h" +#include "cnat_global.h" +#include "cnat_ipv4_udp.h" +#include "cnat_v4_functions.h" + + +#define foreach_cnat_ipv4_tcp_outside_input_error \ +_(CNAT_V4_TCP_O2I_R_PKT, "v4 tcp o2i pkt received") \ +_(CNAT_V4_TCP_O2I_T_PKT, "v4 tcp o2i pkt natted & transmitted") \ +_(CNAT_V4_TCP_O2I_LOOKUP_FAILED, "v4 tcp o2i lookup failed") \ +_(CNAT_V4_TCP_O2I_TTL_GEN, "v4 tcp o2i generated TTL Expiry ICMP packet") \ +_(CNAT_V4_TCP_O2I_TTL_DROP, "v4 tcp o2i drop due to failure in creating TTL expiry ICMP msg") \ +_(CNAT_V4_TCP_O2I_PTB_GEN, "v4 tcp o2i PTB ICMP pkt generation") \ +_(CNAT_V4_UDP_O2I_PTB_DROP, "v4 tcp o2i drop due to failure in creating PTB ICMP pkt") \ +_(CNAT_V4_TCP_O2I_SESSION_DROP, "v4 tcp o2i drop due to failure in creating session db") \ +_(CNAT_V4_TCP_O2I_SEQ_MISMATCH_DROP, "v4 tcp o2i drop due to TCP sequence mismatch") \ +_(CNAT_V4_TCP_O2I_FILTER_DROP, "v4 tcp o2i drop due to endpoint filtering") \ +_(CNAT_V4_TCP_O2I_NON_SYN_RST_DROP, "v4 tcp o2i drop due no syn/rst flag") \ +_(CNAT_V4_TCP_O2I_FIRST_FRAG_DROP, "v4 tcp o2i first fragment drop") \ +_(CNAT_V4_TCP_O2I_SUB_FRAG_NO_DB_DROP, "v4 tcp o2i subsequest frag no DB drop") + +typedef enum { +#define _(sym,str) sym, + foreach_cnat_ipv4_tcp_outside_input_error +#undef _ + CNAT_IPV4_TCP_OUTSIDE_INPUT_N_ERROR, +} cnat_ipv4_tcp_outside_input_t; + +static char * cnat_ipv4_tcp_outside_input_error_strings[] = { +#define _(sym,string) string, + foreach_cnat_ipv4_tcp_outside_input_error +#undef _ +}; + +typedef struct { + u32 cached_next_index; + /* $$$$ add data here */ + + /* convenience variables */ + vlib_main_t * vlib_main; + vnet_main_t * vnet_main; +} cnat_ipv4_tcp_outside_input_main_t; + +typedef enum { + //CNAT_V4_TCP_O2I_E, + CNAT_V4_TCP_O2I_T, + CNAT_V4_TCP_O2I_D, + CNAT_V4_TCP_O2I_NEXT, +} cnat_ipv4_tcp_outside_input_next_t; + +cnat_ipv4_tcp_outside_input_main_t cnat_ipv4_tcp_outside_input_main; +vlib_node_registration_t cnat_ipv4_tcp_outside_input_node; + +#define NSTAGES 6 + +/* + * Use the generic buffer metadata + first line of packet data prefetch + * stage function from . This is usually a Good Idea. + */ +#define stage0 generic_stage0 + + +static inline void +stage1(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) +{ + u64 a, b, c; + u32 bucket; + u8 *prefetch_target; + + + vlib_buffer_t * b0 = vlib_get_buffer (vm, buffer_index); + ipv4_header *ip = vlib_buffer_get_current (b0); + u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; + tcp_hdr_type *tcp = (tcp_hdr_type *)((u8*)ip + ipv4_hdr_len); + + u64 tmp = 0; + tmp = vnet_buffer(b0)->vcgn_uii.key.k.ipv4 = + clib_net_to_host_u32(ip->dest_addr); + vnet_buffer(b0)->vcgn_uii.key.k.port = + clib_net_to_host_u16 (tcp->dest_port); + + tmp |= ((u64)vnet_buffer(b0)->vcgn_uii.key.k.port) << 32; + + PLATFORM_CNAT_SET_RX_VRF(vnet_buffer(b0)->sw_if_index[VLIB_RX], + vnet_buffer(b0)->vcgn_uii.key.k.vrf, + CNAT_TCP) + tmp |= ((u64)vnet_buffer(b0)->vcgn_uii.key.k.vrf) << 48; + + CNAT_V4_GET_HASH(tmp, bucket, CNAT_MAIN_HASH_MASK) + + prefetch_target = (u8 *)(&cnat_out2in_hash[bucket]); + vnet_buffer(b0)->vcgn_uii.bucket = bucket; + + /* Prefetch the hash bucket */ + CLIB_PREFETCH(prefetch_target, CLIB_CACHE_LINE_BYTES, LOAD); +} + +static inline void +stage2(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) +{ /* nothing */ } + +#define SPP_LOG2_CACHE_LINE_BYTES 6 +#define SPP_CACHE_LINE_BYTES (1 << SPP_LOG2_CACHE_LINE_BYTES) + +static inline void +stage3(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) +{ + vlib_buffer_t * b0 = vlib_get_buffer(vm, buffer_index); + uword prefetch_target0, prefetch_target1; + u32 bucket = vnet_buffer(b0)->vcgn_uii.bucket; + + /* read the hash bucket */ + u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket + = cnat_out2in_hash[bucket].next; + + if (PREDICT_TRUE(db_index != EMPTY)) { + /* + * Prefetch database keys. We save space by not cache-line + * aligning the DB entries. We don't want to waste LSU + * bandwidth prefetching stuff we won't need. + */ + prefetch_target0 = (uword)(cnat_main_db + db_index); + CLIB_PREFETCH((void*)prefetch_target0, CLIB_CACHE_LINE_BYTES, STORE); + /* Just beyond DB key #2 */ + prefetch_target1 = prefetch_target0 + + STRUCT_OFFSET_OF(cnat_main_db_entry_t, user_ports); + /* If the targets are in different lines, do the second prefetch */ + if (PREDICT_FALSE((prefetch_target0 & ~(SPP_CACHE_LINE_BYTES-1)) != + (prefetch_target1 & ~(SPP_CACHE_LINE_BYTES-1)))) { + CLIB_PREFETCH((void *)prefetch_target1, CLIB_CACHE_LINE_BYTES, STORE); + } + } +} + +static inline void +stage4(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) +{ + cnat_main_db_entry_t *db; + vlib_buffer_t * b0 = vlib_get_buffer(vm, buffer_index); + u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket; + + /* + * Note: if the search already failed (empty bucket), + * the answer is already in the pipeline context structure + */ + if (PREDICT_TRUE(db_index != EMPTY)) { + + /* + * Note: hash collisions suck. We can't easily prefetch around them. + * The first trip around the track will be fast. After that, maybe + * not so much... + */ + do { + db = cnat_main_db + db_index; + if (PREDICT_TRUE(db->out2in_key.key64 == + vnet_buffer(b0)->vcgn_uii.key.key64)) { + break; + } + db_index = db->out2in_hash.next; + } while (db_index != EMPTY); + + /* Stick the answer back into the pipeline context structure */ + vnet_buffer(b0)->vcgn_uii.bucket = db_index; + } +} + +static inline u32 last_stage (vlib_main_t *vm, vlib_node_runtime_t *node, + u32 bi) +{ + vlib_buffer_t *b0 = vlib_get_buffer (vm, bi); + u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket; + spp_ctx_t *ctx = (spp_ctx_t *) &vnet_buffer(b0)->vcgn_uii; + int disposition = CNAT_V4_TCP_O2I_T; + int counter = CNAT_V4_TCP_O2I_T_PKT; + + ipv4_header *ip = (ipv4_header *)vlib_buffer_get_current(b0); + u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; + tcp_hdr_type *tcp = (tcp_hdr_type *)((u8*)ip + ipv4_hdr_len); + vlib_node_t *n = vlib_get_node (vm, cnat_ipv4_tcp_outside_input_node.index); + u32 node_counter_base_index = n->error_heap_index; + vlib_error_main_t * em = &vm->error_main; + cnat_session_entry_t *session_db = NULL; + cnat_main_db_entry_t *db = NULL; + cnat_key_t dest_info; + + INCREMENT_NODE_COUNTER(CNAT_V4_TCP_O2I_R_PKT); + + if (PREDICT_FALSE(db_index == EMPTY)) { + nat44_dslite_common_stats[0].no_translation_entry_drops ++; + counter = CNAT_V4_TCP_O2I_LOOKUP_FAILED; + disposition = CNAT_V4_TCP_O2I_D; + } else { + if (PLATFORM_HANDLE_TTL_DECREMENT) { + if (PREDICT_FALSE(ip->ttl <= 1)) { + /* Try to generate ICMP error msg, as TTL is <= 1 */ + if (icmpv4_generate_with_throttling(ctx, + ip, ctx->ru.rx.uidb_index)) { + /* Generated ICMP */ + disposition = CNAT_V4_TCP_O2I_T_PKT; //CNAT_REWRITE_OUTPUT; + counter = CNAT_V4_TCP_O2I_TTL_GEN; + } else { + /* Could not generated ICMP - drop the packet */ + disposition = CNAT_V4_TCP_O2I_D; + counter = CNAT_V4_TCP_O2I_TTL_DROP; + } + goto drop_pkt; + } + } + db = cnat_main_db + db_index; +#if 0 + window = db->diff_window; + stored_seq_no = db->proto_data.tcp_seq_chk.seq_no; + stored_ack_no = db->proto_data.tcp_seq_chk.ack_no; + vrf_map_p = cnat_map_by_vrf + db->vrfmap_index; + vrf_index = (db->in2out_key.k.vrf & CNAT_VRF_MASK); +#endif + /* For Out2In packet, the dest info is src address and port */ + dest_info.k.port = clib_net_to_host_u16(tcp->src_port); + dest_info.k.ipv4 = clib_net_to_host_u32(ip->src_addr); + + if(PREDICT_TRUE(!PLATFORM_DBL_SUPPORT)) { + + /* No DBL support, so just update the destn and proceed */ + db->dst_ipv4 = dest_info.k.ipv4; + db->dst_port = dest_info.k.port; + goto update_pkt; + } + + + if(PREDICT_FALSE(db->dst_ipv4 != dest_info.k.ipv4 || + db->dst_port != dest_info.k.port)) { + + if(PREDICT_TRUE(db->nsessions == 0)) { + /* Should be a static entry + * Note this session as the first session and log + */ + cnat_add_dest_n_log(db, &dest_info); + //goto packet_upd; + } else if(PREDICT_FALSE(db->nsessions == 1)) { + /* Destn is not same as in main db. Multiple session + * scenario + */ + dest_info.k.vrf = db->in2out_key.k.vrf; + session_db = cnat_handle_1to2_session(db, &dest_info); + if(PREDICT_FALSE(session_db == NULL)) { + disposition = CNAT_V4_TCP_O2I_D; + counter = CNAT_V4_TCP_O2I_SESSION_DROP; + goto drop_pkt; + } + } else { /* There are already multiple destinations */ + dest_info.k.vrf = db->in2out_key.k.vrf; + /* If session already exists, + * cnat_create_session_db_entry will return the existing db + * else create a new db + * If could not create, return NULL + */ + session_db = cnat_create_session_db_entry(&dest_info, db, TRUE); + if(PREDICT_FALSE(session_db == NULL)) { + disposition = CNAT_V4_TCP_O2I_D; + counter = CNAT_V4_TCP_O2I_SESSION_DROP; + goto drop_pkt; + } + } + /* useful for ALG only */ + #if 0 + if(PREDICT_TRUE(session_db)) { + stored_seq_no = session_db->tcp_seq_num; + stored_ack_no = session_db->ack_no; + window = session_db->window; + } + #endif + } + + +update_pkt: + + counter = CNAT_V4_TCP_O2I_T_PKT; + + if (PLATFORM_HANDLE_TTL_DECREMENT) { + /* + * Decrement TTL and update IPv4 checksum + */ + ipv4_decr_ttl_n_calc_csum(ip); + } + + /* update ip checksum, newchecksum = ~(~oldchecksum + ~old + new) */ + cnat_v4_recalculate_tcp_checksum(ip, tcp, + &(ip->dest_addr), + &(tcp->dest_port), + db->in2out_key.k.ipv4, + db->in2out_key.k.port); + + /* CNAT_PPTP_ALG_SUPPORT */ + db->out2in_pkts++; + + nat44_dslite_global_stats[0].out2in_forwarding_count++;; + + V4_TCP_UPDATE_SESSION_FLAG(db, tcp); + + + if(PREDICT_FALSE(session_db != NULL)) { + V4_TCP_UPDATE_SESSION_DB_FLAG(session_db, tcp); + CNAT_DB_TIMEOUT_RST(session_db); + } else { + V4_TCP_UPDATE_SESSION_FLAG(db, tcp); + CNAT_DB_TIMEOUT_RST(db); + } + + } + +drop_pkt: + em->counters[node_counter_base_index + counter] += 1; + return disposition; +} + +#include + +static uword cnat_ipv4_tcp_outside_input_node_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + return dispatch_pipeline (vm, node, frame); +} + + +VLIB_REGISTER_NODE (cnat_ipv4_tcp_outside_input_node) = { + .function = cnat_ipv4_tcp_outside_input_node_fn, + .name = "vcgn-v4-tcp-o2i", + .vector_size = sizeof (u32), + .type = VLIB_NODE_TYPE_INTERNAL, + + .n_errors = ARRAY_LEN(cnat_ipv4_tcp_outside_input_error_strings), + .error_strings = cnat_ipv4_tcp_outside_input_error_strings, + + .n_next_nodes = CNAT_V4_TCP_O2I_NEXT, + + /* edit / add dispositions here */ + .next_nodes = { + //[CNAT_V4_TCP_O2I_E] = "vcgn-v4-tcp-o2i-e", + [CNAT_V4_TCP_O2I_T] = "ip4-input", + [CNAT_V4_TCP_O2I_D] = "error-drop", + }, +}; + +clib_error_t *cnat_ipv4_tcp_outside_input_init (vlib_main_t *vm) +{ + cnat_ipv4_tcp_outside_input_main_t * mp = &cnat_ipv4_tcp_outside_input_main; + + mp->vlib_main = vm; + mp->vnet_main = vnet_get_main(); + + return 0; +} + +VLIB_INIT_FUNCTION (cnat_ipv4_tcp_outside_input_init); diff --git a/plugins/vcgn-plugin/vcgn/cnat_ipv4_udp.h b/plugins/vcgn-plugin/vcgn/cnat_ipv4_udp.h new file mode 100644 index 00000000..1ccf74a0 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_ipv4_udp.h @@ -0,0 +1,41 @@ +/* + *----------------------------------------------------------------------------- + * + * Filename: cnat_ipv4_udp.h + * + * Description: common functions for udp node + * + * Assumptions and Constraints: + * + * Copyright (c) 2000-2009 Cisco and/or its affiliates. + * 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 __CNAT_IPV4_UDP_H__ +#define __CNAT_IPV4_UDP_H__ + +#include "tcp_header_definitions.h" +#include "cnat_db.h" +#include "cnat_v4_functions.h" +#include "cnat_global.h" +#include "cnat_config.h" + +extern void swap_ip_src_udp_port(ipv4_header *ip, + udp_hdr_type_t *udp, + cnat_main_db_entry_t *db); +extern void swap_ip_dst_udp_port(ipv4_header *ip, + udp_hdr_type_t *udp, + cnat_main_db_entry_t *db, + u16 vrf); +#endif /* __CNAT_IPV4_UDP_H__ */ diff --git a/plugins/vcgn-plugin/vcgn/cnat_ipv4_udp_inside_input.c b/plugins/vcgn-plugin/vcgn/cnat_ipv4_udp_inside_input.c new file mode 100644 index 00000000..657c5f1e --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_ipv4_udp_inside_input.c @@ -0,0 +1,508 @@ +/* + *--------------------------------------------------------------------------- + * cnat_ipv4_udp_inside_input.c - cnat_ipv4_udp_inside_input node functions + * + * + * Copyright (c) 2008-2014 Cisco and/or its affiliates. + * 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 +#include +#include +#include + +#include "cnat_global.h" +#include "cnat_db.h" +#include "cnat_ipv4_udp.h" +#include "cnat_pcp_server.h" + + +#define foreach_cnat_ipv4_udp_inside_input_error \ +_(CNAT_V4_UDP_I2O_T_PKT, "v4 udp i2o transmit") \ +_(CNAT_V4_UDP_I2O_MISS_PKT, "v4 udp i2o db miss") \ +_(CNAT_V4_UDP_I2O_TTL_GEN, "v4 udp i2o TTL gen") \ +_(CNAT_V4_UDP_I2O_TTL_DROP, "v4 udp i2o TTL drop") \ +_(CNAT_V4_PCP_PKT, "v4 pcp pkt") \ +_(CNAT_V4_UDP_I2O_SESSION_DROP, "v4 udp i2o session drop") + +typedef enum { +#define _(sym,str) sym, + foreach_cnat_ipv4_udp_inside_input_error +#undef _ + CNAT_IPV4_UDP_INSIDE_INPUT_N_ERROR, +} cnat_ipv4_udp_inside_input_t; + +static char * cnat_ipv4_udp_inside_input_error_strings[] = { +#define _(sym,string) string, + foreach_cnat_ipv4_udp_inside_input_error +#undef _ +}; + +typedef struct { + u32 cached_next_index; + /* $$$$ add data here */ + + /* convenience variables */ + vlib_main_t * vlib_main; + vnet_main_t * vnet_main; +} cnat_ipv4_udp_inside_input_main_t; + +typedef enum { + CNAT_V4_I2O_FIXME, + CNAT_V4_UDP_I2O_E, + CNAT_REWRITE_OUTPUT, + CNAT_V4_UDP_I2O_T = CNAT_REWRITE_OUTPUT, + CNAT_N_NEXT, +} cnat_ipv4_udp_inside_input_next_t; + +#define CNAT_V4_UDP_I2O_D CNAT_V4_I2O_FIXME +#define CNAT_V4_PCP_T CNAT_V4_I2O_FIXME + +cnat_ipv4_udp_inside_input_main_t cnat_ipv4_udp_inside_input_main; +vlib_node_registration_t cnat_ipv4_udp_inside_input_node; + +#define NSTAGES 6 + +/* + * Use the generic buffer metadata + first line of packet data prefetch + * stage function from . This is usually a Good Idea. + */ +#define stage0 generic_stage0 + +#ifndef TOBE_PORTED +static inline u32 +is_pcp_pkt(u32 addr, u16 port) +{ + return CNAT_NO_CONFIG; +} +#else +static inline u32 +is_pcp_pkt(spp_ctx_t *ctx, u32 addr, u16 port) +{ + cnat_vrfmap_t *my_vrfmap = NULL; + u16 my_vrfmap_index; + + my_vrfmap_index = vrf_map_array[ctx->ru.rx.uidb_index]; + + if (PREDICT_TRUE(my_vrfmap_index != VRF_MAP_ENTRY_EMPTY)) { + + my_vrfmap = cnat_map_by_vrf + my_vrfmap_index; + + if (PREDICT_FALSE( port == my_vrfmap->pcp_server_port)) { + if(PREDICT_TRUE(addr == my_vrfmap->pcp_server_addr)) { + return CNAT_SUCCESS; + } + } + } + + return CNAT_NO_CONFIG; +} +#endif + +inline void swap_ip_src_udp_port(ipv4_header *ip, + udp_hdr_type_t *udp, + cnat_main_db_entry_t *db) +{ + /* + * declare varibale + */ + CNAT_UPDATE_L3_L4_CHECKSUM_DECLARE + /* + * calculate checksum + */ + CNAT_UPDATE_L3_L4_CHECKSUM(((u16)(db->in2out_key.k.ipv4)), + ((u16)(db->in2out_key.k.ipv4 >> 16)), + (db->in2out_key.k.port), + (clib_net_to_host_u16(ip->checksum)), + (clib_net_to_host_u16(udp->udp_checksum)), + ((u16)(db->out2in_key.k.ipv4)), + ((u16)(db->out2in_key.k.ipv4 >> 16)), + (db->out2in_key.k.port)) + +/* #define UDP_PACKET_DEBUG 1 */ + +// Temporary debugs which will be suppressed later +#ifdef UDP_PACKET_DEBUG + if (PREDICT_FALSE(udp_inside_packet_dump_enable)) { + printf("\nIn2Out UDP packet before translation"); + print_udp_pkt(ip); + } +#endif + + //set ip header + ip->src_addr = + clib_host_to_net_u32(db->out2in_key.k.ipv4); + ip->checksum = + clib_host_to_net_u16(new_l3_c); + + u16 frag_offset = + clib_net_to_host_u16(ip->frag_flags_offset); + + if(PREDICT_FALSE(frag_offset & IP_FRAG_OFFSET_MASK)) { + return; /* No need to update UDP fields */ + } + //set udp header + udp->src_port = + clib_host_to_net_u16(db->out2in_key.k.port); + + /* + * No easy way to avoid this if check except by using + * complex logic - may not be worth it. + */ + if (PREDICT_TRUE(udp->udp_checksum)) { + udp->udp_checksum = + clib_host_to_net_u16(new_l4_c); + } + +// Temporary debugs which will be suppressed later +#ifdef UDP_PACKET_DEBUG + if (PREDICT_FALSE(udp_inside_checksum_disable)) { + printf("\nIn2Out UDP checksum 0x%x disabled by force", new_l4_c); + udp->udp_checksum = 0; + } + if (PREDICT_FALSE(udp_inside_packet_dump_enable)) { + printf("\nIn2Out UDP packet after translation"); + print_udp_pkt(ip); + } +#endif +} + +static inline void +stage1(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) +{ + u64 a, b, c; + u32 bucket; + u8 *prefetch_target; + + vlib_buffer_t * b0 = vlib_get_buffer (vm, buffer_index); + ipv4_header *ip = vlib_buffer_get_current (b0); + u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; + udp_hdr_type_t *udp = (udp_hdr_type_t *)((u8*)ip + ipv4_hdr_len); + + u64 tmp = 0; + tmp = vnet_buffer(b0)->vcgn_uii.key.k.ipv4 = + clib_net_to_host_u32(ip->src_addr); + vnet_buffer(b0)->vcgn_uii.key.k.port = + clib_net_to_host_u16 (udp->src_port); + + tmp |= ((u64)vnet_buffer(b0)->vcgn_uii.key.k.port) << 32; + + PLATFORM_CNAT_SET_RX_VRF(vnet_buffer(b0)->sw_if_index[VLIB_RX], + vnet_buffer(b0)->vcgn_uii.key.k.vrf, + CNAT_UDP) + tmp |= ((u64)vnet_buffer(b0)->vcgn_uii.key.k.vrf) << 48; + + CNAT_V4_GET_HASH(tmp, bucket, CNAT_MAIN_HASH_MASK) + + prefetch_target = (u8 *)(&cnat_in2out_hash[bucket]); + vnet_buffer(b0)->vcgn_uii.bucket = bucket; + + /* Prefetch the hash bucket */ + CLIB_PREFETCH(prefetch_target, CLIB_CACHE_LINE_BYTES, LOAD); +} + +static inline void +stage2(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) +{ /* nothing */ } + +#define SPP_LOG2_CACHE_LINE_BYTES 6 +#define SPP_CACHE_LINE_BYTES (1 << SPP_LOG2_CACHE_LINE_BYTES) + +static inline void +stage3(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) +{ + vlib_buffer_t * b0 = vlib_get_buffer(vm, buffer_index); + uword prefetch_target0, prefetch_target1; + u32 bucket = vnet_buffer(b0)->vcgn_uii.bucket; + + /* read the hash bucket */ + u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket + = cnat_in2out_hash[bucket].next; + + if (PREDICT_TRUE(db_index != EMPTY)) { + /* + * Prefetch database keys. We save space by not cache-line + * aligning the DB entries. We don't want to waste LSU + * bandwidth prefetching stuff we won't need. + */ + prefetch_target0 = (uword)(cnat_main_db + db_index); + CLIB_PREFETCH((void*)prefetch_target0, CLIB_CACHE_LINE_BYTES, LOAD); + /* Just beyond DB key #2 */ + prefetch_target1 = prefetch_target0 + + STRUCT_OFFSET_OF(cnat_main_db_entry_t, user_ports); + /* If the targets are in different lines, do the second prefetch */ + if (PREDICT_FALSE((prefetch_target0 & ~(SPP_CACHE_LINE_BYTES-1)) != + (prefetch_target1 & ~(SPP_CACHE_LINE_BYTES-1)))) { + CLIB_PREFETCH((void *)prefetch_target1, CLIB_CACHE_LINE_BYTES, LOAD); + } + } +} + +static inline void +stage4(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) +{ + cnat_main_db_entry_t *db; + vlib_buffer_t * b0 = vlib_get_buffer(vm, buffer_index); + u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket; + + /* + * Note: if the search already failed (empty bucket), + * the answer is already in the pipeline context structure + */ + if (PREDICT_TRUE(db_index != EMPTY)) { + + /* + * Note: hash collisions suck. We can't easily prefetch around them. + * The first trip around the track will be fast. After that, maybe + * not so much... + */ + do { + db = cnat_main_db + db_index; + if (PREDICT_TRUE(db->in2out_key.key64 == + vnet_buffer(b0)->vcgn_uii.key.key64)) { + break; + } + db_index = db->in2out_hash.next; + } while (db_index != EMPTY); + + /* Stick the answer back into the pipeline context structure */ + vnet_buffer(b0)->vcgn_uii.bucket = db_index; + } +} + +static u64 pkt_num = 0; +static inline u32 last_stage (vlib_main_t *vm, vlib_node_runtime_t *node, + u32 bi) +{ + vlib_buffer_t *b0 = vlib_get_buffer (vm, bi); + u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket; + spp_ctx_t *ctx = (spp_ctx_t *) &vnet_buffer(b0)->vcgn_uii; + int disposition = CNAT_V4_UDP_I2O_T; + int counter = CNAT_V4_UDP_I2O_T_PKT; + ipv4_header *ip = (ipv4_header *)vlib_buffer_get_current(b0); + u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; + udp_hdr_type_t *udp = (udp_hdr_type_t *)((u8*)ip + ipv4_hdr_len); + vlib_node_t *n = vlib_get_node (vm, cnat_ipv4_udp_inside_input_node.index); + u32 node_counter_base_index = n->error_heap_index; + vlib_error_main_t * em = &vm->error_main; + cnat_session_entry_t *session_db = NULL; + cnat_key_t dest_info; + + pkt_num++; + + if(PREDICT_FALSE(is_pcp_pkt(ip->dest_addr, udp->dest_port) == + CNAT_SUCCESS)) + { + PCP_INCR(input); + disposition = CNAT_V4_PCP_T; + counter = CNAT_V4_PCP_PKT; + + goto pcp_pkt; + } + + if (PLATFORM_HANDLE_TTL_DECREMENT) { + if (PREDICT_FALSE(ip->ttl <= 1)) { + /* Try to generate ICMP error msg, as TTL is <= 1 */ + + if (icmpv4_generate_with_throttling + (ctx, ip, ctx->ru.rx.uidb_index)) { + /* Generated ICMP */ + disposition = CNAT_REWRITE_OUTPUT; + counter = CNAT_V4_UDP_I2O_TTL_GEN; + } else { + /* Could not generated ICMP - drop the packet */ + disposition = CNAT_V4_UDP_I2O_D; + counter = CNAT_V4_UDP_I2O_TTL_DROP; + } + goto drop_pkt; + } + } + if (PREDICT_TRUE(db_index != EMPTY)) { + cnat_main_db_entry_t *db = cnat_main_db + db_index; + + dest_info.k.ipv4 = clib_net_to_host_u32(ip->dest_addr); + + /* MUST revisit: it seems farg is set to 1 for few packets & because of + * this the port is not updated & it becomes 0. Commenting teporarily + * this fargment check & setting dst port with udp dst port value */ + dest_info.k.port = clib_net_to_host_u16(udp->dest_port); + #if 0 // DONOT REMOVE THIS if 0 + if(PREDICT_FALSE(ctx->ru.rx.frag)) { +#ifdef TOBE_PORTED + /* Must have routed through cnat_v4_frag_in2out node */ + u16 *feature_data_ports = (u16 *)&ctx->feature_data[4]; + dest_info.k.port = *feature_data_ports; +#endif + } else { + dest_info.k.port = clib_net_to_host_u16(udp->dest_port); + } + #endif + + + if (PLATFORM_HANDLE_TTL_DECREMENT) { + /* + * Decrement TTL and update IPv4 checksum + */ + ipv4_decr_ttl_n_calc_csum(ip); + } + + if(PREDICT_TRUE(!PLATFORM_DBL_SUPPORT)) { + + /* No DBL support, so just update the destn and proceed */ + db->dst_ipv4 = dest_info.k.ipv4; + db->dst_port = dest_info.k.port; + CNAT_DB_TIMEOUT_RST(db); + goto update_pkt; + } + + if(PREDICT_TRUE((db->dst_ipv4 == dest_info.k.ipv4) && + (db->dst_port == dest_info.k.port))) { + + CNAT_DB_TIMEOUT_RST(db); + goto update_pkt; + } else { + if (PREDICT_FALSE(db->nsessions == 0)) { + /* Should be a static entry + * Note this session as the first session and log + */ + cnat_add_dest_n_log(db, &dest_info); + /* + * update db counter, timer + */ + + CNAT_DB_TIMEOUT_RST(db); + + } else if(PREDICT_TRUE(db->nsessions == 1)) { + /* Destn is not same as in main db. Multiple session + * scenario + */ + //printf(">>> [pkt# %lu] src_ip: 0x%x, db ip: 0x%x, db port: %u; dest ip: 0x%x, dest port: %u\n", + // pkt_num, ntohl(ip->src_addr), db->dst_ipv4, db->dst_port, dest_info.k.ipv4, dest_info.k.port); + + dest_info.k.vrf = db->in2out_key.k.vrf; + session_db = cnat_handle_1to2_session(db, &dest_info); + + if(PREDICT_TRUE(session_db != NULL)) { + /* session exists */ + CNAT_DB_TIMEOUT_RST(session_db); + } else { + /* could not create session db - drop packet */ + disposition = CNAT_V4_UDP_I2O_D; + counter = CNAT_V4_UDP_I2O_SESSION_DROP; + goto drop_pkt; + } + + } else { + /* More than 2 sessions exists */ + + dest_info.k.vrf = db->in2out_key.k.vrf; + + /* If session already exists, + * cnat_create_session_db_entry will return the existing db + * else create a new db + * If could not create, return NULL + */ + session_db = cnat_create_session_db_entry(&dest_info, + db, TRUE); + + if(PREDICT_FALSE(session_db != NULL)) { + /* session exists */ + CNAT_DB_TIMEOUT_RST(session_db); + } else { + /* could not create session db - drop packet */ + disposition = CNAT_V4_UDP_I2O_D; + counter = CNAT_V4_UDP_I2O_SESSION_DROP; + goto drop_pkt; + } + } + } + +update_pkt: + /* + * 1. update src ipv4 addr and src udp port + * 2. update ipv4 checksum and udp checksum + */ + swap_ip_src_udp_port(ip, udp, db); + /* + * update db counter, timer + */ + + db->in2out_pkts++; + + /* + * need to set outside vrf + * from db->out2in_key.k.vrf + */ + + /* Temporarily keeping this commented */ + //PLATFORM_CNAT_SET_TX_VRF(vnet_buffer(b0)->sw_if_index[VLIB_TX], + // db->out2in_key.k.vrf) + + in2out_forwarding_count++; + + } else { + disposition = CNAT_V4_UDP_I2O_E; + counter = CNAT_V4_UDP_I2O_MISS_PKT; + } + +drop_pkt: +pcp_pkt: + + em->counters[node_counter_base_index + counter] += 1; + + return disposition; +} + +#include + +static uword cnat_ipv4_udp_inside_input_node_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + return dispatch_pipeline (vm, node, frame); +} + + +VLIB_REGISTER_NODE (cnat_ipv4_udp_inside_input_node) = { + .function = cnat_ipv4_udp_inside_input_node_fn, + .name = "vcgn-v4-udp-i2o", + .vector_size = sizeof (u32), + .type = VLIB_NODE_TYPE_INTERNAL, + + .n_errors = ARRAY_LEN(cnat_ipv4_udp_inside_input_error_strings), + .error_strings = cnat_ipv4_udp_inside_input_error_strings, + + .n_next_nodes = CNAT_N_NEXT, + + /* edit / add dispositions here */ + .next_nodes = { + [CNAT_V4_I2O_FIXME] = "error-drop", + // [CNAT_V4_UDP_I2O_T] = "ip4-input", + [CNAT_V4_UDP_I2O_E] = "vcgn-v4-udp-i2o-e", + [CNAT_REWRITE_OUTPUT] = "ip4-input", + }, +}; + +clib_error_t *cnat_ipv4_udp_inside_input_init (vlib_main_t *vm) +{ + cnat_ipv4_udp_inside_input_main_t * mp = &cnat_ipv4_udp_inside_input_main; + + mp->vlib_main = vm; + mp->vnet_main = vnet_get_main(); + + return 0; +} + +VLIB_INIT_FUNCTION (cnat_ipv4_udp_inside_input_init); diff --git a/plugins/vcgn-plugin/vcgn/cnat_ipv4_udp_inside_input_exceptions.c b/plugins/vcgn-plugin/vcgn/cnat_ipv4_udp_inside_input_exceptions.c new file mode 100644 index 00000000..f078c8d4 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_ipv4_udp_inside_input_exceptions.c @@ -0,0 +1,283 @@ +/* + *--------------------------------------------------------------------------- + * cnat_ipv4_udp_inside_input_exception_stages.c - cnat_ipv4_udp_inside_input_exception node pipeline stage functions + * + * + * Copyright (c) 2008-2014 Cisco and/or its affiliates. + * 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 +#include +#include +#include + +#include "cnat_global.h" +#include "cnat_db.h" +#include "cnat_ipv4_udp.h" + +/* + * Dump these counters via the "show error" CLI command + */ + +#define foreach_cnat_ipv4_udp_inside_input_exc_error \ +_(CNAT_V4_UDP_I2O_T_PKT, "v4 udp i2o transmit") \ +_(CNAT_V4_UDP_I2O_D_PKT, "v4 udp i2o drop") \ +_(CNAT_V4_ICMP_G_I2O_T_PKT, "v4 udp i2o icmp msg gen") \ +_(CNAT_V4_UDP_I2O_DC_PKT, "v4 udp i2o (no config) drop") \ +_(CNAT_V4_UDP_I2O_DR_PKT, "v4 udp i2o (not in run state) drop") \ +_(CNAT_V4_UDP_I2O_DD_PKT, "v4 udp i2o (no direct port) drop") \ +_(CNAT_V4_UDP_I2O_DA_PKT, "v4 udp i2o (no any port) drop") \ +_(CNAT_V4_UDP_I2O_DO_PKT, "v4 udp i2o (out of port limit) drop") \ +_(CNAT_V4_UDP_I2O_DI_PKT, "v4 udp i2o (invalid packet) drop") \ +_(CNAT_V4_UDP_I2O_DS_PKT, "v4 udp i2o (no sessoon db) drop") + +typedef enum { +#define _(sym,str) sym, + foreach_cnat_ipv4_udp_inside_input_exc_error +#undef _ + CNAT_IPV4_UDP_INSIDE_INPUT_EXCEPTIONS_N_ERROR, +} cnat_ipv4_udp_inside_input_exc_error_t; + + +static char * cnat_ipv4_udp_inside_input_exc_error_strings[] = { +#define _(sym,string) string, + foreach_cnat_ipv4_udp_inside_input_exc_error +#undef _ +}; + +typedef struct { + u32 cached_next_index; + /* $$$$ add data here */ + + /* convenience variables */ + vlib_main_t * vlib_main; + vnet_main_t * vnet_main; +} cnat_ipv4_udp_inside_input_exc_main_t; + +typedef enum { + CNAT_V4_UDP_I2O_T, + CNAT_V4_UDP_I2O_D, + CNAT_V4_ICMP_G_I2O_T = CNAT_V4_UDP_I2O_D, /* TOBE_PORTED */ + CNAT_V4_UDP_INSIDE_INPUT_EXC_N_NEXT, +} cnat_ipv4_udp_inside_input_exc_next_t; + +cnat_ipv4_udp_inside_input_exc_main_t cnat_ipv4_udp_inside_input_exc_main; +vlib_node_registration_t cnat_ipv4_udp_inside_input_exc_node; + +#define NSTAGES 2 + +/* + * Use the generic buffer metadata + first line of packet data prefetch + * stage function from . This is usually a Good Idea. + */ +#define stage0 generic_stage0 + +static inline u32 last_stage (vlib_main_t *vm, vlib_node_runtime_t *node, + u32 bi) +{ + vlib_buffer_t *b0 = vlib_get_buffer (vm, bi); + vlib_node_t *n = + vlib_get_node (vm, cnat_ipv4_udp_inside_input_exc_node.index); + u32 node_counter_base_index = n->error_heap_index; + vlib_error_main_t * em = &vm->error_main; + + cnat_gen_icmp_info info; + cnat_db_key_bucket_t ki; + spp_ctx_t *ctx __attribute__((unused)) + = (spp_ctx_t *) &vnet_buffer(b0)->vcgn_uii; + cnat_main_db_entry_t *db = NULL; + ipv4_header *ip = (ipv4_header *)vlib_buffer_get_current(b0); + u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; + udp_hdr_type_t *udp = (udp_hdr_type_t *)((u8*)ip + ipv4_hdr_len); + int disposition = CNAT_V4_UDP_I2O_T; + int counter = CNAT_V4_UDP_I2O_T_PKT; + + cnat_key_t dest_info; + + PLATFORM_CNAT_SET_RX_VRF(vnet_buffer(b0)->sw_if_index[VLIB_RX], + vnet_buffer(b0)->vcgn_uii.key.k.vrf, + CNAT_UDP) + + vnet_buffer(b0)->vcgn_uii.key.k.ipv4 = clib_net_to_host_u32(ip->src_addr); + + PLATFORM_CNAT_SET_RX_VRF(vnet_buffer(b0)->sw_if_index[VLIB_RX], + ki.k.k.vrf, CNAT_UDP) + + ki.k.k.ipv4 = clib_net_to_host_u32(ip->src_addr); + + + /* MUST REVISIT: commentting frag check. Unconditional destination port + * update. DONOT remove this #if 0 */ + ki.k.k.port = + clib_net_to_host_u16(udp->src_port); + dest_info.k.port = + clib_net_to_host_u16(udp->dest_port); +#if 0 + if(PREDICT_FALSE(ctx->ru.rx.frag)) { +#ifdef TOBE_PORTED + /* Must have routed through cnat_v4_frag_in2out node */ + u16 *feature_data_ports = (u16 *)&ctx->feature_data[2]; + ki.k.k.port = *feature_data_ports; + feature_data_ports++; + dest_info.k.port = *feature_data_ports; +#endif + } else { + ki.k.k.port = + clib_net_to_host_u16(udp->src_port); + dest_info.k.port = + clib_net_to_host_u16(udp->dest_port); + } +#endif /* if 0 */ + + dest_info.k.ipv4 = clib_net_to_host_u32(ip->dest_addr); + PLATFORM_CNAT_SET_RX_VRF(vnet_buffer(b0)->sw_if_index[VLIB_RX], + dest_info.k.vrf, CNAT_UDP) + + if (PREDICT_TRUE(ki.k.k.port)) { + if (ki.k.k.port & 0x1) { + db = cnat_get_main_db_entry_v2(&ki, PORT_S_ODD, PORT_TYPE_DYNAMIC, + &info, &dest_info); + } else { + db = cnat_get_main_db_entry_v2(&ki, PORT_S_EVEN, PORT_TYPE_DYNAMIC, + &info, &dest_info); + } + } else { + /* + * No UDP port value of 0 - drop it + */ + db = NULL; + info.error = CNAT_ERR_BAD_TCP_UDP_PORT; + } + + if (PREDICT_TRUE((u64)db)) { + + if (PLATFORM_HANDLE_TTL_DECREMENT) { + /* + * Decrement TTL and update IPv4 checksum + */ + ipv4_decr_ttl_n_calc_csum(ip); + } + + /* + * step 6 do nat before fwd pkt + */ + swap_ip_src_udp_port(ip, udp, db); + /* + * update db for this pkt + */ + CNAT_DB_UPDATE_IN2OUT_TIMER + + /* Check timeout db if there is config for this */ + (void) query_and_update_db_timeout((void *)db, MAIN_DB_TYPE); + +/* Temporarily keeping it commented */ + //PLATFORM_CNAT_SET_TX_VRF(vnet_buffer(b0)->sw_if_index[VLIB_TX], + // db->out2in_key.k.vrf) + in2out_forwarding_count++; + + } else { + switch (info.error) { + case (CNAT_NO_VRF_RUN): + em->counters[node_counter_base_index + CNAT_V4_UDP_I2O_DR_PKT] += 1; + break; + case (CNAT_OUT_LIMIT): + em->counters[node_counter_base_index + CNAT_V4_UDP_I2O_DO_PKT] += 1; + break; + case (CNAT_NO_PORT_ANY): + case (CNAT_NO_POOL_ANY): + case (CNAT_BAD_INUSE_ANY): + case (CNAT_NOT_FOUND_ANY): + em->counters[node_counter_base_index + CNAT_V4_UDP_I2O_DA_PKT] += 1; + break; + case (CNAT_INV_PORT_DIRECT): + case (CNAT_DEL_PORT_DIRECT): + case (CNAT_BAD_INUSE_DIRECT): + case (CNAT_NOT_FOUND_DIRECT): + em->counters[node_counter_base_index + CNAT_V4_UDP_I2O_DD_PKT] += 1; + break; + case (CNAT_ERR_BAD_TCP_UDP_PORT): + em->counters[node_counter_base_index + CNAT_V4_UDP_I2O_DI_PKT] += 1; + break; + case (CNAT_ERR_NO_SESSION_DB): + em->counters[node_counter_base_index + CNAT_V4_UDP_I2O_DS_PKT] += 1; + break; + default: + em->counters[node_counter_base_index + CNAT_V4_UDP_I2O_DC_PKT] += 1; + break; + } + /* + * send to icmp msg generate node + */ + if (info.gen_icmp_msg == CNAT_ICMP_MSG) { +#ifdef TOBE_PORTED + u32 *fd = (u32*)ctx->feature_data; + fd[0] = info.svi_addr; + fd[1] = CNAT_ICMP_DEST_UNREACHABLE; +#endif + disposition = CNAT_V4_ICMP_G_I2O_T; + counter = CNAT_V4_ICMP_G_I2O_T_PKT; + } else { + disposition = CNAT_V4_UDP_I2O_D; + counter = CNAT_V4_UDP_I2O_D_PKT; + } + DEBUG_I2O_DROP(CNAT_DEBUG_DROP_UDP) + } + + em->counters[node_counter_base_index + counter] += 1; + + return disposition; +} + + +#include + +static uword cnat_ipv4_udp_inside_input_exc_node_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + return dispatch_pipeline (vm, node, frame); +} + +VLIB_REGISTER_NODE (cnat_ipv4_udp_inside_input_exc_node) = { + .function = cnat_ipv4_udp_inside_input_exc_node_fn, + .name = "vcgn-v4-udp-i2o-e", + .vector_size = sizeof (u32), + .type = VLIB_NODE_TYPE_INTERNAL, + + .n_errors = ARRAY_LEN(cnat_ipv4_udp_inside_input_exc_error_strings), + .error_strings = cnat_ipv4_udp_inside_input_exc_error_strings, + + .n_next_nodes = CNAT_V4_UDP_INSIDE_INPUT_EXC_N_NEXT, + + /* edit / add dispositions here */ + .next_nodes = { + [CNAT_V4_UDP_I2O_T] = "ip4-input", + [CNAT_V4_UDP_I2O_D] = "error-drop", + }, +}; + + +clib_error_t *cnat_ipv4_udp_inside_input_exc_init (vlib_main_t *vm) +{ + cnat_ipv4_udp_inside_input_exc_main_t * mp = &cnat_ipv4_udp_inside_input_exc_main; + + mp->vlib_main = vm; + mp->vnet_main = vnet_get_main(); + + return 0; +} + +VLIB_INIT_FUNCTION (cnat_ipv4_udp_inside_input_exc_init); + diff --git a/plugins/vcgn-plugin/vcgn/cnat_ipv4_udp_outside_input.c b/plugins/vcgn-plugin/vcgn/cnat_ipv4_udp_outside_input.c new file mode 100644 index 00000000..5a24a111 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_ipv4_udp_outside_input.c @@ -0,0 +1,605 @@ + +/* + *--------------------------------------------------------------------------- + * cnat_ipv4_udp_outside_input_stages.c - cnat_ipv4_udp_outside_input node pipeline stage functions + * + * + * Copyright (c) 2008-2014 Cisco and/or its affiliates. + * 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 +#include +#include +#include + +#include "cnat_ipv4_udp.h" +#include "dslite_db.h" +#include "cnat_db.h" +#include "cnat_v4_functions.h" + +//#include +//#include +//#include "cnat_va_db.h" + +#define foreach_cnat_ipv4_udp_outside_input_error \ +_(CNAT_V4_UDP_O2I_T_PKT, "v4 udp o2i transmit") \ +_(CNAT_V4_DSLITE_ENCAP_CTR, "to dslite encap") \ +_(CNAT_V4_UDP_O2I_MISS_PKT, "v4 udp o2i db miss drop") \ +_(CNAT_V4_UDP_O2I_TTL_GEN, "v4 udp o2i TTL gen") \ +_(CNAT_V4_UDP_O2I_TTL_DROP, "v4 udp o2i TTL drop") \ +_(CNAT_V4_UDP_O2I_PTB_GEN, "v4 ptb gen") \ +_(CNAT_V4_UDP_O2I_PTB_DROP, "v4 ptb throttle drop") \ +_(CNAT_V4_UDP_O2I_SESSION_DROP, "v4 udp o2i session drop") \ +_(CNAT_V4_UDP_O2I_FILTER_DROP, "v4 udp o2i drop: end point filtering") \ +_(CNAT_V4_UDP_O2I_SUB_FRAG_NO_DB_DROP, "v4 udp o2i subsequent frag no DB drop") \ +_(CNAT_V4_UDP_O2I_1ST_FRAG_FILTER_DROP, "v4 udp i2o 1st frag filter drop") + +typedef enum { +#define _(sym,str) sym, + foreach_cnat_ipv4_udp_outside_input_error +#undef _ + CNAT_IPV4_UDP_OUTSIDE_INPUT_N_ERROR, +} cnat_ipv4_udp_outside_input_t; + +static char * cnat_ipv4_udp_outside_input_error_strings[] = { +#define _(sym,string) string, + foreach_cnat_ipv4_udp_outside_input_error +#undef _ +}; + +typedef struct { + u32 cached_next_index; + /* $$$$ add data here */ + + /* convenience variables */ + vlib_main_t * vlib_main; + vnet_main_t * vnet_main; +} cnat_ipv4_udp_outside_input_main_t; + +typedef enum { + //CNAT_V4_O2I_FIXME, + CNAT_V4_UDP_O2I_E, + CNAT_V4_UDP_O2I_T, + CNAT_V4_UDP_O2I_NEXT, +} cnat_ipv4_udp_outside_input_next_t; + +//#define CNAT_V4_DSLITE_ENCAP CNAT_V4_O2I_FIXME +//#define CNAT_V4_UDP_O2I_E CNAT_V4_O2I_FIXME + +cnat_ipv4_udp_outside_input_main_t cnat_ipv4_udp_outside_input_main; +vlib_node_registration_t cnat_ipv4_udp_outside_input_node; + +#define NSTAGES 6 + +/* + * Use the generic buffer metadata + first line of packet data prefetch + * stage function from . This is usually a Good Idea. + */ +#define stage0 generic_stage0 + + +#if 0 +typedef struct cnat_ipv4_udp_outside_input_pipeline_data_ { + //spp_node_main_vector_t *nmv; + dslite_common_pipeline_data_t common_data; + /* Add additional pipeline stage data here... */ + u32 bucket; +#ifdef DSLITE_DEF + u32 user_bucket; + dslite_v4_to_v6_udp_counter_t *udp_counter; + dslite_icmp_gen_counter_t *icmp_gen_counter; + +#endif + cnat_key_t ki; + udp_hdr_type_t *udp; + u8 frag_pkt; +} cnat_ipv4_udp_outside_input_pipeline_data_t; + +#endif + +#define CNAT_UDP_OUTSIDE_UPDATE_FLAG_TIMER(db,dslite_nat44_inst_id) \ + if (PREDICT_FALSE(!(db->flags & CNAT_DB_FLAG_UDP_ACTIVE))) { \ + db->flags |= CNAT_DB_FLAG_UDP_ACTIVE; \ + CNAT_DB_TIMEOUT_RST(db); \ + } else if (PREDICT_FALSE(db->flags & CNAT_DB_DSLITE_FLAG)) { \ + if (PREDICT_TRUE(dslite_table_db_ptr[dslite_nat44_inst_id].mapping_refresh_both_direction)) { \ + CNAT_DB_TIMEOUT_RST(db); \ + } \ + } else if (PREDICT_TRUE(mapping_refresh_both_direction)) { \ + CNAT_DB_TIMEOUT_RST(db); \ + } \ + +#if 0 +static cnat_ipv4_udp_outside_input_pipeline_data_t pctx_data[SPP_MAXDISPATCH]; +#define EXTRA_PIPELINE_ARGS_PROTO , cnat_ipv4_udp_outside_input_pipeline_data_t *pctx +#define EXTRA_PIPELINE_ARGS , pctx + +#endif + +/*inline u32 +is_static_dest_nat_enabled(u16 vrf) +{ + if(static_dest_vrf_map_array[vrf] == 1) { + return CNAT_SUCCESS; + } + return CNAT_NO_CONFIG; +}*/ + +static inline void __attribute__((unused)) +swap_ip_dst(ipv4_header *ip, cnat_main_db_entry_t *db, u16 vrf) +{ + + CNAT_UPDATE_L3_CHECKSUM_DECLARE + /* + * calculate checksum + */ + CNAT_UPDATE_L3_CHECKSUM(((u16)(db->out2in_key.k.ipv4)), + ((u16)(db->out2in_key.k.ipv4 >> 16)), + (clib_host_to_net_u16(ip->checksum)), + ((u16)(db->in2out_key.k.ipv4)), + ((u16)(db->in2out_key.k.ipv4 >> 16))) + //set ip header + ip->dest_addr = + clib_host_to_net_u32(db->in2out_key.k.ipv4); + ip->checksum = + clib_host_to_net_u16(new_l3_c); + +#if 0 + + if(is_static_dest_nat_enabled(vrf) == CNAT_SUCCESS) { + direction = 1; + if(cnat_static_dest_db_get_translation(ip->src_addr, &postmap_ip, vrf, direction) == CNAT_SUCCESS) { + old_ip = spp_net_to_host_byte_order_32(&(ip->src_addr)); + old_postmap_ip = spp_net_to_host_byte_order_32(&postmap_ip); + + CNAT_UPDATE_L3_CHECKSUM(((u16)(old_ip & 0xFFFF)), + ((u16)(old_ip >> 16)), + (spp_net_to_host_byte_order_16(&(ip->checksum))), + ((u16)(old_postmap_ip & 0xFFFF)), + ((u16)(old_postmap_ip >> 16))) + ip->checksum = + clib_host_to_net_u16(new_l3_c); + ip->src_addr = postmap_ip; + } + } +#endif +} + +inline void swap_ip_dst_udp_port(ipv4_header *ip, + udp_hdr_type_t *udp, + cnat_main_db_entry_t *db, u16 vrf) +{ + +#define UDP_PACKET_DEBUG 1 + +// Temporary debugs which will be suppressed later +#ifdef UDP_PACKET_DEBUG + if (PREDICT_FALSE(udp_outside_packet_dump_enable)) { + printf("\nOut2In UDP packet before translation"); + print_udp_pkt(ip); + } +#endif + +#if 0 + if(is_static_dest_nat_enabled(vrf) == CNAT_SUCCESS) { + direction = 1; + if(cnat_static_dest_db_get_translation(ip->src_addr, &postmap_ip, vrf, direction) == CNAT_SUCCESS) { + + CNAT_UPDATE_L3_L4_CHECKSUM_DECLARE + + old_ip = spp_net_to_host_byte_order_32(&(ip->src_addr)); + old_postmap_ip = spp_net_to_host_byte_order_32(&postmap_ip); + + CNAT_UPDATE_L3_L4_CHECKSUM(((u16)(old_ip & 0xFFFF)), + ((u16)(old_ip >> 16)), + (spp_net_to_host_byte_order_16(&(udp->src_port))), + (spp_net_to_host_byte_order_16(&(ip->checksum))), + (spp_net_to_host_byte_order_16(&(udp->udp_checksum))), + ((u16)(old_postmap_ip & 0xFFFF)), + ((u16)(old_postmap_ip >> 16)), + (spp_net_to_host_byte_order_16(&(udp->src_port)))) + + ip->checksum = + clib_host_to_net_u16(new_l3_c); + ip->src_addr = postmap_ip; + if (PREDICT_TRUE(udp->udp_checksum)) { + udp->udp_checksum = clib_host_to_net_u16(new_l4_c); + } + } + } +#endif + /* + * declare variable + */ + CNAT_UPDATE_L3_L4_CHECKSUM_DECLARE + /* + * calculate checksum + */ + CNAT_UPDATE_L3_L4_CHECKSUM(((u16)(db->out2in_key.k.ipv4)), + ((u16)(db->out2in_key.k.ipv4 >> 16)), + (db->out2in_key.k.port), + (clib_net_to_host_u16(ip->checksum)), + (clib_net_to_host_u16(udp->udp_checksum)), + ((u16)(db->in2out_key.k.ipv4)), + ((u16)(db->in2out_key.k.ipv4 >> 16)), + (db->in2out_key.k.port)) + + + + + //set ip header + ip->dest_addr = + clib_host_to_net_u32(db->in2out_key.k.ipv4); + ip->checksum = + clib_host_to_net_u16(new_l3_c); + + //set udp header + udp->dest_port = + clib_host_to_net_u16(db->in2out_key.k.port); + + /* + * No easy way to avoid this if check except by using + * complex logic - may not be worth it. + */ + if (PREDICT_TRUE(udp->udp_checksum)) { + udp->udp_checksum = clib_host_to_net_u16(new_l4_c); + } + + + +// Temporary debugs which will be suppressed later +#ifdef UDP_PACKET_DEBUG + if (PREDICT_FALSE(udp_outside_checksum_disable)) { + printf("\nOut2In UDP checksum 0x%x disabled by force", new_l4_c); + udp->udp_checksum = 0; + } + if (PREDICT_FALSE(udp_outside_packet_dump_enable)) { + printf("\nOut2In UDP packet after translation"); + print_udp_pkt(ip); + } +#endif +} + +static inline void +stage1(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) +{ + u64 a, b, c; + u32 bucket; + u8 *prefetch_target; + + vlib_buffer_t * b0 = vlib_get_buffer (vm, buffer_index); + ipv4_header *ip = vlib_buffer_get_current (b0); + u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; + udp_hdr_type_t *udp = (udp_hdr_type_t *)((u8*)ip + ipv4_hdr_len); + + u64 tmp = 0; + tmp = vnet_buffer(b0)->vcgn_uii.key.k.ipv4 = + clib_net_to_host_u32(ip->dest_addr); + vnet_buffer(b0)->vcgn_uii.key.k.port = + clib_net_to_host_u16 (udp->dest_port); + + tmp |= ((u64)vnet_buffer(b0)->vcgn_uii.key.k.port) << 32; + + PLATFORM_CNAT_SET_RX_VRF(vnet_buffer(b0)->sw_if_index[VLIB_RX], + vnet_buffer(b0)->vcgn_uii.key.k.vrf, + CNAT_UDP) + tmp |= ((u64)vnet_buffer(b0)->vcgn_uii.key.k.vrf) << 48; + + CNAT_V4_GET_HASH(tmp, bucket, CNAT_MAIN_HASH_MASK) + + prefetch_target = (u8 *)(&cnat_out2in_hash[bucket]); + vnet_buffer(b0)->vcgn_uii.bucket = bucket; + + /* Prefetch the hash bucket */ + CLIB_PREFETCH(prefetch_target, CLIB_CACHE_LINE_BYTES, LOAD); +} + +static inline void +stage2(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) +{ /* nothing */ } + +#define SPP_LOG2_CACHE_LINE_BYTES 6 +#define SPP_CACHE_LINE_BYTES (1 << SPP_LOG2_CACHE_LINE_BYTES) + +static inline void +stage3(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) +{ + vlib_buffer_t * b0 = vlib_get_buffer(vm, buffer_index); + uword prefetch_target0, prefetch_target1; + u32 bucket = vnet_buffer(b0)->vcgn_uii.bucket; + + /* read the hash bucket */ + u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket + = cnat_out2in_hash[bucket].next; + + if (PREDICT_TRUE(db_index != EMPTY)) { + /* + * Prefetch database keys. We save space by not cache-line + * aligning the DB entries. We don't want to waste LSU + * bandwidth prefetching stuff we won't need. + */ + prefetch_target0 = (uword)(cnat_main_db + db_index); + CLIB_PREFETCH((void*)prefetch_target0, CLIB_CACHE_LINE_BYTES, STORE); + /* Just beyond DB key #2 */ + prefetch_target1 = prefetch_target0 + + STRUCT_OFFSET_OF(cnat_main_db_entry_t, user_ports); + /* If the targets are in different lines, do the second prefetch */ + if (PREDICT_FALSE((prefetch_target0 & ~(SPP_CACHE_LINE_BYTES-1)) != + (prefetch_target1 & ~(SPP_CACHE_LINE_BYTES-1)))) { + CLIB_PREFETCH((void *)prefetch_target1, CLIB_CACHE_LINE_BYTES, STORE); + } + } +} + +static inline void +stage4(vlib_main_t * vm, vlib_node_runtime_t * node, u32 buffer_index) +{ + cnat_main_db_entry_t *db; + vlib_buffer_t * b0 = vlib_get_buffer(vm, buffer_index); + u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket; + + /* + * Note: if the search already failed (empty bucket), + * the answer is already in the pipeline context structure + */ + if (PREDICT_TRUE(db_index != EMPTY)) { + + /* + * Note: hash collisions suck. We can't easily prefetch around them. + * The first trip around the track will be fast. After that, maybe + * not so much... + */ + do { + db = cnat_main_db + db_index; + if (PREDICT_TRUE(db->out2in_key.key64 == + vnet_buffer(b0)->vcgn_uii.key.key64)) { + break; + } + db_index = db->out2in_hash.next; + } while (db_index != EMPTY); + + /* Stick the answer back into the pipeline context structure */ + vnet_buffer(b0)->vcgn_uii.bucket = db_index; + } +} + +#if 0 + +ALWAYS_INLINE( +static inline void +stage5(spp_ctx_t **ctxs, int index, spp_node_t *np, + u8 *disp_used EXTRA_PIPELINE_ARGS_PROTO)) +{ + spp_ctx_t *ctx = ctxs[index]; + u32 db_index = pctx[index].bucket; + /* for nat44, dslite_id will be 1 */ + u16 dslite_id = *(pctx[index].common_data.dslite_id_ptr); + + DSLITE_PREFETCH_COUNTER(pctx[index].udp_counter, + &dslite_all_counters[dslite_id].v46_udp_counters, + dslite_v4_to_v6_udp_counter_t, + v4_to_v6_udp_output_count, + "V4_TO_V6_UDP") + + DSLITE_PREFETCH_COUNTER(pctx[index].icmp_gen_counter, + &dslite_all_counters[dslite_id].dslite_icmp_gen_counters, + dslite_icmp_gen_counter_t, + v6_icmp_gen_count, + "V4_TO_V6_icmp") + +if (PREDICT_TRUE(db_index != EMPTY)) { + cnat_main_db_entry_t *db = cnat_main_db + db_index; + + u32 user_db_index = db->user_index; + DSLITE_PRINTF(1, "UDP o2i, db entry found %u %u %u\n", + db_index, user_db_index, + db->dslite_nat44_inst_id); + uword prefetch_target0 = (uword)(cnat_user_db + user_db_index); + SPP_PREFETCH(prefetch_target0, 0, LOAD); + pctx[index].user_bucket = user_db_index; + DSLITE_PRINTF(1, "UDP: Done with prefetch..\n"); +} else { + DSLITE_PRINTF(1, "UDP: Stage 5, db_index empty...\n"); +} +} + +#endif + + +static inline u32 last_stage (vlib_main_t *vm, vlib_node_runtime_t *node, + u32 bi) +{ + + vlib_buffer_t *b0 = vlib_get_buffer (vm, bi); + u32 db_index = vnet_buffer(b0)->vcgn_uii.bucket; + //spp_ctx_t *ctx = (spp_ctx_t *) &vnet_buffer(b0)->vcgn_uii; + int disposition = CNAT_V4_UDP_O2I_T; + int counter = CNAT_V4_UDP_O2I_T_PKT; + ipv4_header *ip = (ipv4_header *)vlib_buffer_get_current(b0); + u8 ipv4_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; + udp_hdr_type_t *udp = (udp_hdr_type_t *)((u8*)ip + ipv4_hdr_len); + vlib_node_t *n = vlib_get_node (vm, cnat_ipv4_udp_outside_input_node.index); + u32 node_counter_base_index = n->error_heap_index; + vlib_error_main_t * em = &vm->error_main; + cnat_session_entry_t *session_db = NULL; + cnat_main_db_entry_t *db = NULL; + cnat_key_t dest_info; + u16 dslite_nat44_inst_id __attribute__((unused)) = 0; + + dest_info.k.port = clib_net_to_host_u16(udp->src_port); + dest_info.k.ipv4 = clib_net_to_host_u32(ip->src_addr); + + if (PREDICT_TRUE(db_index != EMPTY)) { + /* TTL gen was disabled for nat44 earlier + * But since dslite has got integrated in this + * TTL gen is enabled + */ + + db = cnat_main_db + db_index; + if (PLATFORM_HANDLE_TTL_DECREMENT) { + /* + * Decrement TTL and update IPv4 checksum + */ + ipv4_decr_ttl_n_calc_csum(ip); + } + if(PREDICT_TRUE(!PLATFORM_DBL_SUPPORT)) { + + /* No DBL support, so just update the destn and proceed */ + db->dst_ipv4 = dest_info.k.ipv4; + db->dst_port = dest_info.k.port; + CNAT_UDP_OUTSIDE_UPDATE_FLAG_TIMER(db, 0) + goto update_pkt; + } + + + if(PREDICT_TRUE((db->dst_ipv4 == dest_info.k.ipv4) && + (db->dst_port == dest_info.k.port))) { + + CNAT_UDP_OUTSIDE_UPDATE_FLAG_TIMER(db, 0) + goto update_pkt; + } else { + /* The session entries belonging to this entry are checked to find + * if an entry exist whose destination IP and port match with the + * source IP and port of the packet being processed + */ + dest_info.k.vrf = db->in2out_key.k.vrf; + + if (PREDICT_FALSE(db->nsessions == 0)) { + /* Should be a static entry + * Note this session as the first session and log + */ + cnat_add_dest_n_log(db, &dest_info); + CNAT_UDP_OUTSIDE_UPDATE_FLAG_TIMER(db, 0) + + } else if(PREDICT_TRUE(db->nsessions == 1)) { + + /* Destn is not same as in main db. Multiple session + * scenario + */ + dest_info.k.vrf = db->in2out_key.k.vrf; + session_db = cnat_handle_1to2_session(db, &dest_info); + + if(PREDICT_FALSE(session_db == NULL)) { + disposition = CNAT_V4_UDP_O2I_E; + counter = CNAT_V4_UDP_O2I_SESSION_DROP; + goto drop_pkt; + } + + /* update session_db(cur packet) timer */ + CNAT_UDP_OUTSIDE_UPDATE_FLAG_TIMER(session_db, 0) + } else { + /* More 2 sessions exists */ + + dest_info.k.vrf = db->in2out_key.k.vrf; + + /* If session already exists, + * cnat_create_session_db_entry will return the existing db + * else create a new db + * If could not create, return NULL + */ + session_db = cnat_create_session_db_entry(&dest_info, + db, TRUE); + + if(PREDICT_FALSE(session_db != NULL)) { + /* session exists */ + CNAT_UDP_OUTSIDE_UPDATE_FLAG_TIMER(session_db, 0) + } else { + /* could not create session db - drop packet */ + disposition = CNAT_V4_UDP_O2I_E; + counter = CNAT_V4_UDP_O2I_SESSION_DROP; + goto drop_pkt; + } + } + } + +update_pkt: + + /* + * 1. update dest ipv4 addr and dest udp port + * 2. update ipv4 checksum and udp checksum + */ + //swap_ip_dst(ip, db, db->in2out_key.k.vrf); + swap_ip_dst_udp_port(ip, udp, db, db->in2out_key.k.vrf); + //DSLITE_PRINTF(1, "Done with swap_ip_dst_udp_port..\n"); + + db->out2in_pkts++; + + nat44_dslite_global_stats[0].out2in_forwarding_count++; + + /* #### Temporarily COMMENTED FOR IP ROUTE LOOKUP ISSUE #### */ + + //PLATFORM_CNAT_SET_TX_VRF(vnet_buffer(b0)->sw_if_index[VLIB_TX], + // db->in2out_key.k.vrf) + } else { + disposition = CNAT_V4_UDP_O2I_E; + counter = CNAT_V4_UDP_O2I_MISS_PKT; + /* for NAT44 dslite_id would be 1 */ + nat44_dslite_common_stats[0].no_translation_entry_drops ++; + } + +drop_pkt: + + em->counters[node_counter_base_index + counter] += 1; + return disposition; +} + +#include + +static uword cnat_ipv4_udp_outside_input_node_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + return dispatch_pipeline (vm, node, frame); +} + + +VLIB_REGISTER_NODE (cnat_ipv4_udp_outside_input_node) = { + .function = cnat_ipv4_udp_outside_input_node_fn, + .name = "vcgn-v4-udp-o2i", + .vector_size = sizeof (u32), + .type = VLIB_NODE_TYPE_INTERNAL, + + .n_errors = ARRAY_LEN(cnat_ipv4_udp_outside_input_error_strings), + .error_strings = cnat_ipv4_udp_outside_input_error_strings, + + .n_next_nodes = CNAT_V4_UDP_O2I_NEXT, + + /* edit / add dispositions here */ +#if 0 + .next_nodes = { + //[CNAT_V4_O2I_FIXME] = "error-drop", + //[CNAT_V4_UDP_O2I_E] = "vcgn-v4-udp-o2i-e", + [CNAT_V4_UDP_O2I_E] = "vcgn-v4-udp-o2i-e", + [CNAT_V4_UDP_O2I_T] = "ip4-input", + }, +#endif + .next_nodes = { + [CNAT_V4_UDP_O2I_E] = "error-drop", + [CNAT_V4_UDP_O2I_T] = "ip4-input", + }, + +}; + +clib_error_t *cnat_ipv4_udp_outside_input_init (vlib_main_t *vm) +{ + cnat_ipv4_udp_outside_input_main_t * mp = &cnat_ipv4_udp_outside_input_main; + + mp->vlib_main = vm; + mp->vnet_main = vnet_get_main(); + + return 0; +} + +VLIB_INIT_FUNCTION (cnat_ipv4_udp_outside_input_init); diff --git a/plugins/vcgn-plugin/vcgn/cnat_log_api.h b/plugins/vcgn-plugin/vcgn/cnat_log_api.h new file mode 100644 index 00000000..60cf6836 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_log_api.h @@ -0,0 +1,114 @@ +/* + *------------------------------------------------------------------ + * cnat_log_api.h + * Declraes the common APIs for logging (both syslog and NFV9) + * Copyright (c) 2013, 20122 Cisco and/or its affiliates. + * 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 __CNAT_LOG_API_H__ +#define __CNAT_LOG_API_H__ + +#include "cnat_logging.h" + +static inline void cnat_log_ds_lite_mapping_delete(cnat_main_db_entry_t *db, + dslite_table_entry_t *dslite_entry +#ifndef NO_BULK_LOGGING + , int bulk_alloc +#endif + ) +{ + return; +} + +static inline void cnat_log_ds_lite_mapping_create(cnat_main_db_entry_t *db, + dslite_table_entry_t *dslite_entry +#ifndef NO_BULK_LOGGING + , int bulk_alloc +#endif + ) +{ + return; +} + +static inline void cnat_log_ds_lite_port_limit_exceeded( + dslite_key_t * key, + dslite_table_entry_t *dslite_entry_ptr) +{ + return; + +} + +static inline void cnat_log_nat44_port_limit_exceeded( + cnat_key_t * key, + cnat_vrfmap_t *vrfmap) +{ + return; +} +static inline void cnat_log_nat44_mapping_create(cnat_main_db_entry_t *db, + cnat_vrfmap_t *vrfmap +#ifndef NO_BULK_LOGGING + , int bulk_alloc +#endif + ) +{ + return; +} + +static inline void cnat_log_nat44_mapping_delete(cnat_main_db_entry_t *db, + cnat_vrfmap_t *vrfmap +#ifndef NO_BULK_LOGGING + , int bulk_alloc +#endif + ) +{ + return; +} + +/* Session Logging API for nat44 */ +static inline void cnat_session_log_nat44_mapping_create ( + cnat_main_db_entry_t *db, + cnat_session_entry_t *sdb, + cnat_vrfmap_t *vrfmap ) +{ + return; +} + +static inline void cnat_session_log_nat44_mapping_delete ( + cnat_main_db_entry_t *db, + cnat_session_entry_t *sdb, + cnat_vrfmap_t *vrfmap ) +{ + return; +} + +/* Session Logging API for dslite */ +static inline void cnat_session_log_ds_lite_mapping_create ( + cnat_main_db_entry_t *db, + dslite_table_entry_t *dslite_entry, + cnat_session_entry_t *sdb ) +{ + return; +} + +static inline void cnat_session_log_ds_lite_mapping_delete ( + cnat_main_db_entry_t *db, + dslite_table_entry_t *dslite_entry, + cnat_session_entry_t *sdb ) +{ + return; +} + +#endif /* #ifndef __CNAT_LOG_API_H__ */ + diff --git a/plugins/vcgn-plugin/vcgn/cnat_log_common.h b/plugins/vcgn-plugin/vcgn/cnat_log_common.h new file mode 100644 index 00000000..52731bc0 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_log_common.h @@ -0,0 +1,79 @@ +/* + *------------------------------------------------------------------ + * cnat_log_common.h + * Contains macros and definitions that are common to both syslog and nfv9 + * Copyright (c) 2011-2012 Cisco and/or its affiliates. + * 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 __CNAT_LOG_COMMON_H__ +#define __CNAT_LOG_COMMON_H__ + +#include +#include +#include + +#include "cnat_db.h" +#include "nat64_db.h" +#include "spp_timers.h" +#include "spp_ctx.h" + +/* + * This corresponds to the length of the IMETRO SHIM Header for RODDICK + * For non-roddick cases, introduce an Ethernet header as well + */ +#if 0 + #if defined(TARGET_RODDICK) + #define CNAT_NFV9_SHIM_HDR_OFFSET 8 + #define CNAT_NFV9_L2_ENCAPS_OFFSET 0 + #else + #define CNAT_NFV9_SHIM_HDR_OFFSET 0 + #define CNAT_NFV9_L2_ENCAPS_OFFSET 16 + #endif +#endif + + #define CNAT_NFV9_IP_HDR_OFFSET 0 + + #define CNAT_NFV9_UDP_HDR_OFFSET \ + (CNAT_NFV9_IP_HDR_OFFSET + sizeof(ipv4_header)) + + #define CNAT_NFV9_HDR_OFFSET \ + (CNAT_NFV9_UDP_HDR_OFFSET + sizeof(udp_hdr_type_t)) + +u32 cnat_get_sys_up_time_in_ms(void); +u32 cnat_get_unix_time_in_seconds(void); +void cnat_dump_time_change_logs(void); +void cnat_handle_sys_time_change (time_t current_unix_time); +/* + * Maximum number of time log changes we maintain + */ + +#define MAX_TIME_CHANGE_LOGS (8) + +typedef struct { + /* + * A timer structure to periodically send NFv9 & syslog logging packets + * that have been waiting to be full for a long time. This will + * ensure add/delete events don't get delayed too much before they + * are sent to the collector. + */ + spp_timer_t log_timer; + + /* + * Whether we have initialized the NFv9 information + */ + u8 cnat_log_init_done; +} cnat_log_global_info_t; + +#endif /* __CNAT_LOG_COMMON_H__ */ diff --git a/plugins/vcgn-plugin/vcgn/cnat_logging.c b/plugins/vcgn-plugin/vcgn/cnat_logging.c new file mode 100644 index 00000000..50805d11 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_logging.c @@ -0,0 +1,3518 @@ +/* + *------------------------------------------------------------------ + * cnat_logging.c + * + * Copyright (c) 2009-2013 Cisco and/or its affiliates. + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "cnat_config.h" +#include "cnat_global.h" +#include "cnat_v4_functions.h" +#include "tcp_header_definitions.h" +#include "cnat_v4_ftp_alg.h" +#include "cnat_logging.h" +#include "platform_common.h" + +#define CNAT_NFV9_DEBUG_CODE 2 +#if CNAT_NFV9_DEBUG_CODE > 3 + +#define NFV9_COND if ((my_instance_number != 0) && (my_instance_number != 15)) + +#define NFV9_DEBUG_PRINTF1(a) NFV9_COND printf(a); +#define NFV9_DEBUG_PRINTF2(a, b) NFV9_COND printf(a, b); +#define NFV9_DEBUG_PRINTF3(a, b, c) NFV9_COND printf(a, b, c); +#define NFV9_DEBUG_PRINTF4(a, b, c, d) NFV9_COND printf(a, b, c, d); + +#else + +#define NFV9_DEBUG_PRINTF1(a) +#define NFV9_DEBUG_PRINTF2(a, b) +#define NFV9_DEBUG_PRINTF3(a, b, c) +#define NFV9_DEBUG_PRINTF4(a, b, c, d) + +#endif + +static void cnat_nfv9_insert_ingress_vrfid_name_record(cnat_nfv9_logging_info_t *nfv9_logging_info, u16 index); +void cnat_nfv9_ingress_vrfid_name_mapping_create( + cnat_nfv9_logging_info_t *nfv9_logging_info); + + +cnat_nfv9_global_info_t cnat_nfv9_global_info; + +cnat_nfv9_template_t cnat_nfv9_template_info; + +#define CNAT_NFV9_OPTION_TEMPLATE cnat_nfv9_template_info.cnat_nfv9_option_template + +u16 cnat_template_id[MAX_RECORDS] = + {0, CNAT_NFV9_ADD_TEMPLATE_ID, CNAT_NFV9_DEL_TEMPLATE_ID, + CNAT_NFV9_NAT64_ADD_BIB_TEMPLATE_ID,CNAT_NFV9_NAT64_DEL_BIB_TEMPLATE_ID, + CNAT_NFV9_NAT64_ADD_SESSION_TEMPLATE_ID, + CNAT_NFV9_NAT64_DEL_SESSION_TEMPLATE_ID, + CNAT_NFV9_DS_LITE_ADD_TEMPLATE_ID, + CNAT_NFV9_DS_LITE_DEL_TEMPLATE_ID +#ifndef NO_BULK_LOGGING + , CNAT_NFV9_NAT44_BULK_ADD_TEMPLATE_ID, + CNAT_NFV9_NAT44_BULK_DEL_TEMPLATE_ID, + CNAT_NFV9_DS_LITE_BULK_ADD_TEMPLATE_ID, + CNAT_NFV9_DS_LITE_BULK_DEL_TEMPLATE_ID +#endif /* #ifndef NO_BULK_LOGGING */ + , CNAT_NFV9_INGRESS_VRF_ID_NAME_TEMPLATE_ID, + CNAT_NFV9_NAT44_ADD_SESSION_TEMPLATE_ID, + CNAT_NFV9_NAT44_DEL_SESSION_TEMPLATE_ID, + CNAT_NFV9_DS_LITE_ADD_SESSION_TEMPLATE_ID, + CNAT_NFV9_DS_LITE_DEL_SESSION_TEMPLATE_ID + }; + +/* + * Logging information structures + */ +cnat_nfv9_logging_info_t cnat_default_nfv9_logging_info; +cnat_nfv9_logging_info_t *cnat_nfv9_logging_info_pool; +#define NFV9_SERVER_POOL_SIZE 16 +nfv9_server_info_t *nfv9_server_info_pool; + +u32 nfv9_src_id = 0; + +u32 +cnat_get_sys_up_time_in_ms (void) +{ + vlib_main_t * vm = vlib_get_main(); + u32 cnat_curr_time; + + cnat_curr_time = (u32)vlib_time_now (vm); + return cnat_curr_time; +} + +void +cnat_dump_time_change_logs (void) +{ + return; +} + +inline void cnat_nfv9_handle_sys_time_change(time_t current_unix_time) +{ + return; + #if 0 + cnat_handle_sys_time_change(current_unix_time); + #endif +} + +void cnat_nfv9_update_sys_time_change() +{ + cnat_nfv9_logging_info_t *my_nfv9_logging_info = NULL; + pool_foreach (my_nfv9_logging_info, cnat_nfv9_logging_info_pool, ({ + nfv9_server_info_t *server = nfv9_server_info_pool + + my_nfv9_logging_info->server_index; + server->last_template_sent_time = 0; + })); +} + +void nfv9_params_show(u32 logging_index) +{ + cnat_nfv9_logging_info_t *log_info; + if(logging_index == EMPTY) { + PLATFORM_DEBUG_PRINT("\nNetflow logging not configured\n"); + return; + } + + log_info = cnat_nfv9_logging_info_pool + logging_index; + nfv9_server_info_t *server __attribute__((unused)) + = nfv9_server_info_pool + log_info->server_index; + + + PLATFORM_DEBUG_PRINT("\nNetflow parameters --\n"); + PLATFORM_DEBUG_PRINT("Server index %d IPV4 address: %x, port %d, max log size %d\n", + log_info->server_index, server->ipv4_address, + server->port, log_info->max_length_minus_max_record_size); + + PLATFORM_DEBUG_PRINT("Server ref count %d Refresh rate %d timeout rate %d\n", + server->ref_count, server->refresh_rate, + server->timeout_rate); + +} + +/* + * Code to dump NFV9 packets before they are sent + */ +void +cnat_nfv9_dump_logging_context (u32 value1, + cnat_nfv9_logging_info_t *nfv9_logging_info, + u32 value2) +{ + u8 *pkt_ptr; + u32 i; + u32 next_nfv9_template_data_index = 0xffff; + u32 next_data_flow_index = 0xffff; + u32 next_data_record = 0xffff; + u32 data_record_size = 0; + vlib_main_t *vm = vlib_get_main(); + + nfv9_server_info_t *server = nfv9_server_info_pool + + nfv9_logging_info->server_index; + + vlib_cli_output(vm,"\nDumping %s packet at locn %d: time 0x%x", + (value2 == 1) ? "CURRENT" : "QUEUED", + value1, + cnat_nfv9_get_unix_time_in_seconds()); + + vlib_cli_output(vm, "\ni_vrf 0x%x, ip_address 0x%x, port %d", + nfv9_logging_info->i_vrf, + server->ipv4_address, + server->port); + + vlib_cli_output(vm,"\nseq_num %d", + server->sequence_num); + + vlib_cli_output(vm,"\nlast_template_sent time 0x%x, pkts_since_last_template %d", + server->last_template_sent_time, + server->pkts_since_last_template); + + vlib_cli_output(vm, "\npkt_len %d, add_rec_len %d, del_rec_len %d, total_rec_count %d", + nfv9_logging_info->pkt_length, + nfv9_logging_info->record_length[NAT44_ADD_RECORD], + nfv9_logging_info->record_length[NAT44_DEL_RECORD], + nfv9_logging_info->total_record_count); + + vlib_cli_output(vm,"\nbulk_add_rec_len %d, bulk_del_rec_len %d", + nfv9_logging_info->record_length[NAT44_BULK_ADD_RECORD], + nfv9_logging_info->record_length[NAT44_BULK_DEL_RECORD]); + + vlib_cli_output(vm,"\ncurr_logging_ctx 0x%p, timestamp 0x%x, queued_logging_ctx 0x%p", + nfv9_logging_info->current_logging_context, + nfv9_logging_info->current_logging_context_timestamp, + nfv9_logging_info->queued_logging_context); + + vlib_cli_output(vm,"\nnfv9_hdr 0x%p, tmpl_hdr 0x%p, dataflow_hdr 0x%p", + nfv9_logging_info->nfv9_header, + nfv9_logging_info->nfv9_template_header, + nfv9_logging_info->dataflow_header); + + vlib_cli_output(vm,"\nadd_rec 0x%p, del_rec 0x%p, next_data_ptr 0x%p", + nfv9_logging_info->record[NAT44_ADD_RECORD], + nfv9_logging_info->record[NAT44_DEL_RECORD], + nfv9_logging_info->next_data_ptr); + + vlib_cli_output(vm,"\n"); + + pkt_ptr = vlib_buffer_get_current(nfv9_logging_info->current_logging_context); + /* + * Dump along with 8 bytes of SHIM header + */ + for (i = 0; i < (nfv9_logging_info->pkt_length + CNAT_NFV9_IP_HDR_OFFSET); + i = i + 1) { + u8 c1, c2, c3; + if (i == CNAT_NFV9_IP_HDR_OFFSET) { + vlib_cli_output(vm,"\nIP_HEADER: \n"); + } else if (i == CNAT_NFV9_UDP_HDR_OFFSET) { + vlib_cli_output(vm,"\nUDP_HEADER: \n"); + } else if (i == CNAT_NFV9_HDR_OFFSET) { + vlib_cli_output(vm,"\nNFV9 Header: Version:Count: \n"); + } else if (i == (CNAT_NFV9_HDR_OFFSET+4)) { + vlib_cli_output(vm,"\nBoot_Up_Time_In_ms: \n"); + } else if (i == (CNAT_NFV9_HDR_OFFSET+8)) { + vlib_cli_output(vm, "\nUNIX_Time: \n"); + } else if (i == (CNAT_NFV9_HDR_OFFSET+12)) { + vlib_cli_output(vm,"\nSeq_Num: \n"); + } else if (i == (CNAT_NFV9_HDR_OFFSET+16)) { + vlib_cli_output(vm,"\nSource ID: \n"); + } else if (i == (CNAT_NFV9_HDR_OFFSET+20)) { + if (nfv9_logging_info->nfv9_template_header) { + vlib_cli_output(vm,"\nNFV9 TEMPLATE HDR: \n"); + next_nfv9_template_data_index = i + 4; + } else { + next_data_flow_index = i; + } + } else if (i == (CNAT_NFV9_TEMPLATE_OFFSET+CNAT_NFV9_TEMPLATE_LENGTH)) { + if (nfv9_logging_info->nfv9_template_header) { + next_data_flow_index = i; + } + } + + if (i == next_nfv9_template_data_index) { + vlib_cli_output(vm,"\nNFV9 TEMPLATE DATA: \n"); + } else if (i == next_data_flow_index) { + if (*(pkt_ptr + i) == 0x01) { + if (*(pkt_ptr + i + 1) == 0x00) { + data_record_size = 21; + next_data_record = i + 4; + next_data_flow_index = i + *(pkt_ptr + i + 3) + + *(pkt_ptr + i + 2)*0x100; + vlib_cli_output(vm,"\nADD_RECORD (total %d): next_data_flow_index (%d->%d)\n", (next_data_flow_index - i), i, next_data_flow_index); + } else if (*(pkt_ptr + i + 1) == 0x01) { + data_record_size = 11; + next_data_record = i + 4; + next_data_flow_index = i + *(pkt_ptr + i + 3) + + *(pkt_ptr + i + 2)*0x100; + vlib_cli_output(vm,"\nDEL_RECORD (total %d) : next_data_flow_index (%d->%d)\n", (next_data_flow_index - i), i, next_data_flow_index); + } else if (*(pkt_ptr + i + 1) == 0x09) { + data_record_size = 20; + next_data_record = i + 4; + next_data_flow_index = i + *(pkt_ptr + i + 3) + + *(pkt_ptr + i + 2)*0x100; + vlib_cli_output(vm,"\nBULK_ADD_RECORD (total %d) : next_data_flow_index (%d->%d)\n", (next_data_flow_index - i), i, next_data_flow_index); + } else if (*(pkt_ptr + i + 1) == 0x0a) { + data_record_size = 10; + next_data_record = i + 4; + next_data_flow_index = i + *(pkt_ptr + i + 3) + + *(pkt_ptr + i + 2)*0x100; + vlib_cli_output(vm,"\nBULK_DEL_RECORD (total %d) : next_data_flow_index (%d->%d)\n", (next_data_flow_index - i), i, next_data_flow_index); + } + + } + } else if (i == next_data_record) { + vlib_cli_output(vm,"\n"); + next_data_record += data_record_size; + } + + c3 = *(pkt_ptr + i); + + c2 = c3 & 0xf; + c1 = (c3 >> 4) & 0xf; + + + vlib_cli_output(vm,"%c%c ", + ((c1 <= 9) ? (c1 + '0') : (c1 - 10 + 'a')), + ((c2 <= 9) ? (c2 + '0') : (c2 - 10 + 'a'))); + + } + vlib_cli_output(vm,"\n"); +} + +/* + * edt: * * cnat_nfv9_pad_added_to_an_addr + * + * Returns the difference (no# of bytes) between new_addr + * & org_addr + * + * Argument: u8 *new_addr, u8 *org_addr + * returns the difference + */ + +static inline +int cnat_nfv9_pad_added_to_an_addr(u8 *new_addr, u8 *org_addr) +{ + uword addr1 = (uword) new_addr; + uword addr2 = (uword) org_addr; + return (addr1 - addr2); +} + +/* + * edt: * * cnat_nfv9_add_end_of_record_padding + * + * Tries to add padding to data_ptr to ensure it is word aligned + * + * Argument: u8 * data_ptr + * pointer to the data pointer + */ + +static inline +u8 *cnat_nfv9_add_end_of_record_padding (u8 *data_ptr) +{ + uword tmp = (uword) data_ptr; + uword pad_value = (uword) NFV9_PAD_VALUE; + + tmp = (tmp + pad_value) & (~pad_value); + + return ((u8 *) tmp); +} + +/* + * edt: * * cnat_nfv9_pad_end_of_record_length + * + * Tries to add padding to data_ptr to ensure it is word aligned + * + * Argument: u8 * data_ptr + * pointer to the data pointer + */ + +static inline +u16 cnat_nfv9_pad_end_of_record_length (u16 record_length) +{ + u16 pad_value = NFV9_PAD_VALUE; + + return ((record_length + pad_value) & (~pad_value)); +} + +/* get first interface address */ +static ip4_address_t * +ip4_interface_first_address (ip4_main_t * im, u32 sw_if_index) +{ + ip_lookup_main_t * lm = &im->lookup_main; + ip_interface_address_t * ia = 0; + ip4_address_t * result = 0; + + foreach_ip_interface_address (lm, ia, sw_if_index, + 1 /* honor unnumbered */, + ({ + ip4_address_t * a = ip_interface_address_get_address (lm, ia); + result = a; + break; + })); + return result; +} + +void fill_ip_n_udp_hdr (u32 ipv4_addr, u16 port, + cnat_nfv9_logging_info_t *nfv9_logging_info) +{ + vlib_buffer_t * b0 = nfv9_logging_info->current_logging_context; + ipv4_header *ip_header = vlib_buffer_get_current(b0); + udp_hdr_type_t *udp_header = (udp_hdr_type_t *)((u8*)ip_header + sizeof(ipv4_header)); + vlib_main_t *vm = vlib_get_main(); + u16 ip_length __attribute__((unused)); + u16 pkt_len = nfv9_logging_info->pkt_length; + ip4_address_t *ia0 = 0; + u16 src_port = 0x0a0a; + + /* + * Clear the SHIM header fields. The PD nodes will set it + * appropriately. + */ + PLATFORM_MEMSET_CNAT_LOG_PKT_DATA + + /* + * Don't need a special define for 0x45 - IP version and hdr len + */ + ip_header->version_hdr_len_words = 0x45; + ip_header->tos = 0; + ip_header->frag_flags_offset = 0; + ip_header->ttl = 0xff; + ip_header->protocol = UDP_PROT; + ip_header->dest_addr = clib_host_to_net_u32(ipv4_addr); + ip_length = vlib_buffer_length_in_chain (vm, b0); + ip_header->total_len_bytes = clib_host_to_net_u16(pkt_len); + ia0 = ip4_interface_first_address(&ip4_main, nfv9_logging_info->i_vrf_id); + ip_header->src_addr = ia0->as_u32; + udp_header->src_port = clib_host_to_net_u16(src_port); + udp_header->dest_port = clib_host_to_net_u16(port); + udp_header->udp_checksum = 0; + udp_header->udp_length = + clib_host_to_net_u16(pkt_len - sizeof(ipv4_header)); + ip_header->checksum = ip4_header_checksum((ip4_header_t *)ip_header); +} + +/* + * edt: * * cnat_nfv9_fill_nfv9_ip_header + * + * Tries to fill the fields of the IP header before it + * is sent to the L3 infra node. + * + * Argument: cnat_nfv9_logging_info_t *nfv9_logging_info + * structure that contains the packet context + */ + +static inline +void cnat_nfv9_fill_nfv9_ip_header (cnat_nfv9_logging_info_t *nfv9_logging_info) +{ + u16 new_record_length = 0; + u16 orig_record_length = 0; + vlib_buffer_t * b0 = nfv9_logging_info->current_logging_context; + + /* + * Fill in the IP header and port number of the Netflow collector + * The L3 Infra node will fill in the rest of the fields + */ + + nfv9_logging_info->nfv9_header->count = + clib_host_to_net_u16(nfv9_logging_info->total_record_count); + + /* + * Pad the last add/del record to ensure multiple of 4 bytes + */ + + if(nfv9_logging_info->last_record != RECORD_INVALID) { + + orig_record_length = + nfv9_logging_info->record_length[nfv9_logging_info->last_record]; + + new_record_length = cnat_nfv9_pad_end_of_record_length( + orig_record_length); + + nfv9_logging_info->dataflow_header->dataflow_length = + clib_host_to_net_u16(new_record_length); + } + + /* + * If the record is padded, ensure the padded bytes are ZERO + */ + if (PREDICT_TRUE(new_record_length - orig_record_length)) { + u8 *pkt_ptr = (u8 *) (b0 + nfv9_logging_info->pkt_length); + + /* + * Blindly copy 3 bytes of data to Zero to avoid for loops + * We have sufficient padding bytes for safety and we won't + * go over buffer limits + */ + *pkt_ptr++ = 0; + *pkt_ptr++ = 0; + *pkt_ptr++ = 0; + + nfv9_logging_info->pkt_length += + (new_record_length - orig_record_length); + } + nfv9_server_info_t *server = nfv9_server_info_pool + + nfv9_logging_info->server_index; + fill_ip_n_udp_hdr(server->ipv4_address, + server->port, nfv9_logging_info); + /* + * It is important to set the sw_if_index for the new buffer create + */ + vnet_buffer(b0)->sw_if_index[VLIB_TX] = (u32)~0; + +} + +/* + * edt: * * cnat_nfv9_send_queued_pkt + * + * Tries to send a logging pkt that has been queued earlier + * because it could not be sent due to downstream constipation + * + * Argument: cnat_nfv9_logging_info_t *nfv9_logging_info + * structure that contains the packet context + */ + +static inline +void cnat_nfv9_send_queued_pkt (cnat_nfv9_logging_info_t *nfv9_logging_info) +{ + return; +} + +/* + * edt: * * cnat_nfv9_send_pkt + * + * Tries to send a logging pkt. If the packet cannot be sent + * because of rewrite_output node cannot process it, queue + * it temporarily and try to send it later. + * + * Argument: cnat_nfv9_logging_info_t *nfv9_logging_info + * structure that contains the packet context + */ + +static inline +void cnat_nfv9_send_pkt (cnat_nfv9_logging_info_t *nfv9_logging_info) +{ + cnat_nfv9_fill_nfv9_ip_header(nfv9_logging_info); + + nfv9_server_info_t *server = nfv9_server_info_pool + + nfv9_logging_info->server_index; + + /* Update sequence number just before sending. + * So that, multiple NAT44/NAT64/DSLite instances sharing a + * a single server instance can stamp the sequence number + * in the right sequence (as seen by the server). + */ + server->sequence_num += 1; + nfv9_logging_info->nfv9_header->sequence_num = + clib_host_to_net_u32(server->sequence_num); + +#if DEBUG + cnat_nfv9_dump_logging_context (2, nfv9_logging_info, 1); +#endif +#if 0 /* commented out below */ + send_vpp3_nfv9_pkt(nfv9_logging_info); +#endif + nfv9_logging_info->current_logging_context = NULL; + /* + * Increase last packet sent count + */ + server->pkts_since_last_template++; + + /* + * If we are sending an nfv9 tempate with this packet + * log this timestamp + */ + if (nfv9_logging_info->nfv9_template_header) { + server->last_template_sent_time = + cnat_nfv9_get_unix_time_in_seconds(); + server->pkts_since_last_template = 0; + } + + return; +} + +/* + * send_vpp3_nfv9_pkt: to send multiple b0 in a frame + */ + +static inline +void send_vpp3_nfv9_pkt (cnat_nfv9_logging_info_t *nfv9_logging_info) +{ + vlib_node_t *output_node; + vlib_main_t *vm = vlib_get_main(); + vlib_frame_t *f; + vlib_buffer_t *b0; + u32 *to_next; + u32 bi=0; + ipv4_header *ip; + + //Lets check and send it to ip4-lookup node + output_node = vlib_get_node_by_name (vm, (u8 *) "ip4-lookup"); + f = vlib_get_frame_to_node (vm, output_node->index); + + if ( nfv9_logging_info->current_logging_context != NULL) { + /* Build a pkt from whole cloth */ + b0 = nfv9_logging_info->current_logging_context; + ip = vlib_buffer_get_current(b0); + to_next = vlib_frame_vector_args (f); + bi = vlib_get_buffer_index (vm, b0); + to_next[0] = bi; + + f->n_vectors = 1; + b0->current_length = clib_net_to_host_u16(ip->total_len_bytes); + vlib_put_frame_to_node (vm, output_node->index, f); + } + return; +} +/* + * edt: * * cnat_nfv9_send_pkt_always_success + * + * Tries to send a logging pkt. This cannot fail due to downstream + * constipation because we have already checked if the rewrite_output + * node can accept it. + * + * Argument: cnat_nfv9_logging_info_t *nfv9_logging_info + * structure that contains the packet context + * + * Argument: vlib_node_t *output_node + * vlib_node_t structure for rewrite_output node + */ + +static inline +void cnat_nfv9_send_pkt_always_success ( + cnat_nfv9_logging_info_t *nfv9_logging_info, + vlib_node_t *output_node) +{ + nfv9_server_info_t *server = nfv9_server_info_pool + + nfv9_logging_info->server_index; + vlib_main_t * vm = vlib_get_main(); + + /* + * At this point we either have a current or queued logging context + */ + if (PREDICT_TRUE(nfv9_logging_info->current_logging_context != NULL)) { + server->sequence_num += 1; + nfv9_logging_info->nfv9_header->sequence_num = + clib_host_to_net_u32(server->sequence_num); + cnat_nfv9_fill_nfv9_ip_header(nfv9_logging_info); + + nfv9_logging_info->current_logging_context->current_length = + nfv9_logging_info->pkt_length; + vlib_cli_output(vm, "\nNFV9: 3. Sending Current packet\n"); +#if DEBUG + cnat_nfv9_dump_logging_context (3, nfv9_logging_info, 1); +#endif + send_vpp3_nfv9_pkt(nfv9_logging_info); + nfv9_logging_info->current_logging_context = NULL; + } else { + /* + * For queued logging context, nfv9_header-> count is already set + */ + nfv9_logging_info->queued_logging_context->current_length = + nfv9_logging_info->pkt_length; + vlib_cli_output(vm,"\nNFV9: 4. Sending Queued packet\n"); +#if DEBUG + cnat_nfv9_dump_logging_context (4, nfv9_logging_info, 2); +#endif + send_vpp3_nfv9_pkt(nfv9_logging_info); + + nfv9_logging_info->queued_logging_context = NULL; + } + + /* + * NF Logging info already deleted, just free it and return + */ + if (PREDICT_FALSE(nfv9_logging_info->deleted)) { + pool_put(cnat_nfv9_logging_info_pool, nfv9_logging_info); + return; + } + + /* + * Increase last packet sent count and timestamp + */ + server->pkts_since_last_template++; + + /* + * If we are sending an nfv9 tempate with this packet + * log this timestamp + */ + if (nfv9_logging_info->nfv9_template_header) { + server->last_template_sent_time = + cnat_nfv9_get_unix_time_in_seconds(); + server->pkts_since_last_template = 0; + } +} + +/* + * edt: * * cnat_nfv9_create_logging_context + * + * Tries to create a logging context with packet buffer + * to send a new logging packet + * + * Argument: cnat_nfv9_logging_info_t *nfv9_logging_info + * structure that contains the nfv9 logging info and will store + * the packet context as well. + */ + +static inline +void cnat_nfv9_create_logging_context ( + cnat_nfv9_logging_info_t *nfv9_logging_info, + cnat_nfv9_template_add_flag_t template_flag) +{ + vlib_main_t *vm = vlib_get_main(); + vlib_buffer_t *b0; + static u32 bi; + u8 i; + + /* + * If queued_logging_context_index is non-EMPTY, we already have a logging + * packet queued to be sent. First try sending this before allocating + * a new context. We can have only one active packet context per + * nfv9_logging_info structure + */ + if (PREDICT_FALSE(nfv9_logging_info->queued_logging_context != NULL)) { + cnat_nfv9_send_queued_pkt(nfv9_logging_info); + /* + * If we cannot still send the queued pkt, just return + * Downstream Constipation count would have increased anyway + */ + if (nfv9_logging_info->queued_logging_context != NULL) { + cnat_global_counters.nfv9_logging_context_creation_deferred_count++; + return; + } + } + + + /* + * No context can be allocated, return silently + * calling routine will handle updating the error counters + */ + if (vlib_buffer_alloc (vm, &bi, 1) != 1) { + vlib_cli_output(vm, "buffer allocation failure"); + return; + } + /* Build a pkt from whole cloth */ + b0 = vlib_get_buffer (vm, bi); + b0->current_data = 0; + + nfv9_server_info_t *server = nfv9_server_info_pool + + nfv9_logging_info->server_index; + + nfv9_logging_info->current_logging_context = b0; + nfv9_logging_info->current_logging_context_timestamp = + cnat_nfv9_get_sys_up_time_in_ms(); + + + nfv9_logging_info->nfv9_header = + (nfv9_header_t *) (vlib_buffer_get_current(b0) + + (sizeof(ipv4_header)) + + (sizeof(udp_hdr_type_t))); + + nfv9_logging_info->nfv9_header->version = + clib_host_to_net_u16(CNAT_NFV9_VERSION_NUMBER); + + nfv9_logging_info->nfv9_header->sys_up_time = + clib_host_to_net_u32(cnat_nfv9_get_sys_up_time_in_ms()); + + nfv9_logging_info->nfv9_header->timestamp = + clib_host_to_net_u32(cnat_nfv9_get_unix_time_in_seconds()); + + + nfv9_logging_info->nfv9_header->source_id = + clib_host_to_net_u32(nfv9_src_id); + + nfv9_logging_info->dataflow_header = 0; + + for(i = 0; i < MAX_RECORDS;i++) { + nfv9_logging_info->record[i] = NULL; + nfv9_logging_info->record_length[i] = 0; + } + nfv9_logging_info->last_record = 0; + + + nfv9_logging_info->nfv9_template_header = 0; + nfv9_logging_info->next_data_ptr = + (u8 *) (vlib_buffer_get_current(b0) + + sizeof(ipv4_header) + sizeof(udp_hdr_type_t) + + sizeof(nfv9_header_t)); + + nfv9_logging_info->pkt_length = (CNAT_NFV9_TEMPLATE_OFFSET - + CNAT_NFV9_IP_HDR_OFFSET); + + + /* + * Now we have 0 records to start with + */ + + nfv9_logging_info->total_record_count = 0; + + if ((template_flag == cnat_nfv9_template_add_always) || + (server->pkts_since_last_template > + server->refresh_rate) || + ((cnat_nfv9_get_unix_time_in_seconds() - + server->last_template_sent_time) > + server->timeout_rate)) { + + /* + * Send a new template + */ + nfv9_logging_info->nfv9_template_header = + (cnat_nfv9_template_t *) nfv9_logging_info->next_data_ptr; + + clib_memcpy(nfv9_logging_info->nfv9_template_header, + &cnat_nfv9_template_info, + sizeof(cnat_nfv9_template_info)); + + /* + * Templates are sent irrespective of particular service-type config + */ + nfv9_logging_info->total_record_count = MAX_RECORDS - 1; + + nfv9_logging_info->pkt_length += CNAT_NFV9_TEMPLATE_LENGTH; + + /* + * Set the data pointer beyond the template field + */ + nfv9_logging_info->next_data_ptr = + (u8 *) (nfv9_logging_info->nfv9_template_header + 1); + /* + * Setting template_sent flag as TRUE. this will be checked in + * handle_vrfid_name_mapping() + */ + server->template_sent = TEMPLATE_SENT_TRUE; + } +} + +void cnat_nfv9_record_create ( + cnat_nfv9_logging_info_t *nfv9_logging_info, u16 cur_record) +{ + int byte_diff = 0; + u16 last_record = nfv9_logging_info->last_record; + + if(last_record != 0 && last_record != cur_record) { + u16 orig_length, new_length; + + orig_length = nfv9_logging_info->record_length[last_record]; + new_length = cnat_nfv9_pad_end_of_record_length(orig_length); + + /* + * The padding bytes are required after the last record + * Ensure length of last record accounts for padding bytes + */ + nfv9_logging_info->dataflow_header->dataflow_length = + clib_host_to_net_u16(new_length); + + /* + * Since we are working on the del record, set add record to 0 + */ + nfv9_logging_info->record[last_record] = 0; + + nfv9_logging_info->record_length[last_record] = 0; + + nfv9_logging_info->last_record = 0; + } + + nfv9_logging_info->last_record = cur_record; + + /* + * The padding bytes are required after the last record + * Ensure that we skip over the padding bytes + */ + nfv9_logging_info->dataflow_header = (nfv9_dataflow_record_header_t *) + cnat_nfv9_add_end_of_record_padding(nfv9_logging_info->next_data_ptr); + /* + * Get the difference + */ + byte_diff = cnat_nfv9_pad_added_to_an_addr( + (u8 *)nfv9_logging_info->dataflow_header, + nfv9_logging_info->next_data_ptr); + if(byte_diff > 0) { + /* + * Update the packet length to account for the pad bytes + */ + nfv9_logging_info->pkt_length += byte_diff; + u8 *pkt_ptr = nfv9_logging_info->next_data_ptr; + + /* + * Blindly copy 3 bytes of data to Zero to avoid for loops + * We have sufficient padding bytes for safety and we won't + * go over buffer limits + */ + *pkt_ptr++ = 0; + *pkt_ptr++ = 0; + *pkt_ptr++ = 0; + } + /* + * Initialize the template_id and the length of the add record + */ + nfv9_logging_info->dataflow_header->dataflow_template_id = + clib_host_to_net_u16(cnat_template_id[cur_record]); + + nfv9_logging_info->record[cur_record] = + (u8 *) (nfv9_logging_info->dataflow_header + 1); + + nfv9_logging_info->record_length[cur_record] = + CNAT_NFV9_DATAFLOW_RECORD_HEADER_LENGTH; + + /* + * Update the length of the total NFV9 record + */ + nfv9_logging_info->pkt_length += + CNAT_NFV9_DATAFLOW_RECORD_HEADER_LENGTH; + + /* + * Set the data pointer beyond the dataflow header field + */ + nfv9_logging_info->next_data_ptr = + (u8 *) (nfv9_logging_info->dataflow_header + 1); + +} + +static void cnat_nfv9_insert_add_record( + cnat_nfv9_logging_info_t *nfv9_logging_info, + cnat_main_db_entry_t *db, + cnat_vrfmap_t *vrfmap) +{ + u16 my_proto_mask; + u8 my_protocol; + nfv9_add_record_t nfv9_logging_add_record; + if (PREDICT_FALSE(nfv9_logging_info->record[NAT44_ADD_RECORD] == NULL)) { + cnat_nfv9_record_create(nfv9_logging_info, NAT44_ADD_RECORD); + } + + /* + * We should definitely have add_record now, no need to sanitize + */ + + nfv9_logging_add_record.inside_vrf_id = + clib_host_to_net_u32(vrfmap->i_vrf_id); + + nfv9_logging_add_record.outside_vrf_id = + clib_host_to_net_u32(vrfmap->o_vrf_id); + + nfv9_logging_add_record.inside_ip_addr = + clib_host_to_net_u32(db->in2out_key.k.ipv4); + nfv9_logging_add_record.outside_ip_addr = + clib_host_to_net_u32(db->out2in_key.k.ipv4); + + nfv9_logging_add_record.inside_ip_port = + clib_host_to_net_u16(db->in2out_key.k.port); + nfv9_logging_add_record.outside_ip_port = + clib_host_to_net_u16(db->out2in_key.k.port); + + my_proto_mask = db->in2out_key.k.vrf & CNAT_PRO_MASK; + my_protocol = ((my_proto_mask == CNAT_UDP) ? UDP_PROT : + ((my_proto_mask == CNAT_TCP) ? TCP_PROT : + ((my_proto_mask == CNAT_ICMP) ? ICMP_PROT : GRE_PROT))); + + nfv9_logging_add_record.protocol = my_protocol; + + clib_memcpy(nfv9_logging_info->record[NAT44_ADD_RECORD], + &nfv9_logging_add_record, CNAT_NFV9_ADD_RECORD_LENGTH); + + nfv9_logging_info->record_length[NAT44_ADD_RECORD] + += CNAT_NFV9_ADD_RECORD_LENGTH; + + nfv9_logging_info->pkt_length += CNAT_NFV9_ADD_RECORD_LENGTH; + + nfv9_logging_info->record[NAT44_ADD_RECORD] + += CNAT_NFV9_ADD_RECORD_LENGTH; + nfv9_logging_info->next_data_ptr = + nfv9_logging_info->record[NAT44_ADD_RECORD]; + + nfv9_logging_info->dataflow_header->dataflow_length = + clib_host_to_net_u32( + nfv9_logging_info->record_length[NAT44_ADD_RECORD]); + +} + + +static void cnat_nfv9_ds_lite_insert_add_record( + cnat_nfv9_logging_info_t *nfv9_logging_info, + cnat_main_db_entry_t *db, + dslite_table_entry_t *dslite_entry) +{ + + nfv9_ds_lite_add_record_t nfv9_logging_add_record = {0}; + cnat_user_db_entry_t *udb = NULL; + u16 my_proto_mask; + u8 my_protocol; + + udb = cnat_user_db + db->user_index; + if (PREDICT_FALSE(!udb)) { + return; + } + if (PREDICT_FALSE(nfv9_logging_info->record[DS_LITE_ADD_RECORD] == NULL)) { + cnat_nfv9_record_create(nfv9_logging_info, DS_LITE_ADD_RECORD); + } + /* + * We should definitely have add_record now, no need to sanitize + */ + nfv9_logging_add_record.inside_vrf_id = + clib_host_to_net_u32(dslite_entry->i_vrf_id); + nfv9_logging_add_record.outside_vrf_id = + clib_host_to_net_u32(dslite_entry->o_vrf_id); + +#ifdef DSLITE_USER_IPV4 + nfv9_logging_add_record.inside_ip_addr = + clib_host_to_net_u32(db->in2out_key.k.ipv4); +#else + /* + * Inside ipv4 address is sent as 0.0.0.0 for ds-lite case as + * ipv6 is user here. + */ + nfv9_logging_add_record.inside_ip_addr = 0; +#endif + + nfv9_logging_add_record.inside_v6_src_addr[0] = + clib_host_to_net_u32(udb->ipv6[0]); + nfv9_logging_add_record.inside_v6_src_addr[1] = + clib_host_to_net_u32(udb->ipv6[1]); + nfv9_logging_add_record.inside_v6_src_addr[2] = + clib_host_to_net_u32(udb->ipv6[2]); + nfv9_logging_add_record.inside_v6_src_addr[3] = + clib_host_to_net_u32(udb->ipv6[3]); + + nfv9_logging_add_record.outside_ip_addr = + clib_host_to_net_u32(db->out2in_key.k.ipv4); + + nfv9_logging_add_record.inside_ip_port = + clib_host_to_net_u16(db->in2out_key.k.port); + nfv9_logging_add_record.outside_ip_port = + clib_host_to_net_u16(db->out2in_key.k.port); + + my_proto_mask = db->in2out_key.k.vrf & CNAT_PRO_MASK; + + my_protocol = ((my_proto_mask == CNAT_UDP) ? UDP_PROT : + ((my_proto_mask == CNAT_TCP) ? TCP_PROT : + ((my_proto_mask == CNAT_ICMP) ? ICMP_PROT : 0))); + nfv9_logging_add_record.protocol = my_protocol; + + clib_memcpy(nfv9_logging_info->record[DS_LITE_ADD_RECORD], + &nfv9_logging_add_record, CNAT_NFV9_DS_LITE_ADD_RECORD_LENGTH); + + nfv9_logging_info->record_length[DS_LITE_ADD_RECORD] + += CNAT_NFV9_DS_LITE_ADD_RECORD_LENGTH; + + nfv9_logging_info->pkt_length += CNAT_NFV9_DS_LITE_ADD_RECORD_LENGTH; + nfv9_logging_info->total_record_count += 1; + + nfv9_logging_info->record[DS_LITE_ADD_RECORD] + += CNAT_NFV9_DS_LITE_ADD_RECORD_LENGTH; + nfv9_logging_info->next_data_ptr = + nfv9_logging_info->record[DS_LITE_ADD_RECORD]; + + nfv9_logging_info->dataflow_header->dataflow_length = + clib_host_to_net_u32( + nfv9_logging_info->record_length[DS_LITE_ADD_RECORD]); +} + + +static void cnat_nfv9_ds_lite_insert_del_record( + cnat_nfv9_logging_info_t *nfv9_logging_info, + cnat_main_db_entry_t *db, + dslite_table_entry_t *dslite_entry) +{ + + nfv9_ds_lite_del_record_t nfv9_logging_del_record = {0}; + cnat_user_db_entry_t *udb = NULL; + u16 my_proto_mask; + u8 my_protocol; + + udb = cnat_user_db + db->user_index; + if (PREDICT_FALSE(!udb)) { + return; + } + if (PREDICT_FALSE(nfv9_logging_info->record[DS_LITE_DEL_RECORD] == NULL)) { + cnat_nfv9_record_create(nfv9_logging_info, DS_LITE_DEL_RECORD); + } + /* + * We should definitely have a del record now. + * No need to sanitize + */ + nfv9_logging_del_record.inside_vrf_id = + clib_host_to_net_u32(dslite_entry->i_vrf_id); + +#ifdef DSLITE_USER_IPV4 + nfv9_logging_del_record.inside_ip_addr = + clib_host_to_net_u32(db->in2out_key.k.ipv4); +#else + /* + * Inside ipv4 address is sent as 0.0.0.0 for ds-lite case as + * ipv6 is user here. + */ + nfv9_logging_del_record.inside_ip_addr = 0; +#endif + + nfv9_logging_del_record.inside_v6_src_addr[0] = + clib_host_to_net_u32(udb->ipv6[0]); + nfv9_logging_del_record.inside_v6_src_addr[1] = + clib_host_to_net_u32(udb->ipv6[1]); + nfv9_logging_del_record.inside_v6_src_addr[2] = + clib_host_to_net_u32(udb->ipv6[2]); + nfv9_logging_del_record.inside_v6_src_addr[3] = + clib_host_to_net_u32(udb->ipv6[3]); + + nfv9_logging_del_record.inside_ip_port = + clib_host_to_net_u16(db->in2out_key.k.port); + + my_proto_mask = db->in2out_key.k.vrf & CNAT_PRO_MASK; + + my_protocol = ((my_proto_mask == CNAT_UDP) ? UDP_PROT : + ((my_proto_mask == CNAT_TCP) ? TCP_PROT : + ((my_proto_mask == CNAT_ICMP) ? ICMP_PROT : 0))); + nfv9_logging_del_record.protocol = my_protocol; + + clib_memcpy(nfv9_logging_info->record[DS_LITE_DEL_RECORD], + &nfv9_logging_del_record, CNAT_NFV9_DS_LITE_DEL_RECORD_LENGTH); + + nfv9_logging_info->record_length[DS_LITE_DEL_RECORD] += + CNAT_NFV9_DS_LITE_DEL_RECORD_LENGTH; + + nfv9_logging_info->pkt_length += CNAT_NFV9_DS_LITE_DEL_RECORD_LENGTH; + nfv9_logging_info->total_record_count += 1; + + nfv9_logging_info->record[DS_LITE_DEL_RECORD] + += CNAT_NFV9_DS_LITE_DEL_RECORD_LENGTH; + nfv9_logging_info->next_data_ptr = + nfv9_logging_info->record[DS_LITE_DEL_RECORD]; + + nfv9_logging_info->dataflow_header->dataflow_length = + clib_host_to_net_u32( + nfv9_logging_info->record_length[DS_LITE_DEL_RECORD]); +} + +#ifndef NO_BULK_LOGGING +static void cnat_nfv9_insert_bulk_add_record( + cnat_nfv9_logging_info_t *nfv9_logging_info, + cnat_main_db_entry_t *db, + cnat_vrfmap_t *vrfmap, + int bulk_alloc_start_port) +{ + nfv9_bulk_add_record_t nfv9_logging_bulk_add_record; + bulk_alloc_size_t bulk_size = BULKSIZE_FROM_VRFMAP(vrfmap); + if (PREDICT_FALSE(nfv9_logging_info->record[NAT44_BULK_ADD_RECORD] == NULL)) { + cnat_nfv9_record_create(nfv9_logging_info, NAT44_BULK_ADD_RECORD); + } + + /* + * We should definitely have add_record now, no need to sanitize + */ + + nfv9_logging_bulk_add_record.inside_vrf_id = + clib_host_to_net_u32(vrfmap->i_vrf_id); + nfv9_logging_bulk_add_record.outside_vrf_id = + clib_host_to_net_u32(vrfmap->o_vrf_id); + + nfv9_logging_bulk_add_record.inside_ip_addr = + clib_host_to_net_u32(db->in2out_key.k.ipv4); + nfv9_logging_bulk_add_record.outside_ip_addr = + clib_host_to_net_u32(db->out2in_key.k.ipv4); + + nfv9_logging_bulk_add_record.outside_ip_port_start = + clib_host_to_net_u16(bulk_alloc_start_port); + nfv9_logging_bulk_add_record.outside_ip_port_end = + clib_host_to_net_u16(bulk_alloc_start_port + bulk_size -1); + + clib_memcpy(nfv9_logging_info->record[NAT44_BULK_ADD_RECORD], + &nfv9_logging_bulk_add_record, CNAT_NFV9_BULK_ADD_RECORD_LENGTH); + + nfv9_logging_info->record_length[NAT44_BULK_ADD_RECORD] + += CNAT_NFV9_BULK_ADD_RECORD_LENGTH; + + nfv9_logging_info->pkt_length += CNAT_NFV9_BULK_ADD_RECORD_LENGTH; + + nfv9_logging_info->record[NAT44_BULK_ADD_RECORD] + += CNAT_NFV9_BULK_ADD_RECORD_LENGTH; + nfv9_logging_info->next_data_ptr = + nfv9_logging_info->record[NAT44_BULK_ADD_RECORD]; + + nfv9_logging_info->dataflow_header->dataflow_length = + clib_host_to_net_u32( + nfv9_logging_info->record_length[NAT44_BULK_ADD_RECORD]); + +} + + +static void cnat_nfv9_ds_lite_insert_bulk_add_record( + cnat_nfv9_logging_info_t *nfv9_logging_info, + cnat_main_db_entry_t *db, + dslite_table_entry_t *dslite_entry, + int bulk_alloc_start_port) +{ + + nfv9_ds_lite_bulk_add_record_t nfv9_logging_bulk_add_record = {0}; + cnat_user_db_entry_t *udb = NULL; + bulk_alloc_size_t bulk_size = BULKSIZE_FROM_VRFMAP(dslite_entry); + + if (PREDICT_FALSE(nfv9_logging_info->record[DS_LITE_BULK_ADD_RECORD] == NULL)) { + cnat_nfv9_record_create(nfv9_logging_info, DS_LITE_BULK_ADD_RECORD); + } + udb = cnat_user_db + db->user_index; + if (PREDICT_FALSE(!udb)) { + return; + } + /* + * We should definitely have add_record now, no need to sanitize + */ + + nfv9_logging_bulk_add_record.inside_vrf_id = + clib_host_to_net_u32(dslite_entry->i_vrf_id); + nfv9_logging_bulk_add_record.outside_vrf_id = + clib_host_to_net_u32(dslite_entry->o_vrf_id); + +#ifdef DSLITE_USER_IPV4 + nfv9_logging_bulk_add_record.inside_ip_addr = + clib_host_to_net_u32(db->in2out_key.k.ipv4); +#else + /* + * Inside ipv4 address is sent as 0.0.0.0 for ds-lite case as + * ipv6 is user here. + */ + nfv9_logging_bulk_add_record.inside_ip_addr = 0; +#endif + + nfv9_logging_bulk_add_record.inside_v6_src_addr[0] = + clib_host_to_net_u32(udb->ipv6[0]); + nfv9_logging_bulk_add_record.inside_v6_src_addr[1] = + clib_host_to_net_u32(udb->ipv6[1]); + nfv9_logging_bulk_add_record.inside_v6_src_addr[2] = + clib_host_to_net_u32(udb->ipv6[2]); + nfv9_logging_bulk_add_record.inside_v6_src_addr[3] = + clib_host_to_net_u32(udb->ipv6[3]); + + nfv9_logging_bulk_add_record.outside_ip_addr = + clib_host_to_net_u32(db->out2in_key.k.ipv4); + + nfv9_logging_bulk_add_record.outside_ip_port_start = + clib_host_to_net_u16(bulk_alloc_start_port); + nfv9_logging_bulk_add_record.outside_ip_port_end = + clib_host_to_net_u16(bulk_alloc_start_port + bulk_size -1); + + clib_memcpy(nfv9_logging_info->record[DS_LITE_BULK_ADD_RECORD], + &nfv9_logging_bulk_add_record, CNAT_NFV9_DS_LITE_BULK_ADD_RECORD_LENGTH); + + nfv9_logging_info->record_length[DS_LITE_BULK_ADD_RECORD] + += CNAT_NFV9_DS_LITE_BULK_ADD_RECORD_LENGTH; + + nfv9_logging_info->pkt_length += CNAT_NFV9_DS_LITE_BULK_ADD_RECORD_LENGTH; + nfv9_logging_info->total_record_count += 1; + nfv9_logging_info->record[DS_LITE_BULK_ADD_RECORD] + += CNAT_NFV9_DS_LITE_BULK_ADD_RECORD_LENGTH; + nfv9_logging_info->next_data_ptr = + nfv9_logging_info->record[DS_LITE_BULK_ADD_RECORD]; + nfv9_logging_info->dataflow_header->dataflow_length = + clib_host_to_net_u32( + nfv9_logging_info->record_length[DS_LITE_BULK_ADD_RECORD]); +} + + +static void cnat_nfv9_ds_lite_insert_bulk_del_record( + cnat_nfv9_logging_info_t *nfv9_logging_info, + cnat_main_db_entry_t *db, + dslite_table_entry_t *dslite_entry, + int bulk_alloc_start_port) +{ + + nfv9_ds_lite_bulk_del_record_t nfv9_logging_bulk_del_record = {0}; + cnat_user_db_entry_t *udb = NULL; + + if (PREDICT_FALSE(nfv9_logging_info->record[DS_LITE_BULK_DEL_RECORD] == NULL)) { + cnat_nfv9_record_create(nfv9_logging_info, DS_LITE_BULK_DEL_RECORD); + } + udb = cnat_user_db + db->user_index; + if (PREDICT_FALSE(!udb)) { + return; + } + /* + * We should definitely have add_record now, no need to sanitize + */ + + nfv9_logging_bulk_del_record.inside_vrf_id = + clib_host_to_net_u32(dslite_entry->i_vrf_id); + +#ifdef DSLITE_USER_IPV4 + nfv9_logging_bulk_del_record.inside_ip_addr = + clib_host_to_net_u32(db->in2out_key.k.ipv4); +#else + nfv9_logging_bulk_del_record.inside_ip_addr = + clib_host_to_net_u32(0); +#endif + + nfv9_logging_bulk_del_record.inside_v6_src_addr[0] = + clib_host_to_net_u32(udb->ipv6[0]); + nfv9_logging_bulk_del_record.inside_v6_src_addr[1] = + clib_host_to_net_u32(udb->ipv6[1]); + nfv9_logging_bulk_del_record.inside_v6_src_addr[2] = + clib_host_to_net_u32(udb->ipv6[2]); + nfv9_logging_bulk_del_record.inside_v6_src_addr[3] = + clib_host_to_net_u32(udb->ipv6[3]); + + nfv9_logging_bulk_del_record.outside_ip_port_start = + clib_host_to_net_u16(bulk_alloc_start_port); + + clib_memcpy(nfv9_logging_info->record[DS_LITE_BULK_DEL_RECORD], + &nfv9_logging_bulk_del_record, + CNAT_NFV9_DS_LITE_BULK_DEL_RECORD_LENGTH); + nfv9_logging_info->record_length[DS_LITE_BULK_DEL_RECORD] += + CNAT_NFV9_DS_LITE_BULK_DEL_RECORD_LENGTH; + nfv9_logging_info->pkt_length += + CNAT_NFV9_DS_LITE_BULK_DEL_RECORD_LENGTH; + nfv9_logging_info->total_record_count += 1; + nfv9_logging_info->record[DS_LITE_BULK_DEL_RECORD] += + CNAT_NFV9_DS_LITE_BULK_DEL_RECORD_LENGTH; + nfv9_logging_info->next_data_ptr = + nfv9_logging_info->record[DS_LITE_BULK_DEL_RECORD]; + nfv9_logging_info->dataflow_header->dataflow_length = + clib_host_to_net_u32( + nfv9_logging_info->record_length[DS_LITE_BULK_DEL_RECORD]); +} +#endif /* #ifndef NO_BULK_LOGGING */ + +static void cnat_nfv9_insert_del_record( + cnat_nfv9_logging_info_t *nfv9_logging_info, + cnat_main_db_entry_t *db, + cnat_vrfmap_t *vrfmap) +{ + u16 my_proto_mask; + u8 my_protocol; + nfv9_del_record_t nfv9_logging_del_record; + + if (PREDICT_FALSE(nfv9_logging_info->record[NAT44_DEL_RECORD] == NULL)) { + cnat_nfv9_record_create(nfv9_logging_info, NAT44_DEL_RECORD); + } + + /* + * We should definitely have add_record now, no need to sanitize + */ + + nfv9_logging_del_record.inside_vrf_id = + clib_host_to_net_u32(vrfmap->i_vrf_id); + + nfv9_logging_del_record.inside_ip_addr = + clib_host_to_net_u32(db->in2out_key.k.ipv4); + + nfv9_logging_del_record.inside_ip_port = + clib_host_to_net_u16(db->in2out_key.k.port); + + my_proto_mask = db->in2out_key.k.vrf & CNAT_PRO_MASK; + my_protocol = ((my_proto_mask == CNAT_UDP) ? UDP_PROT : + ((my_proto_mask == CNAT_TCP) ? TCP_PROT : + ((my_proto_mask == CNAT_ICMP) ? ICMP_PROT : GRE_PROT))); + + nfv9_logging_del_record.protocol = my_protocol; + + clib_memcpy(nfv9_logging_info->record[NAT44_DEL_RECORD], + &nfv9_logging_del_record, CNAT_NFV9_DEL_RECORD_LENGTH); + + nfv9_logging_info->record_length[NAT44_DEL_RECORD] + += CNAT_NFV9_DEL_RECORD_LENGTH; + + nfv9_logging_info->pkt_length += CNAT_NFV9_DEL_RECORD_LENGTH; + + nfv9_logging_info->record[NAT44_DEL_RECORD] + += CNAT_NFV9_DEL_RECORD_LENGTH; + nfv9_logging_info->next_data_ptr = + nfv9_logging_info->record[NAT44_DEL_RECORD]; + + nfv9_logging_info->dataflow_header->dataflow_length = + clib_host_to_net_u32( + nfv9_logging_info->record_length[NAT44_DEL_RECORD]); + +} + +#ifndef NO_BULK_LOGGING +static void cnat_nfv9_insert_bulk_del_record( + cnat_nfv9_logging_info_t *nfv9_logging_info, + cnat_main_db_entry_t *db, + cnat_vrfmap_t *vrfmap, + int bulk_alloc_start_port) +{ + nfv9_bulk_del_record_t nfv9_logging_bulk_del_record; + if (PREDICT_FALSE(nfv9_logging_info->record[NAT44_BULK_DEL_RECORD] == NULL)) { + cnat_nfv9_record_create(nfv9_logging_info, NAT44_BULK_DEL_RECORD); + } + + /* + * We should definitely have add_record now, no need to sanitize + */ + + nfv9_logging_bulk_del_record.inside_vrf_id = + clib_host_to_net_u32(vrfmap->i_vrf_id); + + nfv9_logging_bulk_del_record.inside_ip_addr = + clib_host_to_net_u32(db->in2out_key.k.ipv4); + + nfv9_logging_bulk_del_record.outside_ip_port_start = + clib_host_to_net_u16(bulk_alloc_start_port); + + clib_memcpy(nfv9_logging_info->record[NAT44_BULK_DEL_RECORD], + &nfv9_logging_bulk_del_record, CNAT_NFV9_BULK_DEL_RECORD_LENGTH); + + nfv9_logging_info->record_length[NAT44_BULK_DEL_RECORD] + += CNAT_NFV9_BULK_DEL_RECORD_LENGTH; + + nfv9_logging_info->pkt_length += CNAT_NFV9_BULK_DEL_RECORD_LENGTH; + + nfv9_logging_info->record[NAT44_BULK_DEL_RECORD] + += CNAT_NFV9_BULK_DEL_RECORD_LENGTH; + nfv9_logging_info->next_data_ptr = + nfv9_logging_info->record[NAT44_BULK_DEL_RECORD]; + + nfv9_logging_info->dataflow_header->dataflow_length = + clib_host_to_net_u32( + nfv9_logging_info->record_length[NAT44_BULK_DEL_RECORD]); + +} + +#endif /* #ifndef NO_BULK_LOGGING */ +/* + * edt: * * cnat_nfv9_log_mapping_create + * + * Tries to log a creation of mapping record + * + * Argument: cnat_main_db_entry_t *db + * Main DB entry being created + * + * Argument: cnat_vrfmap_t *vrfmap + * VRF Map for the Main DB entry being created + */ +void cnat_nfv9_log_mapping_create (cnat_main_db_entry_t *db, + cnat_vrfmap_t *vrfmap +#ifndef NO_BULK_LOGGING + , int bulk_alloc +#endif + ) +{ + cnat_nfv9_logging_info_t *nfv9_logging_info = 0; + vlib_main_t * vm = vlib_get_main(); + + if (PREDICT_FALSE(vrfmap->nfv9_logging_index == EMPTY)) { + + //vlib_cli_output(vm, "\n1. Log Mapping failed"); + /* + * No logging configured, silently return + */ + return; + } + + if (cnat_nfv9_logging_info_pool == NULL) { + vlib_cli_output(vm, "%s: info_pool pointer is NULL !!!!\n", __func__); + return; + } + nfv9_logging_info = + cnat_nfv9_logging_info_pool + vrfmap->nfv9_logging_index; + + if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { + cnat_nfv9_create_logging_context(nfv9_logging_info, + cnat_nfv9_template_add_default); + + /* + * If still empty, return after increasing the count + */ + if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { + //vlib_cli_output(vm, "\n2. Log Mapping failed"); + return; + } + + } + +#ifndef NO_BULK_LOGGING + if(bulk_alloc > 0) { /* new bulk alloc - use bulk add template */ + cnat_nfv9_insert_bulk_add_record(nfv9_logging_info, db, vrfmap, + bulk_alloc); + } else if(bulk_alloc == CACHE_ALLOC_NO_LOG_REQUIRED) + return; /* No logging required.. bulk port usage */ + else /* Individual logging .. fall back to old method */ +#endif + cnat_nfv9_insert_add_record(nfv9_logging_info, db, vrfmap); + + nfv9_logging_info->total_record_count += 1; + + /* + * If we have exceeded the packet length, let us send the + * packet now. There is buffer of additional bytes beyond + * max_pkt_length to ensure that the last add/delete record + * can be stored safely. + */ + if (PREDICT_FALSE(nfv9_logging_info->pkt_length > + nfv9_logging_info->max_length_minus_max_record_size)) { + cnat_nfv9_send_pkt(nfv9_logging_info); + } +} + +/* + * edt: * * cnat_nfv9_log_mapping_delete + * + * Tries to log a deletion of mapping record + * + * Argument: cnat_main_db_entry_t *db + * Main DB entry being deleted + * + * Argument: cnat_vrfmap_t *vrfmap + * VRF Map for the Main DB entry being deleted + */ +void cnat_nfv9_log_mapping_delete (cnat_main_db_entry_t * db, + cnat_vrfmap_t *vrfmap +#ifndef NO_BULK_LOGGING + , int bulk_alloc +#endif + ) +{ + cnat_nfv9_logging_info_t *nfv9_logging_info = 0; + + if (PREDICT_FALSE(vrfmap->nfv9_logging_index == EMPTY)) { + //vlib_cli_output(vm, "\n3. Log Mapping failed"); + /* + * No logging configured, silently return + */ + return; + } + + nfv9_logging_info = + cnat_nfv9_logging_info_pool + vrfmap->nfv9_logging_index; + + if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { + cnat_nfv9_create_logging_context(nfv9_logging_info, + cnat_nfv9_template_add_default); + + /* + * If still empty, return after increasing the count + */ + if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { + //vlib_cli_output(vm, "\n4. Log Mapping failed"); + return; + } + } +#ifndef NO_BULK_LOGGING + if(bulk_alloc > 0) { /* new bulk alloc - use bulk add template */ + cnat_nfv9_insert_bulk_del_record(nfv9_logging_info, db, vrfmap, + bulk_alloc); + } else if(bulk_alloc == CACHE_ALLOC_NO_LOG_REQUIRED) + return; /* No logging required.. bulk port usage */ + else /* Individual logging .. fall back to old method */ +#endif + cnat_nfv9_insert_del_record(nfv9_logging_info, db, vrfmap); + + nfv9_logging_info->total_record_count += 1; + + /* + * If we have exceeded the packet length, let us send the + * packet now. There is buffer of additional bytes beyond + * max_pkt_length to ensure that the last add/delete record + * can be stored safely. + */ + if (PREDICT_FALSE(nfv9_logging_info->pkt_length > + nfv9_logging_info->max_length_minus_max_record_size)) { + cnat_nfv9_send_pkt(nfv9_logging_info); + } +} + + +/* NAT64 Related routines */ + +/* + * edt: * * cnat_nfv9_bib_mapping_create + * + * Tries to log a creation of Bib mapping record + * + * Argument: nat64_bib_entry_t *db + * BIB DB entry being created + * + * Argument: nat64_table_entry_t *nat64_entry + * NAT64 Instance where this BIB belongs + */ +void cnat_nfv9_bib_mapping_create (nat64_bib_entry_t *db, + nat64_table_entry_t *nat64_entry) +{ + cnat_nfv9_logging_info_t *nfv9_logging_info = 0; + u16 my_proto_mask; + u8 my_protocol; + nfv9_nat64_add_bib_record_t nfv9_logging_add_record; + + if (PREDICT_FALSE(nat64_entry->logging_index == EMPTY)) { + /* + * No logging configured, silently return + */ + return; + } + + nfv9_logging_info = + cnat_nfv9_logging_info_pool + nat64_entry->logging_index; + + + if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { + cnat_nfv9_create_logging_context(nfv9_logging_info, + cnat_nfv9_template_add_default); + + /* + * If still empty, return after increasing the count + */ + if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { + return; + } + } + + if (PREDICT_FALSE(nfv9_logging_info->record[NAT64_ADD_BIB_RECORD] == NULL)){ + cnat_nfv9_record_create(nfv9_logging_info,NAT64_ADD_BIB_RECORD); + } + + + nfv9_logging_add_record.inside_v6_src_addr[0] = + clib_host_to_net_u32(db->v6_in_key.ipv6[0]); + nfv9_logging_add_record.inside_v6_src_addr[1] = + clib_host_to_net_u32(db->v6_in_key.ipv6[1]); + nfv9_logging_add_record.inside_v6_src_addr[2] = + clib_host_to_net_u32(db->v6_in_key.ipv6[2]); + nfv9_logging_add_record.inside_v6_src_addr[3] = + clib_host_to_net_u32(db->v6_in_key.ipv6[3]); + + + nfv9_logging_add_record.outside_v4_src_addr = + clib_host_to_net_u32(db->v4_out_key.k.ipv4); + + nfv9_logging_add_record.inside_src_port = + clib_host_to_net_u16(db->v6_in_key.port); + nfv9_logging_add_record.outside_src_port = + clib_host_to_net_u16(db->v4_out_key.k.port); + + my_proto_mask = db->v6_in_key.vrf & CNAT_PRO_MASK; + + my_protocol = ((my_proto_mask == CNAT_UDP) ? UDP_PROT : + ((my_proto_mask == CNAT_TCP) ? TCP_PROT : + ((my_proto_mask == CNAT_ICMP) ? IPV6_PROTO_ICMPV6 : 0))); + nfv9_logging_add_record.protocol = my_protocol; + + + clib_memcpy(nfv9_logging_info->record[NAT64_ADD_BIB_RECORD], + &nfv9_logging_add_record, CNAT_NFV9_NAT64_ADD_BIB_RECORD_LENGTH); + + nfv9_logging_info->record_length[NAT64_ADD_BIB_RECORD] += + CNAT_NFV9_NAT64_ADD_BIB_RECORD_LENGTH; + nfv9_logging_info->pkt_length += CNAT_NFV9_NAT64_ADD_BIB_RECORD_LENGTH; + nfv9_logging_info->total_record_count += 1; + + nfv9_logging_info->record[NAT64_ADD_BIB_RECORD] + += CNAT_NFV9_NAT64_ADD_BIB_RECORD_LENGTH; + + nfv9_logging_info->next_data_ptr = + nfv9_logging_info->record[NAT64_ADD_BIB_RECORD]; + + nfv9_logging_info->dataflow_header->dataflow_length = + clib_host_to_net_u32( + nfv9_logging_info->record_length[NAT64_ADD_BIB_RECORD]); + + /* + * If we have exceeded the packet length, let us send the + * packet now. There is buffer of additional bytes beyond + * max_pkt_length to ensure that the last add/delete record + * can be stored safely. + */ + if (PREDICT_FALSE(nfv9_logging_info->pkt_length > + nfv9_logging_info->max_length_minus_max_record_size)) { + cnat_nfv9_send_pkt(nfv9_logging_info); + } +} + + +/* + * edt: * * cnat_nfv9_session_mapping_create + * + * Tries to log a creation of Bib mapping record + * + * Argument: nat64_bib_entry_t *bdb + * BIB DB entry for the session that is created + * + * Argument: nat64_session_entry_t *sdb + * Session DB entry being created + * + * Argument: nat64_table_entry_t *nat64_entry + * NAT64 Instance where this BIB and Session belongs + */ +void cnat_nfv9_session_mapping_create (nat64_bib_entry_t *bdb, + nat64_session_entry_t *sdb, + nat64_table_entry_t *nat64_entry_ptr) +{ + cnat_nfv9_logging_info_t *nfv9_logging_info = 0; + u16 my_proto_mask; + u8 my_protocol; + u32 dest_v6[4]; + nfv9_nat64_add_session_record_t nfv9_logging_add_record; + u8 *ipv6_addr_ptr; + u8 *ipv4_addr_ptr; + + + if (PREDICT_FALSE(nat64_entry_ptr->logging_index == EMPTY)) { + /* + * No logging configured, silently return + */ + return; + } + + nfv9_logging_info = + cnat_nfv9_logging_info_pool + nat64_entry_ptr->logging_index; + + + if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { + cnat_nfv9_create_logging_context(nfv9_logging_info, + cnat_nfv9_template_add_default); + + /* + * If still empty, return after increasing the count + */ + if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)){ + return; + } + } + + if (PREDICT_FALSE(nfv9_logging_info->record[NAT64_ADD_SESSION_RECORD] + == NULL)){ + cnat_nfv9_record_create(nfv9_logging_info, NAT64_ADD_SESSION_RECORD); + } + + + nfv9_logging_add_record.inside_v6_src_addr[0] = + clib_host_to_net_u32(bdb->v6_in_key.ipv6[0]); + nfv9_logging_add_record.inside_v6_src_addr[1] = + clib_host_to_net_u32(bdb->v6_in_key.ipv6[1]); + nfv9_logging_add_record.inside_v6_src_addr[2] = + clib_host_to_net_u32(bdb->v6_in_key.ipv6[2]); + nfv9_logging_add_record.inside_v6_src_addr[3] = + clib_host_to_net_u32(bdb->v6_in_key.ipv6[3]); + + + nfv9_logging_add_record.outside_v4_src_addr = + clib_host_to_net_u32(bdb->v4_out_key.k.ipv4); + + + nfv9_logging_add_record.outside_v4_dest_addr = + clib_host_to_net_u32(sdb->v4_dest_key.k.ipv4); + + /* Need to create the V6 address using prefix */ + dest_v6[0] = nat64_entry_ptr->v6_prefix[0]; + dest_v6[1] = nat64_entry_ptr->v6_prefix[1]; + dest_v6[2] = nat64_entry_ptr->v6_prefix[2]; + dest_v6[3] = nat64_entry_ptr->v6_prefix[3]; + + ipv6_addr_ptr = (u8 *) (&(dest_v6[0])); + ipv4_addr_ptr = (u8 *) (&(sdb->v4_dest_key.k.ipv4)); + + *(ipv6_addr_ptr + nat64_entry_ptr->octet0_position) = *(ipv4_addr_ptr); + *(ipv6_addr_ptr + nat64_entry_ptr->octet1_position) = *(ipv4_addr_ptr + 1); + *(ipv6_addr_ptr + nat64_entry_ptr->octet2_position) = *(ipv4_addr_ptr + 2); + *(ipv6_addr_ptr + nat64_entry_ptr->octet3_position) = *(ipv4_addr_ptr + 3); + + nfv9_logging_add_record.inside_v6_dest_addr[0] = + clib_host_to_net_u32(dest_v6[0]); + nfv9_logging_add_record.inside_v6_dest_addr[1] = + clib_host_to_net_u32(dest_v6[1]); + nfv9_logging_add_record.inside_v6_dest_addr[2] = + clib_host_to_net_u32(dest_v6[2]); + nfv9_logging_add_record.inside_v6_dest_addr[3] = + clib_host_to_net_u32(dest_v6[3]); + + nfv9_logging_add_record.outside_v4_dest_addr = + clib_host_to_net_u32(sdb->v4_dest_key.k.ipv4); + + nfv9_logging_add_record.inside_src_port = + clib_host_to_net_u16(bdb->v6_in_key.port); + nfv9_logging_add_record.outside_src_port = + clib_host_to_net_u16(bdb->v4_out_key.k.port); + + nfv9_logging_add_record.dest_port = + clib_host_to_net_u16(sdb->v4_dest_key.k.port); + + + my_proto_mask = bdb->v6_in_key.vrf & CNAT_PRO_MASK; + + my_protocol = ((my_proto_mask == CNAT_UDP) ? UDP_PROT : + ((my_proto_mask == CNAT_TCP) ? TCP_PROT : + ((my_proto_mask == CNAT_ICMP) ? IPV6_PROTO_ICMPV6 : 0))); + nfv9_logging_add_record.protocol = my_protocol; + + + clib_memcpy(nfv9_logging_info->record[NAT64_ADD_SESSION_RECORD], + &nfv9_logging_add_record, CNAT_NFV9_NAT64_ADD_SESSION_RECORD_LENGTH); + + nfv9_logging_info->record_length[NAT64_ADD_SESSION_RECORD] += + CNAT_NFV9_NAT64_ADD_SESSION_RECORD_LENGTH; + nfv9_logging_info->pkt_length += CNAT_NFV9_NAT64_ADD_SESSION_RECORD_LENGTH; + nfv9_logging_info->total_record_count += 1; + + nfv9_logging_info->record[NAT64_ADD_SESSION_RECORD] + += CNAT_NFV9_NAT64_ADD_SESSION_RECORD_LENGTH; + + nfv9_logging_info->next_data_ptr = + nfv9_logging_info->record[NAT64_ADD_SESSION_RECORD]; + + nfv9_logging_info->dataflow_header->dataflow_length = + clib_host_to_net_u32( + nfv9_logging_info->record_length[NAT64_ADD_SESSION_RECORD]); + + /* + * If we have exceeded the packet length, let us send the + * packet now. There is buffer of additional bytes beyond + * max_pkt_length to ensure that the last add/delete record + * can be stored safely. + */ + if (PREDICT_FALSE(nfv9_logging_info->pkt_length > + nfv9_logging_info->max_length_minus_max_record_size)) { + cnat_nfv9_send_pkt(nfv9_logging_info); + } +} + + +/* + * edt: * * cnat_nfv9_bib_mapping_delete + * + * Tries to log a deletion of Bib mapping record + * + * Argument: nat64_bib_entry_t *db + * BIB DB entry being created + * + * Argument: nat64_table_entry_t *nat64_entry + * NAT64 Instance where this BIB belongs + */ +void cnat_nfv9_bib_mapping_delete (nat64_bib_entry_t *db, + nat64_table_entry_t *nat64_entry) +{ + cnat_nfv9_logging_info_t *nfv9_logging_info = 0; + u16 my_proto_mask; + u8 my_protocol; + nfv9_nat64_del_bib_record_t nfv9_logging_del_record; + if (PREDICT_FALSE(nat64_entry->logging_index == EMPTY)) { + /* + * No logging configured, silently return + */ + return; + } + + nfv9_logging_info = + cnat_nfv9_logging_info_pool + nat64_entry->logging_index; + + + if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { + cnat_nfv9_create_logging_context(nfv9_logging_info, + cnat_nfv9_template_add_default); + + /* + * If still empty, return after increasing the count + */ + if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)){ + return; + } + } + + if (PREDICT_FALSE(nfv9_logging_info->record[NAT64_DEL_BIB_RECORD] == NULL)){ + cnat_nfv9_record_create(nfv9_logging_info,NAT64_DEL_BIB_RECORD); + } + + + nfv9_logging_del_record.inside_v6_src_addr[0] = + clib_host_to_net_u32(db->v6_in_key.ipv6[0]); + nfv9_logging_del_record.inside_v6_src_addr[1] = + clib_host_to_net_u32(db->v6_in_key.ipv6[1]); + nfv9_logging_del_record.inside_v6_src_addr[2] = + clib_host_to_net_u32(db->v6_in_key.ipv6[2]); + nfv9_logging_del_record.inside_v6_src_addr[3] = + clib_host_to_net_u32(db->v6_in_key.ipv6[3]); + + + nfv9_logging_del_record.inside_src_port = + clib_host_to_net_u16(db->v6_in_key.port); + + my_proto_mask = db->v6_in_key.vrf & CNAT_PRO_MASK; + + my_protocol = ((my_proto_mask == CNAT_UDP) ? UDP_PROT : + ((my_proto_mask == CNAT_TCP) ? TCP_PROT : + ((my_proto_mask == CNAT_ICMP) ? IPV6_PROTO_ICMPV6 : 0))); + nfv9_logging_del_record.protocol = my_protocol; + + + clib_memcpy(nfv9_logging_info->record[NAT64_DEL_BIB_RECORD], + &nfv9_logging_del_record, CNAT_NFV9_NAT64_DEL_BIB_RECORD_LENGTH); + + nfv9_logging_info->record_length[NAT64_DEL_BIB_RECORD] += + CNAT_NFV9_NAT64_DEL_BIB_RECORD_LENGTH; + nfv9_logging_info->pkt_length += CNAT_NFV9_NAT64_DEL_BIB_RECORD_LENGTH; + nfv9_logging_info->total_record_count += 1; + + nfv9_logging_info->record[NAT64_DEL_BIB_RECORD] + += CNAT_NFV9_NAT64_DEL_BIB_RECORD_LENGTH; + + nfv9_logging_info->next_data_ptr = + nfv9_logging_info->record[NAT64_DEL_BIB_RECORD]; + + nfv9_logging_info->dataflow_header->dataflow_length = + clib_host_to_net_u32( + nfv9_logging_info->record_length[NAT64_DEL_BIB_RECORD]); + + /* + * If we have exceeded the packet length, let us send the + * packet now. There is buffer of additional bytes beyond + * max_pkt_length to ensure that the last add/delete record + * can be stored safely. + */ + if (PREDICT_FALSE(nfv9_logging_info->pkt_length > + nfv9_logging_info->max_length_minus_max_record_size)) { + cnat_nfv9_send_pkt(nfv9_logging_info); + } +} + + +/* + * edt: * * cnat_nfv9_session_mapping_delete + * + * Tries to log a deletion of Bib mapping record + * + * Argument: nat64_bib_entry_t *bdb + * BIB DB entry for the session that is created + * + * Argument: nat64_session_entry_t *sdb + * Session DB entry being created + * + * Argument: nat64_table_entry_t *nat64_entry + * NAT64 Instance where this BIB and Session belongs + */ +void cnat_nfv9_session_mapping_delete (nat64_bib_entry_t *bdb, + nat64_session_entry_t *sdb, + nat64_table_entry_t *nat64_entry_ptr) +{ + cnat_nfv9_logging_info_t *nfv9_logging_info = 0; + u16 my_proto_mask; + u8 my_protocol; + u32 dest_v6[4]; + nfv9_nat64_del_session_record_t nfv9_logging_del_record; + u8 *ipv6_addr_ptr; + u8 *ipv4_addr_ptr; + + if (PREDICT_FALSE(nat64_entry_ptr->logging_index == EMPTY)) { + /* + * No logging configured, silently return + */ + return; + } + + nfv9_logging_info = + cnat_nfv9_logging_info_pool + nat64_entry_ptr->logging_index; + + + if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { + cnat_nfv9_create_logging_context(nfv9_logging_info, + cnat_nfv9_template_add_default); + + /* + * If still empty, return after increasing the count + */ + if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)){ + return; + } + } + + if (PREDICT_FALSE(nfv9_logging_info->record[NAT64_DEL_SESSION_RECORD] + == NULL)){ + cnat_nfv9_record_create(nfv9_logging_info, NAT64_DEL_SESSION_RECORD); + } + + + nfv9_logging_del_record.inside_v6_src_addr[0] = + clib_host_to_net_u32(bdb->v6_in_key.ipv6[0]); + nfv9_logging_del_record.inside_v6_src_addr[1] = + clib_host_to_net_u32(bdb->v6_in_key.ipv6[1]); + nfv9_logging_del_record.inside_v6_src_addr[2] = + clib_host_to_net_u32(bdb->v6_in_key.ipv6[2]); + nfv9_logging_del_record.inside_v6_src_addr[3] = + clib_host_to_net_u32(bdb->v6_in_key.ipv6[3]); + + /* Need to create the V6 address using prefix */ + dest_v6[0] = nat64_entry_ptr->v6_prefix[0]; + dest_v6[1] = nat64_entry_ptr->v6_prefix[1]; + dest_v6[2] = nat64_entry_ptr->v6_prefix[2]; + dest_v6[3] = nat64_entry_ptr->v6_prefix[3]; + + ipv6_addr_ptr = (u8 *) (&(dest_v6[0])); + ipv4_addr_ptr = (u8 *) (&(sdb->v4_dest_key.k.ipv4)); + + *(ipv6_addr_ptr + nat64_entry_ptr->octet0_position) = *(ipv4_addr_ptr); + *(ipv6_addr_ptr + nat64_entry_ptr->octet1_position) = *(ipv4_addr_ptr + 1); + *(ipv6_addr_ptr + nat64_entry_ptr->octet2_position) = *(ipv4_addr_ptr + 2); + *(ipv6_addr_ptr + nat64_entry_ptr->octet3_position) = *(ipv4_addr_ptr + 3); + + nfv9_logging_del_record.inside_v6_dest_addr[0] = + clib_host_to_net_u32(dest_v6[0]); + nfv9_logging_del_record.inside_v6_dest_addr[1] = + clib_host_to_net_u32(dest_v6[1]); + nfv9_logging_del_record.inside_v6_dest_addr[2] = + clib_host_to_net_u32(dest_v6[2]); + nfv9_logging_del_record.inside_v6_dest_addr[3] = + clib_host_to_net_u32(dest_v6[3]); + + nfv9_logging_del_record.inside_src_port = + clib_host_to_net_u16(bdb->v6_in_key.port); + + nfv9_logging_del_record.dest_port = + clib_host_to_net_u16(sdb->v4_dest_key.k.port); + + + my_proto_mask = bdb->v6_in_key.vrf & CNAT_PRO_MASK; + + my_protocol = ((my_proto_mask == CNAT_UDP) ? UDP_PROT : + ((my_proto_mask == CNAT_TCP) ? TCP_PROT : + ((my_proto_mask == CNAT_ICMP) ? IPV6_PROTO_ICMPV6 : 0))); + nfv9_logging_del_record.protocol = my_protocol; + + clib_memcpy(nfv9_logging_info->record[NAT64_DEL_SESSION_RECORD], + &nfv9_logging_del_record, CNAT_NFV9_NAT64_DEL_SESSION_RECORD_LENGTH); + + nfv9_logging_info->record_length[NAT64_DEL_SESSION_RECORD] += + CNAT_NFV9_NAT64_DEL_SESSION_RECORD_LENGTH; + nfv9_logging_info->pkt_length += CNAT_NFV9_NAT64_DEL_SESSION_RECORD_LENGTH; + nfv9_logging_info->total_record_count += 1; + + nfv9_logging_info->record[NAT64_DEL_SESSION_RECORD] + += CNAT_NFV9_NAT64_DEL_SESSION_RECORD_LENGTH; + + nfv9_logging_info->next_data_ptr = + nfv9_logging_info->record[NAT64_DEL_SESSION_RECORD]; + + nfv9_logging_info->dataflow_header->dataflow_length = + clib_host_to_net_u32( + nfv9_logging_info->record_length[NAT64_DEL_SESSION_RECORD]); + + /* + * If we have exceeded the packet length, let us send the + * packet now. There is buffer of additional bytes beyond + * max_pkt_length to ensure that the last add/delete record + * can be stored safely. + */ + if (PREDICT_FALSE(nfv9_logging_info->pkt_length > + nfv9_logging_info->max_length_minus_max_record_size)) { + cnat_nfv9_send_pkt(nfv9_logging_info); + } +} + +/* + * edt: * * cnat_nfv9_nat44_log_session_create + * + * Tries to log a creation of mapping record (session based) + * + * Argument: cnat_main_db_entry_t *db + * Main DB entry being created + * Arugment: cnat_session_entry_t *sdb + * Session DB entry if the destination is not the first dest + * Argument: cnat_vrfmap_t *vrfmap + * VRF Map for the Main DB entry being created + */ + +void cnat_nfv9_nat44_log_session_create(cnat_main_db_entry_t *db, + cnat_session_entry_t *sdb, + cnat_vrfmap_t *vrfmap) +{ + cnat_nfv9_logging_info_t *nfv9_logging_info = 0; + u16 my_proto_mask; + u8 my_protocol; + nfv9_add_session_record_t nfv9_logging_add_session_record; + + if (PREDICT_FALSE(vrfmap->nfv9_logging_index == EMPTY)) { + //vlib_cli_output(vm,"\n1. Log Mapping failed"); + /* + * No logging configured, silently return + */ + return; + } + + nfv9_logging_info = + cnat_nfv9_logging_info_pool + vrfmap->nfv9_logging_index; + + if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { + cnat_nfv9_create_logging_context(nfv9_logging_info, + cnat_nfv9_template_add_default); + + /* + * If still empty, return after increasing the count + */ + if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { + //vlib_cli_output(vm,"\n2. Log Mapping failed"); + return; + } + } + + if(PREDICT_FALSE(nfv9_logging_info->record[ + NAT44_ADD_SESSION_RECORD] == NULL)) { + cnat_nfv9_record_create(nfv9_logging_info, NAT44_ADD_SESSION_RECORD); + } + + /* + * We should definitely have add_record now, no need to sanitize + */ + nfv9_logging_add_session_record.inside_vrf_id = + clib_host_to_net_u32(vrfmap->i_vrf_id); + nfv9_logging_add_session_record.outside_vrf_id = + clib_host_to_net_u32(vrfmap->o_vrf_id); + + nfv9_logging_add_session_record.inside_ip_addr = + clib_host_to_net_u32(db->in2out_key.k.ipv4); + nfv9_logging_add_session_record.outside_ip_addr = + clib_host_to_net_u32(db->out2in_key.k.ipv4); + + /* If sdb is null, it is assumed that logging is being done + * for the first destination which is held in the main db + + * itself + */ + if(PREDICT_TRUE(sdb == NULL)) { + nfv9_logging_add_session_record.dest_ip_addr = + clib_host_to_net_u32(db->dst_ipv4); + nfv9_logging_add_session_record.dest_port = + clib_host_to_net_u16(db->dst_port); + } else { + nfv9_logging_add_session_record.dest_ip_addr = + clib_host_to_net_u32(sdb->v4_dest_key.k.ipv4); + nfv9_logging_add_session_record.dest_port = + clib_host_to_net_u16(sdb->v4_dest_key.k.port); + } + + nfv9_logging_add_session_record.inside_ip_port = + clib_host_to_net_u16(db->in2out_key.k.port); + nfv9_logging_add_session_record.outside_ip_port = + clib_host_to_net_u16(db->out2in_key.k.port); + + + my_proto_mask = db->in2out_key.k.vrf & CNAT_PRO_MASK; + + my_protocol = ((my_proto_mask == CNAT_UDP) ? UDP_PROT : + ((my_proto_mask == CNAT_TCP) ? TCP_PROT : + ((my_proto_mask == CNAT_ICMP) ? ICMP_PROT : GRE_PROT))); + nfv9_logging_add_session_record.protocol = my_protocol; + + clib_memcpy(nfv9_logging_info->record[NAT44_ADD_SESSION_RECORD], + &nfv9_logging_add_session_record, + CNAT_NFV9_NAT44_ADD_SESSION_RECORD_LENGTH); + + nfv9_logging_info->record_length[NAT44_ADD_SESSION_RECORD] + += CNAT_NFV9_NAT44_ADD_SESSION_RECORD_LENGTH; + nfv9_logging_info->pkt_length += CNAT_NFV9_NAT44_ADD_SESSION_RECORD_LENGTH; + nfv9_logging_info->total_record_count += 1; + + + nfv9_logging_info->record[NAT44_ADD_SESSION_RECORD] + += CNAT_NFV9_NAT44_ADD_SESSION_RECORD_LENGTH; + + nfv9_logging_info->next_data_ptr = + nfv9_logging_info->record[NAT44_ADD_SESSION_RECORD]; + + nfv9_logging_info->dataflow_header->dataflow_length = + clib_host_to_net_u32( + nfv9_logging_info->record_length[NAT44_ADD_SESSION_RECORD]); + + /* + * If we have exceeded the packet length, let us send the + * packet now. There is buffer of additional bytes beyond + * max_pkt_length to ensure that the last add/delete record + * can be stored safely. + */ + if (PREDICT_FALSE(nfv9_logging_info->pkt_length > + nfv9_logging_info->max_length_minus_max_record_size)) { + cnat_nfv9_send_pkt(nfv9_logging_info); + } +} + +/* + * edt: * * cnat_nfv9_nat44_log_session_delete + * + * Tries to log a deletion of mapping record (session based) + * + * Argument: cnat_main_db_entry_t *db + * Main DB entry being created + * Arugment: cnat_session_entry_t *sdb + * Session DB entry if the destination is not the first dest + * Argument: cnat_vrfmap_t *vrfmap + * VRF Map for the Main DB entry being deleted + */ + +void cnat_nfv9_nat44_log_session_delete(cnat_main_db_entry_t *db, + cnat_session_entry_t *sdb, + cnat_vrfmap_t *vrfmap) +{ + cnat_nfv9_logging_info_t *nfv9_logging_info = 0; + u16 my_proto_mask; + u8 my_protocol; + nfv9_del_session_record_t nfv9_logging_del_session_record; + + if (PREDICT_FALSE(vrfmap->nfv9_logging_index == EMPTY)) { + //vlib_cli_output(vm, "\n1. Log Mapping failed"); + /* + * No logging configured, silently return + */ + return; + } + + nfv9_logging_info = + cnat_nfv9_logging_info_pool + vrfmap->nfv9_logging_index; + + if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { + cnat_nfv9_create_logging_context(nfv9_logging_info, + cnat_nfv9_template_add_default); + + /* + * If still empty, return after increasing the count + */ + if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { + //vlib_cli_output(vm, "\n2. Log Mapping failed"); + return; + } + } + + if(PREDICT_FALSE(nfv9_logging_info->record[ + NAT44_DEL_SESSION_RECORD] == NULL)) { + cnat_nfv9_record_create(nfv9_logging_info, NAT44_DEL_SESSION_RECORD); + } + + /* + * We should definitely have add_record now, no need to sanitize + */ + nfv9_logging_del_session_record.inside_vrf_id = + clib_host_to_net_u32(vrfmap->i_vrf_id); + + nfv9_logging_del_session_record.inside_ip_addr = + clib_host_to_net_u32(db->in2out_key.k.ipv4); + + /* If sdb is null, it is assumed that logging is being done + * for the first destination which is held in the main db + * itself + */ + if(PREDICT_TRUE(sdb == NULL)) { + nfv9_logging_del_session_record.dest_ip_addr = + clib_host_to_net_u32(db->dst_ipv4); + nfv9_logging_del_session_record.dest_port = + clib_host_to_net_u16(db->dst_port); + } else { + nfv9_logging_del_session_record.dest_ip_addr = + clib_host_to_net_u32(sdb->v4_dest_key.k.ipv4); + nfv9_logging_del_session_record.dest_port = + clib_host_to_net_u16(sdb->v4_dest_key.k.port); + } + + nfv9_logging_del_session_record.inside_ip_port = + clib_host_to_net_u16(db->in2out_key.k.port); + + my_proto_mask = db->in2out_key.k.vrf & CNAT_PRO_MASK; + my_protocol = ((my_proto_mask == CNAT_UDP) ? UDP_PROT : + ((my_proto_mask == CNAT_TCP) ? TCP_PROT : + ((my_proto_mask == CNAT_ICMP) ? ICMP_PROT : GRE_PROT))); + + nfv9_logging_del_session_record.protocol = my_protocol; + + clib_memcpy(nfv9_logging_info->record[NAT44_DEL_SESSION_RECORD], + &nfv9_logging_del_session_record, + CNAT_NFV9_NAT44_DEL_SESSION_RECORD_LENGTH); + + nfv9_logging_info->record_length[NAT44_DEL_SESSION_RECORD] + += CNAT_NFV9_NAT44_DEL_SESSION_RECORD_LENGTH; + nfv9_logging_info->pkt_length += CNAT_NFV9_NAT44_DEL_SESSION_RECORD_LENGTH; + nfv9_logging_info->total_record_count += 1; + + nfv9_logging_info->record[NAT44_DEL_SESSION_RECORD] + += CNAT_NFV9_NAT44_DEL_SESSION_RECORD_LENGTH; + + nfv9_logging_info->next_data_ptr = + nfv9_logging_info->record[NAT44_DEL_SESSION_RECORD]; + + nfv9_logging_info->dataflow_header->dataflow_length = + clib_host_to_net_u32( + nfv9_logging_info->record_length[NAT44_DEL_SESSION_RECORD]); + + /* + * If we have exceeded the packet length, let us send the + * packet now. There is buffer of additional bytes beyond + * max_pkt_length to ensure that the last add/delete record + * can be stored safely. + */ + if (PREDICT_FALSE(nfv9_logging_info->pkt_length > + nfv9_logging_info->max_length_minus_max_record_size)) { + cnat_nfv9_send_pkt(nfv9_logging_info); + } +} + +/* + * DS-Lite APIs for netflow logging + */ + +/* + * edt: * * cnat_nfv9_ds_lite_mapping_create + * + * Tries to log a creation of mapping record + * + * Argument: cnat_main_db_entry_t *db + * Main DB entry being created + * + * Argument: dslite_table_entry_t *dslite_entry + * ds-lite instance for the Main DB entry being created + */ +void cnat_nfv9_ds_lite_mapping_create(cnat_main_db_entry_t *db, + dslite_table_entry_t *dslite_entry +#ifndef NO_BULK_LOGGING + , int bulk_alloc +#endif + ) +{ + + cnat_nfv9_logging_info_t *nfv9_logging_info = NULL; + + if (PREDICT_FALSE(!(db && dslite_entry))) { + return; + } + if (PREDICT_FALSE(dslite_entry->nfv9_logging_index == EMPTY)) { + /* + * no logging configured, silently return + */ + return; + } + + nfv9_logging_info = + cnat_nfv9_logging_info_pool + dslite_entry->nfv9_logging_index; + if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { + cnat_nfv9_create_logging_context(nfv9_logging_info, + cnat_nfv9_template_add_default); + /* + * If still empty, return after increasing the count + */ + if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { + return; + } + } +#ifndef NO_BULK_LOGGING + if(bulk_alloc > 0) { /* new bulk alloc - use bulk add template */ + cnat_nfv9_ds_lite_insert_bulk_add_record(nfv9_logging_info, + db, dslite_entry, bulk_alloc); + } else if(bulk_alloc == CACHE_ALLOC_NO_LOG_REQUIRED) + return; /* No logging required.. bulk port usage */ + else /* Individual logging .. fall back to old method */ +#endif /*NO_BULK_LOGGING*/ + cnat_nfv9_ds_lite_insert_add_record(nfv9_logging_info, db, dslite_entry); + /* + * If we have exceeded the packet length, let us send the + * packet now. There is buffer of additional bytes beyond + * max_pkt_length to ensure that the last add/delete record + * can be stored safely. + */ + if (PREDICT_FALSE(nfv9_logging_info->pkt_length > + nfv9_logging_info->max_length_minus_max_record_size)) { + cnat_nfv9_send_pkt(nfv9_logging_info); + } +} + +/* + * edt: * * cnat_nfv9_ds_lite_mapping_delete + * + * Tries to log a deletion of mapping record + * + * Argument: cnat_main_db_entry_t *db + * Main DB entry being deleted + * + * Argument: dslite_table_entry_t *dslite_entry + * ds-lite instance for the Main DB entry being deleted + */ +void cnat_nfv9_ds_lite_mapping_delete(cnat_main_db_entry_t *db, + dslite_table_entry_t *dslite_entry +#ifndef NO_BULK_LOGGING + , int bulk_alloc +#endif + ) +{ + + cnat_nfv9_logging_info_t *nfv9_logging_info = NULL; + if (PREDICT_FALSE(!(db && dslite_entry))) { + return; + } + if (PREDICT_FALSE(dslite_entry->nfv9_logging_index == EMPTY)) { + /* + * No logging configured, silently return + */ + return; + } + nfv9_logging_info = + cnat_nfv9_logging_info_pool + dslite_entry->nfv9_logging_index; + + + if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { + cnat_nfv9_create_logging_context(nfv9_logging_info, + cnat_nfv9_template_add_default); + /* + * If still empty, return after increasing the count + */ + if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { + return; + } + } +#ifndef NO_BULK_LOGGING + if(bulk_alloc > 0) { /* new bulk alloc - use bulk add template */ + cnat_nfv9_ds_lite_insert_bulk_del_record(nfv9_logging_info, + db, dslite_entry, bulk_alloc); + } else if(bulk_alloc == CACHE_ALLOC_NO_LOG_REQUIRED) + return; /* No logging required.. bulk port usage */ + else /* Individual logging .. fall back to old method */ +#endif /*NO_BULK_LOGGING*/ + cnat_nfv9_ds_lite_insert_del_record(nfv9_logging_info, db, dslite_entry); + /* + * If we have exceeded the packet length, let us send the + * packet now. There is buffer of additional bytes beyond + * max_pkt_length to ensure that the last add/delete record + * can be stored safely. + */ + if (PREDICT_FALSE(nfv9_logging_info->pkt_length > + nfv9_logging_info->max_length_minus_max_record_size)) { + cnat_nfv9_send_pkt(nfv9_logging_info); + } +} + +/* + * edt: * * cnat_nfv9_dslite_log_session_create + * + * Tries to log a creation of mapping record (session based) + * Argument: cnat_main_db_entry_t *db + * Main DB entry being created + * Arugment: cnat_session_entry_t *sdb + * Session DB entry if the destination is not the first dest + * Argument: dslite_table_entry_t *dslite_entry, + * dslite table entry for dslite instance + */ + +void cnat_nfv9_ds_lite_log_session_create( + cnat_main_db_entry_t *db, + dslite_table_entry_t *dslite_entry, + cnat_session_entry_t *sdb) +{ + + nfv9_ds_lite_add_session_record_t nfv9_logging_add_record ; + cnat_user_db_entry_t *udb = NULL; + u16 my_proto_mask; + u8 my_protocol; + cnat_nfv9_logging_info_t *nfv9_logging_info = 0; + + if (PREDICT_FALSE(dslite_entry->nfv9_logging_index == EMPTY)) { + /* + * no logging configured, silently return + */ + return; + } + + nfv9_logging_info = + cnat_nfv9_logging_info_pool + dslite_entry->nfv9_logging_index; + udb = cnat_user_db + db->user_index; + + if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { + cnat_nfv9_create_logging_context(nfv9_logging_info, + cnat_nfv9_template_add_default); + + /* + * If still empty, return after increasing the count + */ + if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { + return; + } + } + + udb = cnat_user_db + db->user_index; + if (PREDICT_FALSE(!udb)) { + return; + } + if (PREDICT_FALSE(nfv9_logging_info->record[DS_LITE_ADD_SESSION_RECORD] == NULL)) { + cnat_nfv9_record_create(nfv9_logging_info, DS_LITE_ADD_SESSION_RECORD); + } + /* + * We should definitely have add_record now, no need to sanitize + */ + nfv9_logging_add_record.inside_vrf_id = + clib_host_to_net_u32(dslite_entry->i_vrf_id); + nfv9_logging_add_record.outside_vrf_id = + clib_host_to_net_u32(dslite_entry->o_vrf_id); + + nfv9_logging_add_record.inside_ip_addr = + clib_host_to_net_u32(db->in2out_key.k.ipv4); + + nfv9_logging_add_record.inside_v6_src_addr[0] = + clib_host_to_net_u32(udb->ipv6[0]); + nfv9_logging_add_record.inside_v6_src_addr[1] = + clib_host_to_net_u32(udb->ipv6[1]); + nfv9_logging_add_record.inside_v6_src_addr[2] = + clib_host_to_net_u32(udb->ipv6[2]); + nfv9_logging_add_record.inside_v6_src_addr[3] = + clib_host_to_net_u32(udb->ipv6[3]); + + nfv9_logging_add_record.outside_ip_addr = + clib_host_to_net_u32(db->out2in_key.k.ipv4); + + nfv9_logging_add_record.inside_ip_port = + clib_host_to_net_u16(db->in2out_key.k.port); + nfv9_logging_add_record.outside_ip_port = + clib_host_to_net_u16(db->out2in_key.k.port); + + /* If sdb is null, it is assumed that logging is being done + * for the first destination which is held in the main db + + * itself + */ + if(PREDICT_TRUE(sdb == NULL)) { + nfv9_logging_add_record.dest_ip_addr = + clib_host_to_net_u32(db->dst_ipv4); + nfv9_logging_add_record.dest_port = + clib_host_to_net_u16(db->dst_port); + } else { + nfv9_logging_add_record.dest_ip_addr = + clib_host_to_net_u32(sdb->v4_dest_key.k.ipv4); + nfv9_logging_add_record.dest_port = + clib_host_to_net_u16(sdb->v4_dest_key.k.port); + } + + + my_proto_mask = db->in2out_key.k.vrf & CNAT_PRO_MASK; + + my_protocol = ((my_proto_mask == CNAT_UDP) ? UDP_PROT : + ((my_proto_mask == CNAT_TCP) ? TCP_PROT : + ((my_proto_mask == CNAT_ICMP) ? ICMP_PROT : 0))); + nfv9_logging_add_record.protocol = my_protocol; + + clib_memcpy(nfv9_logging_info->record[DS_LITE_ADD_SESSION_RECORD], + &nfv9_logging_add_record, CNAT_NFV9_DS_LITE_ADD_SESSION_RECORD_LENGTH); + + nfv9_logging_info->record_length[DS_LITE_ADD_SESSION_RECORD] + += CNAT_NFV9_DS_LITE_ADD_SESSION_RECORD_LENGTH; + + nfv9_logging_info->pkt_length += CNAT_NFV9_DS_LITE_ADD_SESSION_RECORD_LENGTH; + nfv9_logging_info->total_record_count += 1; + + nfv9_logging_info->record[DS_LITE_ADD_SESSION_RECORD] + += CNAT_NFV9_DS_LITE_ADD_SESSION_RECORD_LENGTH; + nfv9_logging_info->next_data_ptr = + nfv9_logging_info->record[DS_LITE_ADD_SESSION_RECORD]; + + nfv9_logging_info->dataflow_header->dataflow_length = + clib_host_to_net_u32( + nfv9_logging_info->record_length[DS_LITE_ADD_SESSION_RECORD]); + + /* + * If we have exceeded the packet length, let us send the + * packet now. There is buffer of additional bytes beyond + * max_pkt_length to ensure that the last add/delete record + * can be stored safely. + */ + if (PREDICT_FALSE(nfv9_logging_info->pkt_length > + nfv9_logging_info->max_length_minus_max_record_size)) { + cnat_nfv9_send_pkt(nfv9_logging_info); + } + +} + +/* + * edt: * * cnat_nfv9_dslite_log_session_delete + * + * Tries to log a creation of mapping record (session based) + * Argument: cnat_main_db_entry_t *db + * Main DB entry being created + * Arugment: cnat_session_entry_t *sdb + * Session DB entry if the destination is not the first dest + * Argument: dslite_table_entry_t *dslite_entry, + * dslite table entry for dslite instance + */ + +void cnat_nfv9_ds_lite_log_session_delete( + cnat_main_db_entry_t *db, + dslite_table_entry_t *dslite_entry, + cnat_session_entry_t *sdb) +{ + + nfv9_ds_lite_del_session_record_t nfv9_logging_add_record = {0}; + cnat_user_db_entry_t *udb = NULL; + u16 my_proto_mask; + u8 my_protocol; + cnat_nfv9_logging_info_t *nfv9_logging_info = NULL; + + if (PREDICT_FALSE(dslite_entry->nfv9_logging_index == EMPTY)) { + /* + * no logging configured, silently return + */ + return; + } + + nfv9_logging_info = + cnat_nfv9_logging_info_pool + dslite_entry->nfv9_logging_index; + udb = cnat_user_db + db->user_index; + + if (PREDICT_FALSE(!udb)) { + return; + } + + if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { + cnat_nfv9_create_logging_context(nfv9_logging_info, + cnat_nfv9_template_add_default); + + /* + * If still empty, return after increasing the count + */ + if (PREDICT_FALSE(nfv9_logging_info->current_logging_context == NULL)) { + return; + } + } + + if (PREDICT_FALSE(nfv9_logging_info->record[DS_LITE_DEL_SESSION_RECORD] == NULL)) { + cnat_nfv9_record_create(nfv9_logging_info, DS_LITE_DEL_SESSION_RECORD); + } + /* + * We should definitely have add_record now, no need to sanitize + */ + nfv9_logging_add_record.inside_vrf_id = + clib_host_to_net_u32(dslite_entry->i_vrf_id); + + nfv9_logging_add_record.inside_ip_addr = + clib_host_to_net_u32(db->in2out_key.k.ipv4); + + nfv9_logging_add_record.inside_v6_src_addr[0] = + clib_host_to_net_u32(udb->ipv6[0]); + nfv9_logging_add_record.inside_v6_src_addr[1] = + clib_host_to_net_u32(udb->ipv6[1]); + nfv9_logging_add_record.inside_v6_src_addr[2] = + clib_host_to_net_u32(udb->ipv6[2]); + nfv9_logging_add_record.inside_v6_src_addr[3] = + clib_host_to_net_u32(udb->ipv6[3]); + + nfv9_logging_add_record.inside_ip_port = + clib_host_to_net_u16(db->in2out_key.k.port); + + /* If sdb is null, it is assumed that logging is being done + * for the first destination which is held in the main db + * itself + */ + if(PREDICT_TRUE(sdb == NULL)) { + nfv9_logging_add_record.dest_ip_addr = + clib_host_to_net_u32(db->dst_ipv4); + nfv9_logging_add_record.dest_port = + clib_host_to_net_u16(db->dst_port); + } else { + nfv9_logging_add_record.dest_ip_addr = + clib_host_to_net_u32(sdb->v4_dest_key.k.ipv4); + nfv9_logging_add_record.dest_port = + clib_host_to_net_u16(sdb->v4_dest_key.k.port); + } + + + my_proto_mask = db->in2out_key.k.vrf & CNAT_PRO_MASK; + + my_protocol = ((my_proto_mask == CNAT_UDP) ? UDP_PROT : + ((my_proto_mask == CNAT_TCP) ? TCP_PROT : + ((my_proto_mask == CNAT_ICMP) ? ICMP_PROT : 0))); + nfv9_logging_add_record.protocol = my_protocol; + + clib_memcpy(nfv9_logging_info->record[DS_LITE_DEL_SESSION_RECORD], + &nfv9_logging_add_record, CNAT_NFV9_DS_LITE_DEL_SESSION_RECORD_LENGTH); + + nfv9_logging_info->record_length[DS_LITE_DEL_SESSION_RECORD] + += CNAT_NFV9_DS_LITE_DEL_SESSION_RECORD_LENGTH; + + nfv9_logging_info->pkt_length += CNAT_NFV9_DS_LITE_DEL_SESSION_RECORD_LENGTH; + nfv9_logging_info->total_record_count += 1; + + nfv9_logging_info->record[DS_LITE_DEL_SESSION_RECORD] + += CNAT_NFV9_DS_LITE_DEL_SESSION_RECORD_LENGTH; + nfv9_logging_info->next_data_ptr = + nfv9_logging_info->record[DS_LITE_DEL_SESSION_RECORD]; + + nfv9_logging_info->dataflow_header->dataflow_length = + clib_host_to_net_u32( + nfv9_logging_info->record_length[DS_LITE_DEL_SESSION_RECORD]); + + /* + * If we have exceeded the packet length, let us send the + * packet now. There is buffer of additional bytes beyond + * max_pkt_length to ensure that the last add/delete record + * can be stored safely. + */ + if (PREDICT_FALSE(nfv9_logging_info->pkt_length > + nfv9_logging_info->max_length_minus_max_record_size)) { + cnat_nfv9_send_pkt(nfv9_logging_info); + } + +} + + +/* + * netflow logging API for ingress vrf_id to name mapping + */ + +/* + * edt: * * handle_vrfid_name_mapping + * It will search for valid natflow entry in netflow pool, + * once found one, will send all vrfid name mapping info + * using that entry + */ + + +static inline __attribute__((unused)) +void handle_vrfid_name_mapping(void) +{ + cnat_nfv9_logging_info_t *nfv9_logging_info = NULL; + + pool_foreach (nfv9_logging_info, cnat_nfv9_logging_info_pool, ({ + if(PREDICT_FALSE(nfv9_logging_info == NULL)) { + continue; + } + nfv9_server_info_t *server = nfv9_server_info_pool + + nfv9_logging_info->server_index; + if(server->template_sent == TEMPLATE_SENT_TRUE) { + cnat_nfv9_ingress_vrfid_name_mapping_create(nfv9_logging_info); + server->template_sent = TEMPLATE_SENT_FALSE; + } + })); +} + +/* + * edt: * * cnat_nfv9_ingress_vrfid_name_mapping_create + * + * Tries to log vrfid-name mapping record + * Argument: netflow pointer + */ + + +void cnat_nfv9_ingress_vrfid_name_mapping_create( + cnat_nfv9_logging_info_t *nfv9_logging_info) +{ + u16 index = 0; + + for (index = 0; index < MAX_VRFID; index++) { + if(vrfid_name_map[index].ref_count == 0) { + continue; + } + if (PREDICT_FALSE( + nfv9_logging_info->current_logging_context == NULL)) { + cnat_nfv9_create_logging_context(nfv9_logging_info, + cnat_nfv9_template_add_default); + } + cnat_nfv9_insert_ingress_vrfid_name_record( + nfv9_logging_info,index); + if (PREDICT_FALSE(nfv9_logging_info->pkt_length > + nfv9_logging_info->max_length_minus_max_record_size) || + PREDICT_FALSE(index == MAX_VRFID - 1)) { + if (PREDICT_TRUE(nfv9_logging_info->current_logging_context + != NULL)) { + cnat_nfv9_send_pkt(nfv9_logging_info); + } + } + }/*for()*/ + return; +} + +static void cnat_nfv9_insert_ingress_vrfid_name_record( + cnat_nfv9_logging_info_t *nfv9_logging_info, u16 index) +{ + nfv9_ingress_vrfid_name_record_t nfv9_ingress_vrfid_name_record = {0}; + + if (PREDICT_FALSE( + nfv9_logging_info->record[INGRESS_VRF_ID_NAME_RECORD] == NULL)) { + cnat_nfv9_record_create(nfv9_logging_info, INGRESS_VRF_ID_NAME_RECORD); + } + nfv9_ingress_vrfid_name_record.ingress_vrf_id = + clib_host_to_net_u32(vrfid_name_map[index].vrf_id); + + clib_memcpy(nfv9_ingress_vrfid_name_record.ingress_vrf_name, + vrfid_name_map[index].vrf_name, NFV9_VRF_NAME_LEN); + + clib_memcpy(nfv9_logging_info->record[INGRESS_VRF_ID_NAME_RECORD], + &nfv9_ingress_vrfid_name_record, + CNAT_NFV9_INGRESS_VRFID_NAME_RECORD_LENGTH); + + nfv9_logging_info->record_length[INGRESS_VRF_ID_NAME_RECORD] + += CNAT_NFV9_INGRESS_VRFID_NAME_RECORD_LENGTH; + + nfv9_logging_info->pkt_length += + CNAT_NFV9_INGRESS_VRFID_NAME_RECORD_LENGTH; + + nfv9_logging_info->total_record_count += 1; + + nfv9_logging_info->record[INGRESS_VRF_ID_NAME_RECORD] + += CNAT_NFV9_INGRESS_VRFID_NAME_RECORD_LENGTH; + + nfv9_logging_info->next_data_ptr = + nfv9_logging_info->record[INGRESS_VRF_ID_NAME_RECORD]; + + nfv9_logging_info->dataflow_header->dataflow_length = + clib_host_to_net_u32( + nfv9_logging_info->record_length[INGRESS_VRF_ID_NAME_RECORD]); + return; +} +/* + * edt: * * cnat_log_timer_handler + * + * Timer handler for sending any pending NFV9 record + * + * Argument: spp_timer_t * timer_p + * Timer handler structure + */ +void handle_pending_nfv9_pkts() +{ + vlib_node_t *output_node; + vlib_main_t * vm = vlib_get_main(); + cnat_nfv9_logging_info_t *my_nfv9_logging_info = 0; + u32 current_timestamp = cnat_nfv9_get_sys_up_time_in_ms(); + u32 current_unix_time_in_seconds = cnat_nfv9_get_unix_time_in_seconds(); + + output_node = vlib_get_node_by_name (vm, (u8 *) "ip4-lookup"); + + pool_foreach (my_nfv9_logging_info, cnat_nfv9_logging_info_pool, ({ + nfv9_server_info_t *server = nfv9_server_info_pool + + my_nfv9_logging_info->server_index; + if (my_nfv9_logging_info->queued_logging_context || + (my_nfv9_logging_info->current_logging_context && + (current_timestamp - + my_nfv9_logging_info->current_logging_context_timestamp) + > 1000)) { + /* + * If there is a current logging context and timestamp + * indicates it is pending for long, send it out + * Also if there is a queued context send it out as well + */ + vlib_cli_output(vm, "\nNFV9_TIMER: queued %p, curr %p", + my_nfv9_logging_info->queued_logging_context, + my_nfv9_logging_info->current_logging_context); + + + cnat_nfv9_send_pkt_always_success(my_nfv9_logging_info, + output_node); + } else { + /* + * If the last_template_sent_time is too far back in time + * send the template even if there is no NFv9 records to send + */ + if ((my_nfv9_logging_info->queued_logging_context == NULL) && + (my_nfv9_logging_info->current_logging_context == NULL) && + ((current_unix_time_in_seconds - + server->last_template_sent_time) > + server->timeout_rate)) { + cnat_nfv9_create_logging_context(my_nfv9_logging_info, + cnat_nfv9_template_add_always); + if (PREDICT_TRUE(my_nfv9_logging_info->current_logging_context + != NULL)) { + cnat_nfv9_send_pkt(my_nfv9_logging_info); + } + } + } + })); +} + +/* + * Code to initialize NFV9 Template. This is done when a NFV9 is enabled + * It is done only once and later used when sending NFV9 template records. + */ +static void +cnat_nfv9_template_init (void) +{ + cnat_nfv9_template_info.flowset_id = + clib_host_to_net_u16(CNAT_NFV9_TEMPLATE_FLOWSET_ID); + cnat_nfv9_template_info.length = + clib_host_to_net_u16(CNAT_NFV9_TEMPLATE_LENGTH - + CNAT_NFV9_OPTION_TEMPLATE_LENGTH); + /* + * Create the add Template + */ + cnat_nfv9_template_info.add_template_id = + clib_host_to_net_u16(CNAT_NFV9_ADD_TEMPLATE_ID); + cnat_nfv9_template_info.add_field_count = + clib_host_to_net_u16(CNAT_NFV9_ADD_FIELD_COUNT); + + cnat_nfv9_template_info.add_inside_vrf_id_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_TYPE); + cnat_nfv9_template_info.add_inside_vrf_id_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_SIZE); + + cnat_nfv9_template_info.add_outside_vrf_id_field_type = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_VRFID_FIELD_TYPE); + cnat_nfv9_template_info.add_outside_vrf_id_field_size = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_VRFID_FIELD_SIZE); + + cnat_nfv9_template_info.add_inside_ip_addr_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_TYPE); + cnat_nfv9_template_info.add_inside_ip_addr_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_SIZE); + + cnat_nfv9_template_info.add_outside_ip_addr_field_type = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_ADDR_FIELD_TYPE); + cnat_nfv9_template_info.add_outside_ip_addr_field_size = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_ADDR_FIELD_SIZE); + + cnat_nfv9_template_info.add_inside_ip_port_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_TYPE); + cnat_nfv9_template_info.add_inside_ip_port_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_SIZE); + + cnat_nfv9_template_info.add_outside_ip_port_field_type = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_FIELD_TYPE); + cnat_nfv9_template_info.add_outside_ip_port_field_size = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_FIELD_SIZE); + + cnat_nfv9_template_info.add_protocol_field_type = + clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_TYPE); + cnat_nfv9_template_info.add_protocol_field_size = + clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_SIZE); + + /* + * Create the delete Template + */ + cnat_nfv9_template_info.del_template_id = + clib_host_to_net_u16(CNAT_NFV9_DEL_TEMPLATE_ID); + cnat_nfv9_template_info.del_field_count = + clib_host_to_net_u16(CNAT_NFV9_DEL_FIELD_COUNT); + + cnat_nfv9_template_info.del_inside_vrf_id_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_TYPE); + cnat_nfv9_template_info.del_inside_vrf_id_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_SIZE); + + cnat_nfv9_template_info.del_inside_ip_addr_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_TYPE); + cnat_nfv9_template_info.del_inside_ip_addr_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_SIZE); + + cnat_nfv9_template_info.del_inside_ip_port_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_TYPE); + cnat_nfv9_template_info.del_inside_ip_port_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_SIZE); + + cnat_nfv9_template_info.del_protocol_field_type = + clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_TYPE); + cnat_nfv9_template_info.del_protocol_field_size = + clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_SIZE); + + + /* Create NAT64 BIB Add template */ +#if 0 + cnat_nfv9_template_info.nat64_add_bib_template_id = + clib_host_to_net_u16(CNAT_NFV9_NAT64_ADD_BIB_TEMPLATE_ID); + cnat_nfv9_template_info.nat64_add_bib_field_count = + clib_host_to_net_u16(CNAT_NFV9_NAT64_ADD_BIB_FIELD_COUNT); + + + cnat_nfv9_template_info.nat64_add_bib_inside_ipv6_addr_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_TYPE); + cnat_nfv9_template_info.nat64_add_bib_inside_ipv6_addr_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_SIZE); + + cnat_nfv9_template_info.nat64_add_bib_outside_ip_addr_field_type = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_ADDR_FIELD_TYPE); + cnat_nfv9_template_info.nat64_add_bib_outside_ip_addr_field_size = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_ADDR_FIELD_SIZE); + + cnat_nfv9_template_info.nat64_add_bib_inside_ip_port_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_TYPE); + cnat_nfv9_template_info.nat64_add_bib_inside_ip_port_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_SIZE); + + cnat_nfv9_template_info.nat64_add_bib_outside_ip_port_field_type = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_FIELD_TYPE); + cnat_nfv9_template_info.nat64_add_bib_outside_ip_port_field_size = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_FIELD_SIZE); + + cnat_nfv9_template_info.nat64_add_bib_protocol_field_type = + clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_TYPE); + cnat_nfv9_template_info.nat64_add_bib_protocol_field_size = + clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_SIZE); + + + /* NAT64 BIB Delete */ + cnat_nfv9_template_info.nat64_del_bib_template_id = + clib_host_to_net_u16(CNAT_NFV9_NAT64_DEL_BIB_TEMPLATE_ID); + cnat_nfv9_template_info.nat64_del_bib_field_count = + clib_host_to_net_u16(CNAT_NFV9_NAT64_DEL_BIB_FIELD_COUNT); + + cnat_nfv9_template_info.nat64_del_bib_inside_ip_addr_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_TYPE); + cnat_nfv9_template_info.nat64_del_bib_inside_ip_addr_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_SIZE); + + cnat_nfv9_template_info.nat64_del_bib_inside_ip_port_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_TYPE); + cnat_nfv9_template_info.nat64_del_bib_inside_ip_port_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_SIZE); + + cnat_nfv9_template_info.nat64_del_bib_protocol_field_type = + clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_TYPE); + cnat_nfv9_template_info.nat64_del_bib_protocol_field_size = + clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_SIZE); + + + /* NAt64 SESSION ADD */ + + cnat_nfv9_template_info.nat64_add_session_template_id = + clib_host_to_net_u16(CNAT_NFV9_NAT64_ADD_SESSION_TEMPLATE_ID); + cnat_nfv9_template_info.nat64_add_session_field_count = + clib_host_to_net_u16(CNAT_NFV9_NAT64_ADD_SESSION_FIELD_COUNT); + + + cnat_nfv9_template_info.nat64_add_session_inside_ipv6_src_addr_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_TYPE); + cnat_nfv9_template_info.nat64_add_session_inside_ipv6_src_addr_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_SIZE); + + cnat_nfv9_template_info.nat64_add_session_outside_ip_src_addr_field_type = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_ADDR_FIELD_TYPE); + cnat_nfv9_template_info.nat64_add_session_outside_ip_src_addr_field_size = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_ADDR_FIELD_SIZE); + + + cnat_nfv9_template_info.nat64_add_session_inside_ipv6_dst_addr_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_DST_ADDR_FIELD_TYPE); + cnat_nfv9_template_info.nat64_add_session_inside_ipv6_dst_addr_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_DST_ADDR_FIELD_SIZE); + + + cnat_nfv9_template_info.nat64_add_session_outside_ip_dst_addr_field_type = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_DST_ADDR_FIELD_TYPE); + cnat_nfv9_template_info.nat64_add_session_outside_ip_dst_addr_field_size = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_DST_ADDR_FIELD_SIZE); + + cnat_nfv9_template_info.nat64_add_session_inside_ip_src_port_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_TYPE); + cnat_nfv9_template_info.nat64_add_session_inside_ip_src_port_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_SIZE); + + + cnat_nfv9_template_info.nat64_add_session_outside_ip_src_port_field_type = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_FIELD_TYPE); + cnat_nfv9_template_info.nat64_add_session_outside_ip_src_port_field_size = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_FIELD_SIZE); + + + cnat_nfv9_template_info.nat64_add_session_ip_dest_port_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_DST_PORT_FIELD_TYPE); + cnat_nfv9_template_info.nat64_add_session_ip_dest_port_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_DST_PORT_FIELD_SIZE); + + cnat_nfv9_template_info.nat64_add_session_protocol_field_type = + clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_TYPE); + cnat_nfv9_template_info.nat64_add_session_protocol_field_size = + clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_SIZE); + + + + /* Session Delete */ + cnat_nfv9_template_info.nat64_del_session_template_id = + clib_host_to_net_u16(CNAT_NFV9_NAT64_DEL_SESSION_TEMPLATE_ID); + cnat_nfv9_template_info.nat64_del_session_field_count = + clib_host_to_net_u16(CNAT_NFV9_NAT64_DEL_SESSION_FIELD_COUNT); + + cnat_nfv9_template_info.nat64_del_session_inside_ip_src_addr_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_TYPE); + cnat_nfv9_template_info.nat64_del_session_inside_ip_src_addr_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_SIZE); + + cnat_nfv9_template_info.nat64_del_session_inside_ip_dst_addr_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_DST_ADDR_FIELD_TYPE); + cnat_nfv9_template_info.nat64_del_session_inside_ip_dst_addr_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_DST_ADDR_FIELD_SIZE); + + cnat_nfv9_template_info.nat64_del_session_inside_ip_src_port_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_TYPE); + cnat_nfv9_template_info.nat64_del_session_inside_ip_src_port_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_SIZE); + + cnat_nfv9_template_info.nat64_del_session_inside_ip_dst_port_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_DST_PORT_FIELD_TYPE); + cnat_nfv9_template_info.nat64_del_session_inside_ip_dst_port_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_DST_PORT_FIELD_SIZE); + + cnat_nfv9_template_info.nat64_del_session_protocol_field_type = + clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_TYPE); + cnat_nfv9_template_info.nat64_del_session_protocol_field_size = + clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_SIZE); +#endif + /* + * Create the nat44 session add Template + */ + cnat_nfv9_template_info.nat44_session_add_template_id = + clib_host_to_net_u16(CNAT_NFV9_NAT44_ADD_SESSION_TEMPLATE_ID); + cnat_nfv9_template_info.nat44_session_add_field_count = + clib_host_to_net_u16(CNAT_NFV9_NAT44_ADD_SESSION_FIELD_COUNT); + + cnat_nfv9_template_info.nat44_session_add_inside_vrf_id_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_TYPE); + cnat_nfv9_template_info.nat44_session_add_inside_vrf_id_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_SIZE); + + cnat_nfv9_template_info.nat44_session_add_outside_vrf_id_field_type = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_VRFID_FIELD_TYPE); + cnat_nfv9_template_info.nat44_session_add_outside_vrf_id_field_size = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_VRFID_FIELD_SIZE); + + cnat_nfv9_template_info.nat44_session_add_inside_ip_addr_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_TYPE); + cnat_nfv9_template_info.nat44_session_add_inside_ip_addr_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_SIZE); + + cnat_nfv9_template_info.nat44_session_add_outside_ip_addr_field_type = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_ADDR_FIELD_TYPE); + cnat_nfv9_template_info.nat44_session_add_outside_ip_addr_field_size = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_ADDR_FIELD_SIZE); + + cnat_nfv9_template_info.nat44_session_add_inside_ip_port_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_TYPE); + cnat_nfv9_template_info.nat44_session_add_inside_ip_port_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_SIZE); + + cnat_nfv9_template_info.nat44_session_add_outside_ip_port_field_type = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_FIELD_TYPE); + cnat_nfv9_template_info.nat44_session_add_outside_ip_port_field_size = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_FIELD_SIZE); + + cnat_nfv9_template_info.nat44_session_add_dest_ip_addr_field_type = + clib_host_to_net_u16(CNAT_NFV9_DESTINATION_IP_ADDR_FIELD_TYPE); + cnat_nfv9_template_info.nat44_session_add_dest_ip_addr_field_size = + clib_host_to_net_u16(CNAT_NFV9_DESTINATION_IP_ADDR_FIELD_SIZE); + + cnat_nfv9_template_info.nat44_session_add_dest_port_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_DST_PORT_FIELD_TYPE); + cnat_nfv9_template_info.nat44_session_add_dest_port_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_DST_PORT_FIELD_SIZE); + + cnat_nfv9_template_info.nat44_session_add_protocol_field_type = + clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_TYPE); + cnat_nfv9_template_info.nat44_session_add_protocol_field_size = + clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_SIZE); + + /* + * Create the nat44 session del Template + */ + cnat_nfv9_template_info.nat44_session_del_template_id = + clib_host_to_net_u16(CNAT_NFV9_NAT44_DEL_SESSION_TEMPLATE_ID); + cnat_nfv9_template_info.nat44_session_del_field_count = + clib_host_to_net_u16(CNAT_NFV9_NAT44_DEL_SESSION_FIELD_COUNT); + + cnat_nfv9_template_info.nat44_session_del_inside_vrf_id_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_TYPE); + cnat_nfv9_template_info.nat44_session_del_inside_vrf_id_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_SIZE); + + cnat_nfv9_template_info.nat44_session_del_inside_ip_addr_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_TYPE); + cnat_nfv9_template_info.nat44_session_del_inside_ip_addr_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_SIZE); + + cnat_nfv9_template_info.nat44_session_del_dest_ip_addr_field_type = + clib_host_to_net_u16(CNAT_NFV9_DESTINATION_IP_ADDR_FIELD_TYPE); + cnat_nfv9_template_info.nat44_session_del_dest_ip_addr_field_size = + clib_host_to_net_u16(CNAT_NFV9_DESTINATION_IP_ADDR_FIELD_SIZE); + + cnat_nfv9_template_info.nat44_session_del_inside_ip_port_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_TYPE); + cnat_nfv9_template_info.nat44_session_del_inside_ip_port_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_SIZE); + + cnat_nfv9_template_info.nat44_session_del_dest_port_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_DST_PORT_FIELD_TYPE); + cnat_nfv9_template_info.nat44_session_del_dest_port_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_DST_PORT_FIELD_SIZE); + + cnat_nfv9_template_info.nat44_session_del_protocol_field_type = + clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_TYPE); + cnat_nfv9_template_info.nat44_session_del_protocol_field_size = + clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_SIZE); + /* + * Ds-lite add template + */ +#if 0 + cnat_nfv9_template_info.add_dslite_template_id = + clib_host_to_net_u16(CNAT_NFV9_DS_LITE_ADD_TEMPLATE_ID); + cnat_nfv9_template_info.add_dslite_field_count = + clib_host_to_net_u16(CNAT_NFV9_DS_LITE_ADD_FIELD_COUNT); + + cnat_nfv9_template_info.add_dslite_inside_vrf_id_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_TYPE); + cnat_nfv9_template_info.add_dslite_inside_vrf_id_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_SIZE); + + cnat_nfv9_template_info.add_dslite_outside_vrf_id_field_type = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_VRFID_FIELD_TYPE); + cnat_nfv9_template_info.add_dslite_outside_vrf_id_field_size = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_VRFID_FIELD_SIZE); + + cnat_nfv9_template_info.add_dslite_inside_ip_addr_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_TYPE); + cnat_nfv9_template_info.add_dslite_inside_ip_addr_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_SIZE); + + cnat_nfv9_template_info.add_dslite_inside_ipv6_addr_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_TYPE); + cnat_nfv9_template_info.add_dslite_inside_ipv6_addr_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_SIZE); + + cnat_nfv9_template_info.add_dslite_outside_ip_addr_field_type = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_ADDR_FIELD_TYPE); + cnat_nfv9_template_info.add_dslite_outside_ip_addr_field_size = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_ADDR_FIELD_SIZE); + + cnat_nfv9_template_info.add_dslite_inside_ip_port_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_TYPE); + cnat_nfv9_template_info.add_dslite_inside_ip_port_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_SIZE); + + cnat_nfv9_template_info.add_dslite_outside_ip_port_field_type = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_FIELD_TYPE); + cnat_nfv9_template_info.add_dslite_outside_ip_port_field_size = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_FIELD_SIZE); + + cnat_nfv9_template_info.add_dslite_protocol_field_type = + clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_TYPE); + cnat_nfv9_template_info.add_dslite_protocol_field_size = + clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_SIZE); + + /* + * Ds-lite delete template + */ + cnat_nfv9_template_info.del_dslite_template_id = + clib_host_to_net_u16(CNAT_NFV9_DS_LITE_DEL_TEMPLATE_ID); + cnat_nfv9_template_info.del_dslite_field_count = + clib_host_to_net_u16(CNAT_NFV9_DS_LITE_DEL_FIELD_COUNT); + + cnat_nfv9_template_info.del_dslite_inside_vrf_id_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_TYPE); + cnat_nfv9_template_info.del_dslite_inside_vrf_id_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_SIZE); + + cnat_nfv9_template_info.del_dslite_inside_ip_addr_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_TYPE); + cnat_nfv9_template_info.del_dslite_inside_ip_addr_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_SIZE); + + cnat_nfv9_template_info.del_dslite_inside_ipv6_addr_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_TYPE); + cnat_nfv9_template_info.del_dslite_inside_ipv6_addr_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_SIZE); + + cnat_nfv9_template_info.del_dslite_inside_ip_port_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_TYPE); + cnat_nfv9_template_info.del_dslite_inside_ip_port_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_SIZE); + + cnat_nfv9_template_info.del_dslite_protocol_field_type = + clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_TYPE); + cnat_nfv9_template_info.del_dslite_protocol_field_size = + clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_SIZE); + + /* + * Ds-lite session add template + */ + + cnat_nfv9_template_info.add_dslite_session_template_id = + clib_host_to_net_u16(CNAT_NFV9_DS_LITE_ADD_SESSION_TEMPLATE_ID); + cnat_nfv9_template_info.add_dslite_session_field_count = + clib_host_to_net_u16(CNAT_NFV9_DS_LITE_ADD_SESSION_FIELD_COUNT); + + cnat_nfv9_template_info.add_dslite_session_inside_vrf_id_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_TYPE); + cnat_nfv9_template_info.add_dslite_session_inside_vrf_id_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_SIZE); + + cnat_nfv9_template_info.add_dslite_session_outside_vrf_id_field_type = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_VRFID_FIELD_TYPE); + cnat_nfv9_template_info.add_dslite_session_outside_vrf_id_field_size = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_VRFID_FIELD_SIZE); + + cnat_nfv9_template_info.add_dslite_session_inside_ip_addr_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_TYPE); + cnat_nfv9_template_info.add_dslite_session_inside_ip_addr_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_SIZE); + + cnat_nfv9_template_info.add_dslite_session_inside_ipv6_addr_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_TYPE); + cnat_nfv9_template_info.add_dslite_session_inside_ipv6_addr_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_SIZE); + + cnat_nfv9_template_info.add_dslite_session_outside_ip_addr_field_type = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_ADDR_FIELD_TYPE); + cnat_nfv9_template_info.add_dslite_session_outside_ip_addr_field_size = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_ADDR_FIELD_SIZE); + + cnat_nfv9_template_info.add_dslite_session_inside_ip_port_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_TYPE); + cnat_nfv9_template_info.add_dslite_session_inside_ip_port_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_SIZE); + + cnat_nfv9_template_info.add_dslite_session_outside_ip_port_field_type = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_FIELD_TYPE); + cnat_nfv9_template_info.add_dslite_session_outside_ip_port_field_size = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_FIELD_SIZE); + + cnat_nfv9_template_info.add_dslite_session_dest_ip_addr_field_type = + clib_host_to_net_u16(CNAT_NFV9_DESTINATION_IP_ADDR_FIELD_TYPE); + cnat_nfv9_template_info.add_dslite_session_dest_ip_addr_field_size = + clib_host_to_net_u16(CNAT_NFV9_DESTINATION_IP_ADDR_FIELD_SIZE); + + cnat_nfv9_template_info.add_dslite_session_dest_port_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_DST_PORT_FIELD_TYPE); + cnat_nfv9_template_info.add_dslite_session_dest_port_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_DST_PORT_FIELD_SIZE); + + cnat_nfv9_template_info.add_dslite_session_protocol_field_type = + clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_TYPE); + cnat_nfv9_template_info.add_dslite_session_protocol_field_size = + clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_SIZE); + + /* + * Ds-lite session delete template + */ + cnat_nfv9_template_info.del_dslite_session_template_id = + clib_host_to_net_u16(CNAT_NFV9_DS_LITE_DEL_SESSION_TEMPLATE_ID); + cnat_nfv9_template_info.del_dslite_session_field_count = + clib_host_to_net_u16(CNAT_NFV9_DS_LITE_DEL_SESSION_FIELD_COUNT); + + cnat_nfv9_template_info.del_dslite_session_inside_vrf_id_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_TYPE); + cnat_nfv9_template_info.del_dslite_session_inside_vrf_id_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_SIZE); + + cnat_nfv9_template_info.del_dslite_session_inside_ip_addr_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_TYPE); + cnat_nfv9_template_info.del_dslite_session_inside_ip_addr_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_SIZE); + + cnat_nfv9_template_info.del_dslite_session_inside_ipv6_addr_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_TYPE); + cnat_nfv9_template_info.del_dslite_session_inside_ipv6_addr_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_SIZE); + + cnat_nfv9_template_info.del_dslite_session_inside_ip_port_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_TYPE); + cnat_nfv9_template_info.del_dslite_session_inside_ip_port_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_PORT_FIELD_SIZE); + + cnat_nfv9_template_info.del_dslite_session_dest_ip_addr_field_type = + clib_host_to_net_u16(CNAT_NFV9_DESTINATION_IP_ADDR_FIELD_TYPE); + cnat_nfv9_template_info.del_dslite_session_dest_ip_addr_field_size = + clib_host_to_net_u16(CNAT_NFV9_DESTINATION_IP_ADDR_FIELD_SIZE); + + cnat_nfv9_template_info.del_dslite_session_dest_port_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_DST_PORT_FIELD_TYPE); + cnat_nfv9_template_info.del_dslite_session_dest_port_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_DST_PORT_FIELD_SIZE); + + cnat_nfv9_template_info.del_dslite_session_protocol_field_type = + clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_TYPE); + cnat_nfv9_template_info.del_dslite_session_protocol_field_size = + clib_host_to_net_u16(CNAT_NFV9_PROTOCOL_FIELD_SIZE); + + /* Create add bulk template */ + cnat_nfv9_template_info.bulk_add_template_id = + clib_host_to_net_u16(CNAT_NFV9_NAT44_BULK_ADD_TEMPLATE_ID); + cnat_nfv9_template_info.bulk_add_field_count = + clib_host_to_net_u16(CNAT_NFV9_NAT44_BULK_ADD_FIELD_COUNT); + + cnat_nfv9_template_info.bulk_add_inside_vrf_id_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_TYPE); + cnat_nfv9_template_info.bulk_add_inside_vrf_id_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_SIZE); + + cnat_nfv9_template_info.bulk_add_outside_vrf_id_field_type = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_VRFID_FIELD_TYPE); + cnat_nfv9_template_info.bulk_add_outside_vrf_id_field_size = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_VRFID_FIELD_SIZE); + + cnat_nfv9_template_info.bulk_add_inside_ip_addr_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_TYPE); + cnat_nfv9_template_info.bulk_add_inside_ip_addr_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_SIZE); + + cnat_nfv9_template_info.bulk_add_outside_ip_addr_field_type = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_ADDR_FIELD_TYPE); + cnat_nfv9_template_info.bulk_add_outside_ip_addr_field_size = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_ADDR_FIELD_SIZE); + + cnat_nfv9_template_info.bulk_add_outside_start_port_field_type = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_START_FIELD_TYPE); + cnat_nfv9_template_info.bulk_add_outside_start_port_field_size = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_START_FIELD_SIZE); + + cnat_nfv9_template_info.bulk_add_outside_end_port_field_type = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_END_FIELD_TYPE); + cnat_nfv9_template_info.bulk_add_outside_end_port_field_size = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_END_FIELD_SIZE); + + /* + * Create the bulk delete Template + */ + cnat_nfv9_template_info.bulk_del_template_id = + clib_host_to_net_u16(CNAT_NFV9_NAT44_BULK_DEL_TEMPLATE_ID); + cnat_nfv9_template_info.bulk_del_field_count = + clib_host_to_net_u16(CNAT_NFV9_NAT44_BULK_DEL_FIELD_COUNT); + + cnat_nfv9_template_info.bulk_del_inside_vrf_id_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_TYPE); + cnat_nfv9_template_info.bulk_del_inside_vrf_id_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_SIZE); + + cnat_nfv9_template_info.bulk_del_inside_ip_addr_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_TYPE); + cnat_nfv9_template_info.bulk_del_inside_ip_addr_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_SIZE); + + cnat_nfv9_template_info.bulk_del_outside_start_port_field_type = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_START_FIELD_TYPE); + cnat_nfv9_template_info.bulk_del_outside_start_port_field_size = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_START_FIELD_SIZE); + + /* + * Ds-lite bulk add template + */ + cnat_nfv9_template_info.bulk_dslite_add_template_id = + clib_host_to_net_u16(CNAT_NFV9_DS_LITE_BULK_ADD_TEMPLATE_ID); + cnat_nfv9_template_info.bulk_dslite_add_field_count = + clib_host_to_net_u16(CNAT_NFV9_DS_LITE_BULK_ADD_FIELD_COUNT); + + cnat_nfv9_template_info.bulk_dslite_add_inside_vrf_id_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_TYPE); + cnat_nfv9_template_info.bulk_dslite_add_inside_vrf_id_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_SIZE); + + cnat_nfv9_template_info.bulk_dslite_add_outside_vrf_id_field_type = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_VRFID_FIELD_TYPE); + cnat_nfv9_template_info.bulk_dslite_add_outside_vrf_id_field_size = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_VRFID_FIELD_SIZE); + + cnat_nfv9_template_info.bulk_dslite_add_inside_ip_addr_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_TYPE); + cnat_nfv9_template_info.bulk_dslite_add_inside_ip_addr_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_SIZE); + + cnat_nfv9_template_info.bulk_dslite_add_inside_ipv6_addr_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_TYPE); + cnat_nfv9_template_info.bulk_dslite_add_inside_ipv6_addr_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_SIZE); + + cnat_nfv9_template_info.bulk_dslite_add_outside_ip_addr_field_type = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_ADDR_FIELD_TYPE); + cnat_nfv9_template_info.bulk_dslite_add_outside_ip_addr_field_size = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_ADDR_FIELD_SIZE); + + cnat_nfv9_template_info.bulk_dslite_add_outside_start_port_field_type = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_START_FIELD_TYPE); + cnat_nfv9_template_info.bulk_dslite_add_outside_start_port_field_size = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_START_FIELD_SIZE); + + cnat_nfv9_template_info.bulk_dslite_add_outside_end_port_field_type = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_END_FIELD_TYPE); + cnat_nfv9_template_info.bulk_dslite_add_outside_end_port_field_size = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_END_FIELD_SIZE); + + /* + * Ds-lite bulk delete template + */ + + cnat_nfv9_template_info.bulk_dslite_del_template_id = + clib_host_to_net_u16(CNAT_NFV9_DS_LITE_BULK_DEL_TEMPLATE_ID); + cnat_nfv9_template_info.bulk_dslite_del_field_count = + clib_host_to_net_u16(CNAT_NFV9_DS_LITE_BULK_DEL_FIELD_COUNT); + + cnat_nfv9_template_info.bulk_dslite_del_inside_vrf_id_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_TYPE); + cnat_nfv9_template_info.bulk_dslite_del_inside_vrf_id_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_SIZE); + + cnat_nfv9_template_info.bulk_dslite_del_inside_ip_addr_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_TYPE); + cnat_nfv9_template_info.bulk_dslite_del_inside_ip_addr_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IP_ADDR_FIELD_SIZE); + + cnat_nfv9_template_info.bulk_dslite_del_inside_ipv6_addr_field_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_TYPE); + cnat_nfv9_template_info.bulk_dslite_del_inside_ipv6_addr_field_size = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_SIZE); + + cnat_nfv9_template_info.bulk_dslite_del_outside_start_port_field_type = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_START_FIELD_TYPE); + cnat_nfv9_template_info.bulk_dslite_del_outside_start_port_field_size = + clib_host_to_net_u16(CNAT_NFV9_OUTSIDE_IP_PORT_START_FIELD_SIZE); + +#endif /* NO_BULK_LOGGING */ + + /* + * Ingress vrfid - name mapping + */ + CNAT_NFV9_OPTION_TEMPLATE.flowset_id = + clib_host_to_net_u16(CNAT_NFV9_OPTION_TEMPLATE_FLOWSET_ID); + CNAT_NFV9_OPTION_TEMPLATE.length = + clib_host_to_net_u16(CNAT_NFV9_OPTION_TEMPLATE_LENGTH); + + CNAT_NFV9_OPTION_TEMPLATE.ingress_vrfid_name_map_template_id = + clib_host_to_net_u16(CNAT_NFV9_INGRESS_VRF_ID_NAME_TEMPLATE_ID); + /* currently no scope field supported */ + CNAT_NFV9_OPTION_TEMPLATE.ingress_vrfid_name_map_scope_len = 0; + CNAT_NFV9_OPTION_TEMPLATE.ingress_vrfid_name_map_option_len = + clib_host_to_net_u16(CNAT_NFV9_INGRESS_VRF_ID_NAME_OPTION_LEN); + CNAT_NFV9_OPTION_TEMPLATE.ingress_vrfid_name_map_vrfid_option_type = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_TYPE); + CNAT_NFV9_OPTION_TEMPLATE.ingress_vrfid_name_map_vrfid_option_len = + clib_host_to_net_u16(CNAT_NFV9_INSIDE_VRFID_FIELD_SIZE); + CNAT_NFV9_OPTION_TEMPLATE.ingress_vrfid_name_map_vrfname_option_type = + clib_host_to_net_u16(CNAT_NFV9_INGRESS_VRF_NAME_FIELD_TYPE); + CNAT_NFV9_OPTION_TEMPLATE.ingress_vrfid_name_map_vrfname_option_len = + clib_host_to_net_u16(CNAT_NFV9_INGRESS_VRF_NAME_FIELD_SIZE); + + /* + * Set the padding (which was added to make the size of template + * multiple of 4) to zero + */ + CNAT_NFV9_OPTION_TEMPLATE.padding1 = 0; +} + +/* + * one time function + * has to be called at the init time + */ +void cnat_nfv9_logging_init() +{ + if (!cnat_nfv9_global_info.cnat_nfv9_init_done) { + cnat_nfv9_template_init(); + + /* Pre allocate for NFV9_SERVER_POOL_SIZE. Will be good + * enough for most deployments + */ + pool_alloc(nfv9_server_info_pool, NFV9_SERVER_POOL_SIZE); + int i; + nfv9_server_info_t *server __attribute__((unused)); + for(i = 0; i < NFV9_SERVER_POOL_SIZE; i++) { + pool_get(nfv9_server_info_pool, server); + } + + for(i = 0; i < NFV9_SERVER_POOL_SIZE; i++) { + pool_put(nfv9_server_info_pool, nfv9_server_info_pool + i); + } + + memset(&cnat_nfv9_global_info, 0 , sizeof(cnat_nfv9_global_info_t)); + ASSERT(cnat_nfv9_global_info.cnat_nfv9_disp_node_index != (u16)~0); + + cnat_nfv9_global_info.cnat_nfv9_global_collector_index = EMPTY; + cnat_nfv9_global_info.cnat_nfv9_init_done = 1; + + /* + * src id is set to infra IPv4 address + octeon core number + */ + nfv9_src_id = my_instance_number; + } +} diff --git a/plugins/vcgn-plugin/vcgn/cnat_logging.h b/plugins/vcgn-plugin/vcgn/cnat_logging.h new file mode 100644 index 00000000..7bd43ecf --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_logging.h @@ -0,0 +1,1091 @@ +/* + *------------------------------------------------------------------ + * cnat_logging.h + * + * Copyright (c) 2009, 2012 Cisco and/or its affiliates. + * 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 __CNAT_LOGGING_H__ +#define __CNAT_LOGGING_H__ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "nat64_db.h" +#include "cnat_log_common.h" +#include "dslite_defs.h" + +#define NFV9_DEF_PATH_MTU 1500 +#define NFV9_VRF_NAME_LEN 12 + +/* one time call at the beginning */ +void cnat_nfv9_logging_init(); + +/* + * unconditional call + * will check logging config inside + */ +void cnat_nfv9_log_mapping_create(cnat_main_db_entry_t * db, + cnat_vrfmap_t *vrfmap +#ifndef NO_BULK_LOGGING + , int bulk_alloc +#endif + ); + +void cnat_nfv9_nat44_log_session_create(cnat_main_db_entry_t * db, + cnat_session_entry_t * sdb, + cnat_vrfmap_t *vrfmap); + +void cnat_nfv9_nat44_log_session_delete(cnat_main_db_entry_t * db, + cnat_session_entry_t * sdb, + cnat_vrfmap_t *vrfmap); + + +/* + * unconditional call + * will check logging config inside + */ +void cnat_nfv9_log_mapping_delete(cnat_main_db_entry_t * db, + cnat_vrfmap_t *vrfmap +#ifndef NO_BULK_LOGGING + , int bulk_alloc +#endif + ); + +/* nat44 syslog APIs */ +void cnat_syslog_nat44_mapping_create(cnat_main_db_entry_t *db, + cnat_vrfmap_t *vrfmap, cnat_session_entry_t * sdb +#ifndef NO_BULK_LOGGING + , int bulk_alloc +#endif + ); + +void cnat_syslog_nat44_mapping_delete(cnat_main_db_entry_t *db, + cnat_vrfmap_t *vrfmap, cnat_session_entry_t *sdb +#ifndef NO_BULK_LOGGING + , int bulk_alloc +#endif + ); + +/* + * dslite + */ +void cnat_nfv9_ds_lite_mapping_create(cnat_main_db_entry_t *db, + dslite_table_entry_t *dslite_entry +#ifndef NO_BULK_LOGGING + , int bulk_alloc +#endif + ); + +void cnat_nfv9_ds_lite_mapping_delete(cnat_main_db_entry_t *db, + dslite_table_entry_t *dslite_entry +#ifndef NO_BULK_LOGGING + , int bulk_alloc +#endif + ); +void cnat_nfv9_ds_lite_log_session_create(cnat_main_db_entry_t * db, + dslite_table_entry_t *dslite_entry, + cnat_session_entry_t * sdb); + +void cnat_nfv9_ds_lite_log_session_delete(cnat_main_db_entry_t * db, + dslite_table_entry_t *dslite_entry, + cnat_session_entry_t * sdb); + +/* + * nat64 + */ + +void cnat_nfv9_bib_mapping_create (nat64_bib_entry_t *db, + nat64_table_entry_t *nat64_entry); + +void cnat_nfv9_session_mapping_create (nat64_bib_entry_t *bdb, + nat64_session_entry_t *sdb, + nat64_table_entry_t *nat64_entry_ptr); + +void cnat_nfv9_bib_mapping_delete (nat64_bib_entry_t *db, + nat64_table_entry_t *nat64_entry); + +void cnat_nfv9_session_mapping_delete (nat64_bib_entry_t *bdb, + nat64_session_entry_t *sdb, + nat64_table_entry_t *nat64_entry_ptr); + +typedef enum { + RECORD_INVALID = 0, + NAT44_ADD_RECORD, + NAT44_DEL_RECORD, + NAT64_ADD_BIB_RECORD, + NAT64_DEL_BIB_RECORD, + NAT64_ADD_SESSION_RECORD, + NAT64_DEL_SESSION_RECORD, + DS_LITE_ADD_RECORD, + DS_LITE_DEL_RECORD, + NAT44_BULK_ADD_RECORD, + NAT44_BULK_DEL_RECORD, + DS_LITE_BULK_ADD_RECORD, + DS_LITE_BULK_DEL_RECORD, + INGRESS_VRF_ID_NAME_RECORD, + NAT44_ADD_SESSION_RECORD, + NAT44_DEL_SESSION_RECORD, + DS_LITE_ADD_SESSION_RECORD, + DS_LITE_DEL_SESSION_RECORD, + MAX_RECORDS +} netflow_record; + +typedef enum { + TEMPLATE_SENT_FALSE = 0, + TEMPLATE_SENT_TRUE = 1 +} netflow_template_sent; + +#define cnat_nfv9_get_sys_up_time_in_ms cnat_get_sys_up_time_in_ms + +#define cnat_nfv9_get_unix_time_in_seconds cnat_get_unix_time_in_seconds + +#define cnat_nfv9_dump_time_change_logs cnat_dump_time_change_logs + + +/* + * Netflow V9 Specific Defines and structures + */ + +#define CNAT_NFV9_VERSION_NUMBER 9 + +#define CNAT_NFV9_TEMPLATE_FLOWSET_ID 0 +#define CNAT_NFV9_OPTION_TEMPLATE_FLOWSET_ID 1 + +#define CNAT_NFV9_ADD_FIELD_COUNT 7 +#define CNAT_NFV9_DEL_FIELD_COUNT 4 +#define CNAT_NFV9_DS_LITE_ADD_FIELD_COUNT 8 +#define CNAT_NFV9_DS_LITE_DEL_FIELD_COUNT 5 +#define CNAT_NFV9_NAT64_ADD_BIB_FIELD_COUNT 5 +#define CNAT_NFV9_NAT64_DEL_BIB_FIELD_COUNT 3 +#define CNAT_NFV9_NAT64_ADD_SESSION_FIELD_COUNT 8 +#define CNAT_NFV9_NAT64_DEL_SESSION_FIELD_COUNT 5 +#define CNAT_NFV9_NAT44_ADD_SESSION_FIELD_COUNT 9 +#define CNAT_NFV9_NAT44_DEL_SESSION_FIELD_COUNT 6 +#define CNAT_NFV9_DS_LITE_ADD_SESSION_FIELD_COUNT 10 +#define CNAT_NFV9_DS_LITE_DEL_SESSION_FIELD_COUNT 7 + +#define CNAT_NFV9_ADD_TEMPLATE_ID 256 +#define CNAT_NFV9_DEL_TEMPLATE_ID 257 +#define CNAT_NFV9_NAT64_ADD_BIB_TEMPLATE_ID 258 +#define CNAT_NFV9_NAT64_DEL_BIB_TEMPLATE_ID 259 +#define CNAT_NFV9_NAT64_ADD_SESSION_TEMPLATE_ID 260 +#define CNAT_NFV9_NAT64_DEL_SESSION_TEMPLATE_ID 261 +#define CNAT_NFV9_INGRESS_VRF_ID_NAME_TEMPLATE_ID 262 +#define CNAT_NFV9_DS_LITE_ADD_TEMPLATE_ID 267 +#define CNAT_NFV9_DS_LITE_DEL_TEMPLATE_ID 268 +#define CNAT_NFV9_NAT44_ADD_SESSION_TEMPLATE_ID 271 +#define CNAT_NFV9_NAT44_DEL_SESSION_TEMPLATE_ID 272 +#define CNAT_NFV9_DS_LITE_ADD_SESSION_TEMPLATE_ID 273 +#define CNAT_NFV9_DS_LITE_DEL_SESSION_TEMPLATE_ID 274 + +#ifndef NO_BULK_LOGGING +#define CNAT_NFV9_NAT44_BULK_ADD_TEMPLATE_ID 265 +#define CNAT_NFV9_NAT44_BULK_DEL_TEMPLATE_ID 266 +#define CNAT_NFV9_DS_LITE_BULK_ADD_TEMPLATE_ID 269 +#define CNAT_NFV9_DS_LITE_BULK_DEL_TEMPLATE_ID 270 + +#define CNAT_NFV9_NAT44_BULK_ADD_FIELD_COUNT 6 +#define CNAT_NFV9_NAT44_BULK_DEL_FIELD_COUNT 3 +#define CNAT_NFV9_DS_LITE_BULK_ADD_FIELD_COUNT 7 +#define CNAT_NFV9_DS_LITE_BULK_DEL_FIELD_COUNT 4 + +#define CNAT_NFV9_OUTSIDE_IP_PORT_START_FIELD_TYPE 361 +#define CNAT_NFV9_OUTSIDE_IP_PORT_START_FIELD_SIZE 2 + +#define CNAT_NFV9_OUTSIDE_IP_PORT_END_FIELD_TYPE 362 +#define CNAT_NFV9_OUTSIDE_IP_PORT_END_FIELD_SIZE 2 + +#endif /* #ifndef NO_BULK_LOGGING */ + +#define CNAT_NFV9_INGRESS_VRF_NAME_FIELD_TYPE 236 +#define CNAT_NFV9_INGRESS_VRF_NAME_FIELD_SIZE 12 +/* 4 byte for vrf_id + 4 byte for vrf_name (option fields) */ +#define CNAT_NFV9_INGRESS_VRF_ID_NAME_OPTION_LEN 8 +extern u16 cnat_template_id[MAX_RECORDS]; + +#define CNAT_NFV9_INSIDE_VRFID_FIELD_TYPE 234 +#define CNAT_NFV9_INSIDE_VRFID_FIELD_SIZE 4 + +#define CNAT_NFV9_OUTSIDE_VRFID_FIELD_TYPE 235 +#define CNAT_NFV9_OUTSIDE_VRFID_FIELD_SIZE 4 + +#define CNAT_NFV9_INSIDE_IP_ADDR_FIELD_TYPE 8 +#define CNAT_NFV9_INSIDE_IP_ADDR_FIELD_SIZE 4 + +#define CNAT_NFV9_OUTSIDE_IP_ADDR_FIELD_TYPE 225 +#define CNAT_NFV9_OUTSIDE_IP_ADDR_FIELD_SIZE 4 + +#define CNAT_NFV9_INSIDE_IP_PORT_FIELD_TYPE 7 +#define CNAT_NFV9_INSIDE_IP_PORT_FIELD_SIZE 2 + +#define CNAT_NFV9_OUTSIDE_IP_PORT_FIELD_TYPE 227 +#define CNAT_NFV9_OUTSIDE_IP_PORT_FIELD_SIZE 2 + +#define CNAT_NFV9_PROTOCOL_FIELD_TYPE 4 +#define CNAT_NFV9_PROTOCOL_FIELD_SIZE 1 + +/* IPv6 related info */ + +#define CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_TYPE 27 +#define CNAT_NFV9_INSIDE_IPV6_SRC_ADDR_FIELD_SIZE 16 + +#define CNAT_NFV9_INSIDE_IPV6_DST_ADDR_FIELD_TYPE 28 +#define CNAT_NFV9_INSIDE_IPV6_DST_ADDR_FIELD_SIZE 16 + +#define CNAT_NFV9_OUTSIDE_IP_DST_ADDR_FIELD_TYPE 226 +#define CNAT_NFV9_OUTSIDE_IP_DST_ADDR_FIELD_SIZE 4 + +#define CNAT_NFV9_INSIDE_DST_PORT_FIELD_TYPE 11 +#define CNAT_NFV9_INSIDE_DST_PORT_FIELD_SIZE 2 + +#define CNAT_NFV9_DESTINATION_IP_ADDR_FIELD_TYPE 12 +#define CNAT_NFV9_DESTINATION_IP_ADDR_FIELD_SIZE 4 + + +typedef struct { + u16 version; + u16 count; + u32 sys_up_time; /* time in ms since system was booted */ + u32 timestamp; /* UNIX time in seconds since 1970 */ + u32 sequence_num; + u32 source_id; +} nfv9_header_t; + +/* + * Hardcoded - need to be fixed + */ +#define CNAT_NFV9_SOURCE_ID_VALUE 0x1234 + +typedef struct { + u16 flowset_id; + u16 length; + + u16 ingress_vrfid_name_map_template_id; + u16 ingress_vrfid_name_map_scope_len; + u16 ingress_vrfid_name_map_option_len; + u16 ingress_vrfid_name_map_vrfid_option_type; + u16 ingress_vrfid_name_map_vrfid_option_len; + u16 ingress_vrfid_name_map_vrfname_option_type; + u16 ingress_vrfid_name_map_vrfname_option_len; + /* + * Adding the padding so as to make the tempalate + * structure end on a 4 byte boundary + */ + u16 padding1; + +} cnat_nfv9_option_template_t; + +/* + * The following structure defines the Netflow Template that + * will be exported to the Netflow Collector + */ + +typedef struct { + u16 flowset_id; + u16 length; + + u16 add_template_id; + u16 add_field_count; + u16 add_inside_vrf_id_field_type; + u16 add_inside_vrf_id_field_size; + u16 add_outside_vrf_id_field_type; + u16 add_outside_vrf_id_field_size; + u16 add_inside_ip_addr_field_type; + u16 add_inside_ip_addr_field_size; + u16 add_outside_ip_addr_field_type; + u16 add_outside_ip_addr_field_size; + u16 add_inside_ip_port_field_type; + u16 add_inside_ip_port_field_size; + u16 add_outside_ip_port_field_type; + u16 add_outside_ip_port_field_size; + u16 add_protocol_field_type; + u16 add_protocol_field_size; + + u16 del_template_id; + u16 del_field_count; + u16 del_inside_vrf_id_field_type; + u16 del_inside_vrf_id_field_size; + u16 del_inside_ip_addr_field_type; + u16 del_inside_ip_addr_field_size; + u16 del_inside_ip_port_field_type; + u16 del_inside_ip_port_field_size; + u16 del_protocol_field_type; + u16 del_protocol_field_size; +#if 0 + /* NAT64 related info */ + u16 nat64_add_bib_template_id; + u16 nat64_add_bib_field_count; + u16 nat64_add_bib_inside_ipv6_addr_field_type; + u16 nat64_add_bib_inside_ipv6_addr_field_size; + u16 nat64_add_bib_outside_ip_addr_field_type; + u16 nat64_add_bib_outside_ip_addr_field_size; + u16 nat64_add_bib_inside_ip_port_field_type; + u16 nat64_add_bib_inside_ip_port_field_size; + u16 nat64_add_bib_outside_ip_port_field_type; + u16 nat64_add_bib_outside_ip_port_field_size; + u16 nat64_add_bib_protocol_field_type; + u16 nat64_add_bib_protocol_field_size; + + u16 nat64_del_bib_template_id; + u16 nat64_del_bib_field_count; + u16 nat64_del_bib_inside_ip_addr_field_type; + u16 nat64_del_bib_inside_ip_addr_field_size; + u16 nat64_del_bib_inside_ip_port_field_type; + u16 nat64_del_bib_inside_ip_port_field_size; + u16 nat64_del_bib_protocol_field_type; + u16 nat64_del_bib_protocol_field_size; + + + u16 nat64_add_session_template_id; + u16 nat64_add_session_field_count; + u16 nat64_add_session_inside_ipv6_src_addr_field_type; + u16 nat64_add_session_inside_ipv6_src_addr_field_size; + u16 nat64_add_session_outside_ip_src_addr_field_type; + u16 nat64_add_session_outside_ip_src_addr_field_size; + u16 nat64_add_session_inside_ipv6_dst_addr_field_type; + u16 nat64_add_session_inside_ipv6_dst_addr_field_size; + u16 nat64_add_session_outside_ip_dst_addr_field_type; + u16 nat64_add_session_outside_ip_dst_addr_field_size; + u16 nat64_add_session_inside_ip_src_port_field_type; + u16 nat64_add_session_inside_ip_src_port_field_size; + u16 nat64_add_session_outside_ip_src_port_field_type; + u16 nat64_add_session_outside_ip_src_port_field_size; + u16 nat64_add_session_ip_dest_port_field_type; + u16 nat64_add_session_ip_dest_port_field_size; + u16 nat64_add_session_protocol_field_type; + u16 nat64_add_session_protocol_field_size; + + u16 nat64_del_session_template_id; + u16 nat64_del_session_field_count; + u16 nat64_del_session_inside_ip_src_addr_field_type; + u16 nat64_del_session_inside_ip_src_addr_field_size; + u16 nat64_del_session_inside_ip_dst_addr_field_type; + u16 nat64_del_session_inside_ip_dst_addr_field_size; + u16 nat64_del_session_inside_ip_src_port_field_type; + u16 nat64_del_session_inside_ip_src_port_field_size; + u16 nat64_del_session_inside_ip_dst_port_field_type; + u16 nat64_del_session_inside_ip_dst_port_field_size; + u16 nat64_del_session_protocol_field_type; + u16 nat64_del_session_protocol_field_size; + + /* + * Ds-Lite specific info + */ + u16 add_dslite_template_id; + u16 add_dslite_field_count; + u16 add_dslite_inside_vrf_id_field_type; + u16 add_dslite_inside_vrf_id_field_size; + u16 add_dslite_outside_vrf_id_field_type; + u16 add_dslite_outside_vrf_id_field_size; + u16 add_dslite_inside_ip_addr_field_type; + u16 add_dslite_inside_ip_addr_field_size; + u16 add_dslite_inside_ipv6_addr_field_type; + u16 add_dslite_inside_ipv6_addr_field_size; + u16 add_dslite_outside_ip_addr_field_type; + u16 add_dslite_outside_ip_addr_field_size; + u16 add_dslite_inside_ip_port_field_type; + u16 add_dslite_inside_ip_port_field_size; + u16 add_dslite_outside_ip_port_field_type; + u16 add_dslite_outside_ip_port_field_size; + u16 add_dslite_protocol_field_type; + u16 add_dslite_protocol_field_size; + + u16 del_dslite_template_id; + u16 del_dslite_field_count; + u16 del_dslite_inside_vrf_id_field_type; + u16 del_dslite_inside_vrf_id_field_size; + u16 del_dslite_inside_ip_addr_field_type; + u16 del_dslite_inside_ip_addr_field_size; + u16 del_dslite_inside_ipv6_addr_field_type; + u16 del_dslite_inside_ipv6_addr_field_size; + u16 del_dslite_inside_ip_port_field_type; + u16 del_dslite_inside_ip_port_field_size; + u16 del_dslite_protocol_field_type; + u16 del_dslite_protocol_field_size; +#endif + +//#ifndef NO_BULK_LOGGING /* commenting for time being */ +#if 0 + u16 bulk_add_template_id; + u16 bulk_add_field_count; + u16 bulk_add_inside_vrf_id_field_type; + u16 bulk_add_inside_vrf_id_field_size; + u16 bulk_add_outside_vrf_id_field_type; + u16 bulk_add_outside_vrf_id_field_size; + u16 bulk_add_inside_ip_addr_field_type; + u16 bulk_add_inside_ip_addr_field_size; + u16 bulk_add_outside_ip_addr_field_type; + u16 bulk_add_outside_ip_addr_field_size; + u16 bulk_add_outside_start_port_field_type; + u16 bulk_add_outside_start_port_field_size; + u16 bulk_add_outside_end_port_field_type; + u16 bulk_add_outside_end_port_field_size; + + u16 bulk_del_template_id; + u16 bulk_del_field_count; + u16 bulk_del_inside_vrf_id_field_type; + u16 bulk_del_inside_vrf_id_field_size; + u16 bulk_del_inside_ip_addr_field_type; + u16 bulk_del_inside_ip_addr_field_size; + u16 bulk_del_outside_start_port_field_type; + u16 bulk_del_outside_start_port_field_size; + + /* ds-lite bulk logging create delete event */ + + u16 bulk_dslite_add_template_id; + u16 bulk_dslite_add_field_count; + u16 bulk_dslite_add_inside_vrf_id_field_type; + u16 bulk_dslite_add_inside_vrf_id_field_size; + u16 bulk_dslite_add_outside_vrf_id_field_type; + u16 bulk_dslite_add_outside_vrf_id_field_size; + u16 bulk_dslite_add_inside_ip_addr_field_type; + u16 bulk_dslite_add_inside_ip_addr_field_size; + u16 bulk_dslite_add_inside_ipv6_addr_field_type; + u16 bulk_dslite_add_inside_ipv6_addr_field_size; + u16 bulk_dslite_add_outside_ip_addr_field_type; + u16 bulk_dslite_add_outside_ip_addr_field_size; + u16 bulk_dslite_add_outside_start_port_field_type; + u16 bulk_dslite_add_outside_start_port_field_size; + u16 bulk_dslite_add_outside_end_port_field_type; + u16 bulk_dslite_add_outside_end_port_field_size; + + u16 bulk_dslite_del_template_id; + u16 bulk_dslite_del_field_count; + u16 bulk_dslite_del_inside_vrf_id_field_type; + u16 bulk_dslite_del_inside_vrf_id_field_size; + u16 bulk_dslite_del_inside_ip_addr_field_type; + u16 bulk_dslite_del_inside_ip_addr_field_size; + u16 bulk_dslite_del_inside_ipv6_addr_field_type; + u16 bulk_dslite_del_inside_ipv6_addr_field_size; + u16 bulk_dslite_del_outside_start_port_field_type; + u16 bulk_dslite_del_outside_start_port_field_size; + +#endif /* NO_BULK_LOGGING */ + + u16 nat44_session_add_template_id; + u16 nat44_session_add_field_count; + u16 nat44_session_add_inside_vrf_id_field_type; + u16 nat44_session_add_inside_vrf_id_field_size; + u16 nat44_session_add_outside_vrf_id_field_type; + u16 nat44_session_add_outside_vrf_id_field_size; + u16 nat44_session_add_inside_ip_addr_field_type; + u16 nat44_session_add_inside_ip_addr_field_size; + u16 nat44_session_add_outside_ip_addr_field_type; + u16 nat44_session_add_outside_ip_addr_field_size; + u16 nat44_session_add_inside_ip_port_field_type; + u16 nat44_session_add_inside_ip_port_field_size; + u16 nat44_session_add_outside_ip_port_field_type; + u16 nat44_session_add_outside_ip_port_field_size; + u16 nat44_session_add_dest_ip_addr_field_type; + u16 nat44_session_add_dest_ip_addr_field_size; + u16 nat44_session_add_dest_port_field_type; + u16 nat44_session_add_dest_port_field_size; + u16 nat44_session_add_protocol_field_type; + u16 nat44_session_add_protocol_field_size; + + u16 nat44_session_del_template_id; + u16 nat44_session_del_field_count; + u16 nat44_session_del_inside_vrf_id_field_type; + u16 nat44_session_del_inside_vrf_id_field_size; + u16 nat44_session_del_inside_ip_addr_field_type; + u16 nat44_session_del_inside_ip_addr_field_size; + u16 nat44_session_del_dest_ip_addr_field_type; + u16 nat44_session_del_dest_ip_addr_field_size; + u16 nat44_session_del_inside_ip_port_field_type; + u16 nat44_session_del_inside_ip_port_field_size; + u16 nat44_session_del_dest_port_field_type; + u16 nat44_session_del_dest_port_field_size; + u16 nat44_session_del_protocol_field_type; + u16 nat44_session_del_protocol_field_size; + +#if 0 + u16 add_dslite_session_template_id; + u16 add_dslite_session_field_count; + u16 add_dslite_session_inside_vrf_id_field_type; + u16 add_dslite_session_inside_vrf_id_field_size; + u16 add_dslite_session_outside_vrf_id_field_type; + u16 add_dslite_session_outside_vrf_id_field_size; + u16 add_dslite_session_inside_ip_addr_field_type; + u16 add_dslite_session_inside_ip_addr_field_size; + u16 add_dslite_session_inside_ipv6_addr_field_type; + u16 add_dslite_session_inside_ipv6_addr_field_size; + u16 add_dslite_session_outside_ip_addr_field_type; + u16 add_dslite_session_outside_ip_addr_field_size; + u16 add_dslite_session_inside_ip_port_field_type; + u16 add_dslite_session_inside_ip_port_field_size; + u16 add_dslite_session_outside_ip_port_field_type; + u16 add_dslite_session_outside_ip_port_field_size; + u16 add_dslite_session_dest_ip_addr_field_type; + u16 add_dslite_session_dest_ip_addr_field_size; + u16 add_dslite_session_dest_port_field_type; + u16 add_dslite_session_dest_port_field_size; + u16 add_dslite_session_protocol_field_type; + u16 add_dslite_session_protocol_field_size; + + u16 del_dslite_session_template_id; + u16 del_dslite_session_field_count; + u16 del_dslite_session_inside_vrf_id_field_type; + u16 del_dslite_session_inside_vrf_id_field_size; + u16 del_dslite_session_inside_ip_addr_field_type; + u16 del_dslite_session_inside_ip_addr_field_size; + u16 del_dslite_session_inside_ipv6_addr_field_type; + u16 del_dslite_session_inside_ipv6_addr_field_size; + u16 del_dslite_session_dest_ip_addr_field_type; + u16 del_dslite_session_dest_ip_addr_field_size; + u16 del_dslite_session_inside_ip_port_field_type; + u16 del_dslite_session_inside_ip_port_field_size; + u16 del_dslite_session_dest_port_field_type; + u16 del_dslite_session_dest_port_field_size; + u16 del_dslite_session_protocol_field_type; + u16 del_dslite_session_protocol_field_size; +#endif + + /* + * Netflow option template + * Ingress VRF ID - Name mapping + * This template will be sent under flowset id 1 + */ + cnat_nfv9_option_template_t cnat_nfv9_option_template; +} cnat_nfv9_template_t; + +/* + * The Dataflow header for each add/delete record group + */ +typedef struct { + u16 dataflow_template_id; + u16 dataflow_length; +} nfv9_dataflow_record_header_t; + +/* + * NFv9 Add record definition + */ + +/* + * pad bytes needed to make the structure a multiple of 4 bytes + */ +#define CNAT_NFV9_ADD_RECORD_PAD_BYTES (3) +#define CNAT_NFV9_DEL_RECORD_PAD_BYTES (1) + +#define CNAT_NFV9_NAT64_ADD_BIB_RECORD_PAD_BYTES (3) +#define CNAT_NFV9_NAT64_DEL_BIB_RECORD_PAD_BYTES (1) +#define CNAT_NFV9_NAT64_ADD_SESSION_RECORD_PAD_BYTES (1) +#define CNAT_NFV9_NAT64_DEL_SESSION_RECORD_PAD_BYTES (3) +#define CNAT_NFV9_NAT44_ADD_SESSION_RECORD_PAD_BYTES (1) +#define CNAT_NFV9_NAT44_DEL_SESSION_RECORD_PAD_BYTES (3) + +#define CNAT_NFV9_DS_LITE_ADD_RECORD_PAD_BYTES (3) +#define CNAT_NFV9_DS_LITE_DEL_RECORD_PAD_BYTES (1) +#define CNAT_NFV9_DS_LITE_ADD_SESSION_RECORD_PAD_BYTES (1) +#define CNAT_NFV9_DS_LITE_DEL_SESSION_RECORD_PAD_BYTES (3) + +#define CNAT_NFV9_INGRESS_VRFID_NAME_RECORD_PAD_BYTES (0) + +typedef struct { + u32 inside_vrf_id; + u32 outside_vrf_id; + u32 inside_ip_addr; + u32 outside_ip_addr; + u16 inside_ip_port; + u16 outside_ip_port; + u8 protocol; + u8 pad[CNAT_NFV9_ADD_RECORD_PAD_BYTES]; +} nfv9_add_record_t; + +/* + * NFv9 Delete record definition + */ +typedef struct { + u32 inside_vrf_id; + u32 inside_ip_addr; + u16 inside_ip_port; + u8 protocol; + u8 pad[CNAT_NFV9_DEL_RECORD_PAD_BYTES]; +} nfv9_del_record_t; + +#ifndef NO_BULK_LOGGING + +#define CNAT_NFV9_BULK_ADD_RECORD_PAD_BYTES (0) +#define CNAT_NFV9_BULK_DEL_RECORD_PAD_BYTES (2) + +typedef struct { + u32 inside_vrf_id; + u32 outside_vrf_id; + u32 inside_ip_addr; + u32 outside_ip_addr; + u16 outside_ip_port_start; + u16 outside_ip_port_end; + u8 pad[CNAT_NFV9_BULK_ADD_RECORD_PAD_BYTES]; +} nfv9_bulk_add_record_t; + +/* + * NFv9 Delete record definition + */ +typedef struct { + u32 inside_vrf_id; + u32 inside_ip_addr; + u16 outside_ip_port_start; + u8 pad[CNAT_NFV9_BULK_DEL_RECORD_PAD_BYTES]; +} nfv9_bulk_del_record_t; + +/* + * DS-lite bulk port (user based) add record definition + */ + +#define CNAT_NFV9_DS_LITE_BULK_ADD_RECORD_PAD_BYTES (0) +#define CNAT_NFV9_DS_LITE_BULK_DEL_RECORD_PAD_BYTES (2) + +typedef struct { + u32 inside_vrf_id; + u32 outside_vrf_id; + u32 inside_ip_addr; + u32 inside_v6_src_addr[4]; + u32 outside_ip_addr; + u16 outside_ip_port_start; + u16 outside_ip_port_end; + u8 pad[CNAT_NFV9_DS_LITE_BULK_ADD_RECORD_PAD_BYTES]; +} nfv9_ds_lite_bulk_add_record_t; + + +/* + * DS-lite bulk port (user based) delete record definition + */ + +typedef struct { + u32 inside_vrf_id; + u32 inside_ip_addr; + u32 inside_v6_src_addr[4]; + u16 outside_ip_port_start; + u8 pad[CNAT_NFV9_DS_LITE_BULK_DEL_RECORD_PAD_BYTES]; +} nfv9_ds_lite_bulk_del_record_t; + +#endif /* NO_BULK_LOGGING */ + +/* NAT64 related structures */ + +typedef struct { + u32 inside_v6_src_addr[4]; + u32 outside_v4_src_addr; + u16 inside_src_port; + u16 outside_src_port; + u8 protocol; + u8 pad[CNAT_NFV9_NAT64_ADD_BIB_RECORD_PAD_BYTES]; +} nfv9_nat64_add_bib_record_t; + + +typedef struct { + u32 inside_v6_src_addr[4]; + u32 outside_v4_src_addr; + u32 inside_v6_dest_addr[4]; + u32 outside_v4_dest_addr; + u16 inside_src_port; + u16 outside_src_port; + u16 dest_port; + u8 protocol; + u8 pad[CNAT_NFV9_NAT64_ADD_SESSION_RECORD_PAD_BYTES]; +} nfv9_nat64_add_session_record_t; + + +typedef struct { + u32 inside_v6_src_addr[4]; + u16 inside_src_port; + u8 protocol; + u8 pad[CNAT_NFV9_NAT64_DEL_BIB_RECORD_PAD_BYTES]; +} nfv9_nat64_del_bib_record_t; + + +typedef struct { + u32 inside_v6_src_addr[4]; + u32 inside_v6_dest_addr[4]; + u16 inside_src_port; + u16 dest_port; + u8 protocol; + u8 pad[CNAT_NFV9_NAT64_DEL_SESSION_RECORD_PAD_BYTES]; +} nfv9_nat64_del_session_record_t; + +/* + * NFv9 Session based Add record definition + */ +typedef struct { + u32 inside_vrf_id; + u32 outside_vrf_id; + u32 inside_ip_addr; + u32 outside_ip_addr; + u16 inside_ip_port; + u16 outside_ip_port; + u32 dest_ip_addr; + u16 dest_port; + u8 protocol; + u8 pad[CNAT_NFV9_NAT44_ADD_SESSION_RECORD_PAD_BYTES]; +} nfv9_add_session_record_t; + +/* + * NFv9 Session based del record definition + */ +typedef struct { + u32 inside_vrf_id; + u32 inside_ip_addr; + u32 dest_ip_addr; + u16 inside_ip_port; + u16 dest_port; + u8 protocol; + u8 pad[CNAT_NFV9_NAT44_DEL_SESSION_RECORD_PAD_BYTES]; +} nfv9_del_session_record_t; + +/* + * DS-lite NFv9 create record structure + */ +typedef struct { + u32 inside_vrf_id; + u32 outside_vrf_id; + u32 inside_ip_addr; + u32 inside_v6_src_addr[4]; + u32 outside_ip_addr; + u16 inside_ip_port; + u16 outside_ip_port; + u8 protocol; + u8 pad[CNAT_NFV9_DS_LITE_ADD_RECORD_PAD_BYTES]; +} nfv9_ds_lite_add_record_t; + +typedef struct { + u32 inside_vrf_id; + u32 inside_ip_addr; + u32 inside_v6_src_addr[4]; + u16 inside_ip_port; + u8 protocol; + u8 pad[CNAT_NFV9_DS_LITE_DEL_RECORD_PAD_BYTES]; +} nfv9_ds_lite_del_record_t; + +/* + * NFv9 Session based Add record definition + */ +typedef struct { + u32 inside_vrf_id; + u32 outside_vrf_id; + u32 inside_ip_addr; + u32 inside_v6_src_addr[4]; + u32 outside_ip_addr; + u16 inside_ip_port; + u16 outside_ip_port; + u32 dest_ip_addr; + u16 dest_port; + u8 protocol; + u8 pad[CNAT_NFV9_DS_LITE_ADD_SESSION_RECORD_PAD_BYTES]; +} nfv9_ds_lite_add_session_record_t; + +/* + * NFv9 Session based del record definition + */ +typedef struct { + u32 inside_vrf_id; + u32 inside_ip_addr; + u32 inside_v6_src_addr[4]; + u32 dest_ip_addr; + u16 inside_ip_port; + u16 dest_port; + u8 protocol; + u8 pad[CNAT_NFV9_DS_LITE_DEL_SESSION_RECORD_PAD_BYTES]; +} nfv9_ds_lite_del_session_record_t; + + +typedef struct { + u32 ingress_vrf_id; + u8 ingress_vrf_name[NFV9_VRF_NAME_LEN]; + u8 pad[CNAT_NFV9_INGRESS_VRFID_NAME_RECORD_PAD_BYTES]; +} nfv9_ingress_vrfid_name_record_t; + +#define CNAT_NFV9_TEMPLATE_OFFSET \ + (CNAT_NFV9_HDR_OFFSET + sizeof(nfv9_header_t)) + +#define CNAT_NFV9_TEMPLATE_LENGTH (sizeof(cnat_nfv9_template_t)) +#define CNAT_NFV9_OPTION_TEMPLATE_LENGTH (sizeof(cnat_nfv9_option_template_t)) + +#define CNAT_NFV9_DATAFLOW_RECORD_HEADER_LENGTH \ + (sizeof(nfv9_dataflow_record_header_t)) + +/* + * No padding is needed for the add/delete records - reduce padding bytes + */ + +#define CNAT_NFV9_ADD_RECORD_LENGTH (sizeof(nfv9_add_record_t) - \ + CNAT_NFV9_ADD_RECORD_PAD_BYTES) + +#define CNAT_NFV9_DEL_RECORD_LENGTH (sizeof(nfv9_del_record_t) - \ + CNAT_NFV9_DEL_RECORD_PAD_BYTES) + +#define CNAT_NFV9_DS_LITE_ADD_RECORD_LENGTH (sizeof(nfv9_ds_lite_add_record_t) - \ + CNAT_NFV9_DS_LITE_ADD_RECORD_PAD_BYTES) +#define CNAT_NFV9_DS_LITE_DEL_RECORD_LENGTH (sizeof(nfv9_ds_lite_del_record_t) - \ + CNAT_NFV9_DS_LITE_DEL_RECORD_PAD_BYTES) +#ifndef NO_BULK_LOGGING +#define CNAT_NFV9_BULK_ADD_RECORD_LENGTH (sizeof(nfv9_bulk_add_record_t) - \ + CNAT_NFV9_BULK_ADD_RECORD_PAD_BYTES) +#define CNAT_NFV9_BULK_DEL_RECORD_LENGTH (sizeof(nfv9_bulk_del_record_t) - \ + CNAT_NFV9_BULK_DEL_RECORD_PAD_BYTES) + +#define CNAT_NFV9_DS_LITE_BULK_ADD_RECORD_LENGTH (sizeof(nfv9_ds_lite_bulk_add_record_t) - \ + CNAT_NFV9_DS_LITE_BULK_ADD_RECORD_PAD_BYTES) +#define CNAT_NFV9_DS_LITE_BULK_DEL_RECORD_LENGTH (sizeof(nfv9_ds_lite_bulk_del_record_t) - \ + CNAT_NFV9_DS_LITE_BULK_DEL_RECORD_PAD_BYTES) + + +#endif /* NO_BULK_LOGGING */ + +#define CNAT_NFV9_INGRESS_VRFID_NAME_RECORD_LENGTH (sizeof(nfv9_ingress_vrfid_name_record_t) - \ + CNAT_NFV9_INGRESS_VRFID_NAME_RECORD_PAD_BYTES) + +#define CNAT_NFV9_NAT64_ADD_BIB_RECORD_LENGTH \ + (sizeof(nfv9_nat64_add_bib_record_t) - \ + CNAT_NFV9_NAT64_ADD_BIB_RECORD_PAD_BYTES) + +#define CNAT_NFV9_NAT64_DEL_BIB_RECORD_LENGTH \ + (sizeof(nfv9_nat64_del_bib_record_t) - \ + CNAT_NFV9_NAT64_DEL_BIB_RECORD_PAD_BYTES) + +#define CNAT_NFV9_NAT64_ADD_SESSION_RECORD_LENGTH \ + (sizeof(nfv9_nat64_add_session_record_t) - \ + CNAT_NFV9_NAT64_ADD_SESSION_RECORD_PAD_BYTES) + +#define CNAT_NFV9_NAT64_DEL_SESSION_RECORD_LENGTH \ + (sizeof(nfv9_nat64_del_session_record_t) - \ + CNAT_NFV9_NAT64_DEL_SESSION_RECORD_PAD_BYTES) + +#define CNAT_NFV9_MAX_SINGLE_RECORD_LENGTH \ + (sizeof(nfv9_ds_lite_add_session_record_t) - \ + CNAT_NFV9_DS_LITE_ADD_SESSION_RECORD_PAD_BYTES) + +#define CNAT_NFV9_NAT44_ADD_SESSION_RECORD_LENGTH \ + (sizeof(nfv9_add_session_record_t) -\ + CNAT_NFV9_NAT44_ADD_SESSION_RECORD_PAD_BYTES) + +#define CNAT_NFV9_NAT44_DEL_SESSION_RECORD_LENGTH \ + (sizeof(nfv9_del_session_record_t) -\ + CNAT_NFV9_NAT44_DEL_SESSION_RECORD_PAD_BYTES) + +#define CNAT_NFV9_DS_LITE_ADD_SESSION_RECORD_LENGTH \ + (sizeof(nfv9_ds_lite_add_session_record_t) -\ + CNAT_NFV9_DS_LITE_ADD_SESSION_RECORD_PAD_BYTES) + +#define CNAT_NFV9_DS_LITE_DEL_SESSION_RECORD_LENGTH \ + (sizeof(nfv9_ds_lite_del_session_record_t) -\ + CNAT_NFV9_DS_LITE_DEL_SESSION_RECORD_PAD_BYTES) + +/* + * Minimum value of the path MTU value + */ +#define CNAT_NFV9_MIN_RECORD_SIZE (60 + \ + CNAT_NFV9_DATAFLOW_RECORD_HEADER_LENGTH + \ + CNAT_NFV9_TEMPLATE_LENGTH + \ + CNAT_NFV9_MAX_SINGLE_RECORD_LENGTH) + +/* + * Let us put the maximum length of the netflow data to be 1400 + */ +#define CNAT_NFV9_MAX_PKT_LENGTH 1400 + +/* + * Data structures and defines to store NFV9 specific info + */ +#define CNAT_NFV9_INVALID_LOGGING_INDEX 0xffffffff + +/* + * Padding value between ADD and DELETE records. This can be atmost 3 bytes + */ +#define NFV9_PAD_VALUE (3) + +typedef struct { + /* NFV9 server specific info + * For now, it will maintain only package sequence count. + * Later it will maintain server address, port, etc. + * Though it currently has server address and port, it is only for + * cross refernce + */ + u32 ipv4_address; /* Destination IP address of the collector */ + u16 port; /* Destination port number of the collector */ + u16 refresh_rate; /* Refresh rate in packets after which template is sent */ + u16 timeout_rate; /* Timeout rate in seconds after which template is sent */ + u16 ref_count; /* Num of instances using this data */ + u32 sequence_num; /* Sequence number of the logging packet */ + /* + * Keep track of the time and packets since last template send + */ + u32 last_template_sent_time; + u32 pkts_since_last_template; + u8 template_sent; /* used while sending vrfid-name mapping */ + +} nfv9_server_info_t; + +/* + * This structure store the Netflow Logging information on per NFv9 + * collector basis. This structure is allocated from a pool and index + * to this structure is stored VRF MAP structures + */ +typedef struct { + /* + * nat64_id will be 0 for nat44 config and i_vrf_id, i_vrf will be 0 + * for nat64 config. Nat64_id will be used while nat64 collector is + * search and i_vrf* for nat44 collector + */ + /* Similarly for ds_lite, ds_lite_id will be used and nat64_id, + * ivrf_id shall be set to 0 + */ + u32 i_vrf_id; /* Inside VRF ID corresponding to this collector */ + u16 i_vrf; /* Inside VRF (uidb_index) corresponding to this collector */ + u16 nat64_id; /* NAT64 instance for to this collector */ + u16 ds_lite_id; /* DS Lite instance for this collector */ + + /* + * This field determines the maximum size of the Netflow V9 information + * that can be stored in a logging packet + */ + u16 max_length_minus_max_record_size; + + /* + * Indicates if the entry is already deleted + */ + u16 deleted; + + u16 pkt_length; /* Length of the currently NFv9 information */ + u16 record_length[MAX_RECORDS]; /* Length of delete record */ + u16 total_record_count; /* Total number of records including templates */ + + u8 logging_policy; + + /* + * Keep track of the time and packets since last template send + */ + u32 last_template_sent_time; + u32 pkts_since_last_template; + + /* Server info */ + u32 server_index; + + /* + * current logging context + */ + vlib_buffer_t *current_logging_context; + + /* + * Timestamp in UNIX seconds corresponding to when the current + * logging packet was created + */ + u32 current_logging_context_timestamp; + + /* + * Queued logging context waiting to be sent to the l3 infra node + */ + vlib_buffer_t *queued_logging_context; + + /* + * Headers corresponding to various records in this + * current nfv9 logging context + */ + nfv9_header_t *nfv9_header; + cnat_nfv9_template_t *nfv9_template_header; + nfv9_dataflow_record_header_t *dataflow_header; + u8 *record[MAX_RECORDS]; + u8 *next_data_ptr; + u8 last_record; + u32 nfv9_logging_next_index; + u32 ip4_input_node_index; + vlib_frame_t *f; + u32 *to_next; +} cnat_nfv9_logging_info_t; + + +/* + * Global structure for CGN APP configuration + */ +typedef struct { + /* + * Global NFv9 Logging Collector Index + */ + u32 cnat_nfv9_global_collector_index; + + /* + * Node index corresponding to the infra L3 output node + * to which the nfv9 logging node will send the packet + */ + u16 cnat_nfv9_disp_node_index; + + /* + * Whether we have initialized the NFv9 information + */ + u8 cnat_nfv9_init_done; +} cnat_nfv9_global_info_t; + +typedef enum { + cnat_nfv9_template_add_default, + cnat_nfv9_template_add_always +} cnat_nfv9_template_add_flag_t; + +extern cnat_nfv9_template_t cnat_nfv9_template_info; + +extern cnat_nfv9_logging_info_t cnat_default_nfv9_logging_info; +extern cnat_nfv9_logging_info_t *cnat_nfv9_logging_info_pool; + +extern cnat_nfv9_global_info_t cnat_nfv9_global_info; +extern nfv9_server_info_t *nfv9_server_info_pool; + +/* #define DEBUG_NF_SERVER_CONFIG 1 */ +static inline void nfv9_delete_server_info(cnat_nfv9_logging_info_t *nfv9_info) +{ + nfv9_server_info_t *server = nfv9_server_info_pool + + nfv9_info->server_index; + if(nfv9_info->server_index == EMPTY) { +#ifdef DEBUG_NF_SERVER_CONFIG + if(my_instance_number == 1) { + PLATFORM_DEBUG_PRINT("Deleting empty server info\n"); + } +#endif /* #ifdef DEBUG_NF_SERVER_CONFIG */ + return; + } + + /* Check if this server is not used by anyone.. if not delete */ + /* Caller of this function does not need it..so decrement ref count */ + server->ref_count--; + if(!(server->ref_count)) { +#ifdef DEBUG_NF_SERVER_CONFIG + if(my_instance_number == 1) { + PLATFORM_DEBUG_PRINT("Deleting nfv9 server %x, %d at %d\n", + server->ipv4_address, + server->port, + nfv9_info->server_index); + } +#endif /* #ifdef DEBUG_NF_SERVER_CONFIG */ + pool_put(nfv9_server_info_pool, server); + nfv9_info->server_index = EMPTY; + } +#ifdef DEBUG_NF_SERVER_CONFIG + else { + if(my_instance_number == 1) { + PLATFORM_DEBUG_PRINT("Not Deleting nfv9 server %x, %d rc %d\n", + server->ipv4_address, + server->port, + server->ref_count); + } + } +#endif /* #ifdef DEBUG_NF_SERVER_CONFIG */ + return; +} + +void handle_pending_nfv9_pkts(); +#endif /* __CNAT_LOGGING_H__ */ diff --git a/plugins/vcgn-plugin/vcgn/cnat_pcp_server.h b/plugins/vcgn-plugin/vcgn/cnat_pcp_server.h new file mode 100644 index 00000000..c77c6a87 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_pcp_server.h @@ -0,0 +1,398 @@ +/* + *------------------------------------------------------------------ + * cnat_pcp_server.h + * + * Copyright (c) 2009-2012 Cisco and/or its affiliates. + * 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 __CNAT_PCP_SERVER_H__ +#define __CNAT_PCP_SERVER_H__ + +#include "dslite_defs.h" + +/* Debug utils of PCP */ +#define PCP_DBG(debug, ...) \ + if(PREDICT_FALSE(cnat_pcp_debug_flag >= debug)) { \ + printf("%s:%s:%d - ", \ + __FILE__, __FUNCTION__, __LINE__);\ + printf(__VA_ARGS__);\ + printf("\n"); \ + } + +#define PCP_DUMP_PDATA \ + if(PREDICT_FALSE(cnat_pcp_debug_flag >= 100)) { \ + printf("%s:%s:%d - \n", \ + __FILE__, __FUNCTION__, __LINE__);\ + printf("src - ip = %X, proto = %d, port = %d i_vrf = %d, o_vrf = %d\n", \ + pcp_data.src_ip[3], pcp_data.proto, pcp_data.src_port, pcp_data.i_vrf, pcp_data.o_vrf); \ + printf(" third party ip = %X\n", pcp_data.third_party_ip[3]); \ + printf("map - ip = %X, port = %d \n", \ + pcp_data.ext_ip[3], pcp_data.ext_port);\ + printf("remote - ip = %X, port = %d \n", \ + pcp_data.peer_ip[3], pcp_data.peer_port); \ + printf("req life time = %d \n", pcp_data.req_lifetime); \ + printf("drop = %d \n", pcp_data.drop);\ + printf("udp_len = %d \n", pcp_data.udp_len); \ + printf("pm = %p \n", pcp_data.pm); \ + printf("cnat_proto = %X \n", pcp_data.cnat_proto); \ + printf("inst_id = %X \n", pcp_data.inst_id); \ + printf("======================================================\n"); \ + } + +#define PCP_DUMP_PACKET(ip, len) pcp_hex_dump(ip, len) + +#ifdef TOBE_PORTED +#define PCP_INCR(counter) pcp_counters.pcp_##counter++ ; +#else +#define PCP_INCR(counter) +#endif + +typedef struct pcp_debug_counters { + u64 pcp_input; + u64 pcp_output; + u64 pcp_service_nat44; + u64 pcp_service_dslite; + /* below all are drops */ + u64 pcp_drops; + u64 pcp_i2o_key_inuse; + u64 pcp_throttle_drops; + u64 pcp_udp_len; + u64 pcp_nrequest; + u64 pcp_min_udp_len; + u64 pcp_max_udp_len; + u64 pcp_mod4_len; + u64 pcp_invalid_3rd_len; + u64 pcp_invalid_option; + u64 pcp_version; + u64 pcp_invalid_opcode; + u64 pcp_invalid_client_ip; + u64 pcp_invalid_proto; + u64 pcp_invalid_port; + u64 pcp_invalid_vrfmap; + u64 pcp_invalid_ext_addr; + u64 pcp_out_addr_inuse; + u64 pcp_exact_match; + u64 pcp_exact_entry_created; + u64 pcp_exact_db_alloc_failed; + u64 pcp_udb_mismatch; + u64 pcp_noexact_db_allocated; + u64 pcp_static_entry_present; + u64 pcp_entry_deleted; + u64 pcp_3rd_party_option; + + /* map counters */ + u64 pcp_map_input; + u64 pcp_map_min_len; + u64 pcp_map_max_len; + u64 pcp_map_invalid_option; + u64 pcp_map_invalid_option_len; + u64 pcp_map_pref_fail_option; + u64 pcp_map_invalid_delete_req; + u64 pcp_map_delete_req; + u64 pcp_map_create_req; + u64 pcp_map_refresh; + + /* peer counters */ + u64 pcp_peer_input; + u64 pcp_peer_invalid_len; + u64 pcp_peer_delete_req; + u64 pcp_peer_create_req; + u64 pcp_peer_addr_mistmatch; + u64 pcp_peer_refresh; + +} pcp_debug_counters_t; + +typedef struct { + u16 msg_id; + u8 rc; + u8 pad[5]; + + /* better to have a group structures rather than individual + variables, any change in counters is will automatically + reflect here */ + pcp_debug_counters_t counters; +} pcp_show_counters_resp_t ; + + + +/* PCP opcodes */ +typedef enum pcp_opcode { + PCP_OPCODE_MAP = 1, + PCP_OPCODE_PEER = 2 +}pcp_opcode_t; + + +/* PCP opcodes */ +typedef enum pcp_options { + PCP_OPTION_3RD_PARTY = 1, + PCP_OPTION_PREF_FAIL = 2, + PCP_OPTION_FILTER = 3 +} pcp_options_t; + +/* PCP Result codes */ +typedef enum pcp_result_codes { + PCP_SUCCESS = 0, + PCP_ERR_UNSUPP_VERSION = 1, + PCP_ERR_NOT_AUTHORIZED = 2, + PCP_ERR_MALFORMED_REQUEST = 3, + PCP_ERR_UNSUPP_OPCODE = 4, + PCP_ERR_UNSUPP_OPTION = 5, + PCP_ERR_MALFORMED_OPTION = 6, + PCP_ERR_NETWORK_FAILURE = 7, + PCP_ERR_NO_RESOURCES = 8, + PCP_ERR_UNSUPP_PROTOCOL = 9, + PCP_ERR_USER_EX_QUOTA = 10, + PCP_ERR_CANNOT_PROVIDE_EXTERNAL = 11, + PCP_ERR_ADDRESS_MISMATCH = 12, + PCP_ERR_EXCESSIVE_REMOTE_PEERS = 13 +} pcp_result_codes_t; + +#define PCP_DISABLED 0 +#define PCP_ENABLED 1 + +#define PCP_DROP 1 + +#define PCP_STATIC_LIFETIME 0xFFFFFFFF +#define PCP_MAX_LIFETIME 0x00015180 /* 24 hours = 86400 seconds*/ + +#define PCP_VERSION_SUPPORTED 1 + +#define PCP_NO_PREF_FAIL_OPTION 0 +#define PCP_PREF_FAIL_OPTION 1 + +#define CNAT_DEF_PCP_PORT 5351 + +#define PCP_REQ_RESP_BIT 0x80 +#define PCP_RESPONSE(r_opcode) (r_opcode & PCP_REQ_RESP_BIT) +#define PCP_REQUEST(r_opcode) !(PCP_RESPONSE(r_opcode)) + +#define PCP_REQ_OPCODE(r_opcode) (r_opcode & 0x7F) + +/* 24 bytes */ +#define PCP_COMMON_HDR_LEN sizeof(pcp_request_t) + +/* 8 bytes */ +#define UDP_HDR_LEN sizeof(udp_hdr_type_t) + +#define PCP_PREF_FAIL_OPTION_SIZE \ + sizeof(pcp_prefer_fail_option_t) + +#define PCP_3RD_PARTY_OPTION_SIZE \ + sizeof(pcp_3rd_party_option_t) + +#define PCP_MIN_LEN PCP_COMMON_HDR_LEN + +/* 24+8=32 bytes */ +#define PCP_MIN_UDP_LEN (PCP_MIN_LEN + UDP_HDR_LEN) + +#define PCP_MAX_LEN 1024 + +/* 1024+8 = 1032 bytes */ +#define PCP_MAX_UDP_LEN (PCP_MAX_LEN + UDP_HDR_LEN) + +/* 24+ 24 = 48 bytes */ +#define PCP_MAP_OPCODE_MIN_LEN (PCP_COMMON_HDR_LEN + \ + sizeof( pcp_map_option_specific_data_t)) + +/* 24 + 44 = 68 bytes */ +#define PCP_PEER_OPCODE_MIN_LEN (PCP_COMMON_HDR_LEN + \ + sizeof( pcp_peer_option_specific_data_t)) + +/* 48 + 8 = 56 bytes */ +#define PCP_MAP_OPCODE_MIN_UDP_LEN (PCP_MAP_OPCODE_MIN_LEN + \ + UDP_HDR_LEN ) + +#define PCP_GET_MAP_OPTION_OFFSET(req) \ + ((u8*)req + PCP_MAP_OPCODE_MIN_LEN) + +#define PCP_GET_PEER_OPTION_OFFSET(req) \ + ((u8*)req + PCP_PEER_OPCODE_MIN_LEN) + + +#define PCP_REQ_TOTAL_LEN(udp) (udp->udp_length - \ + UDP_HDR_LEN) +/* 56 + 4 = 60 bytes */ +#define PCP_MAP_OPCODE_PREF_FAIL_OPTION_LEN \ + (PCP_MAP_OPCODE_MIN_UDP_LEN + \ + sizeof(pcp_prefer_fail_option_t)) + + +/* 68 + 8 = 76 bytes */ +#define PCP_PEER_OPCODE_MIN_UDP_LEN (PCP_PEER_OPCODE_MIN_LEN + \ + UDP_HDR_LEN) + +#define PCP_MUST_OPTION(option_code) (option_code & 0x80) + + + +/* 56 + 20 = 76*/ +#define PCP_DSLITE_MAP_OPCODE_MIN_UDP_LEN \ + ( PCP_MAP_OPCODE_MIN_UDP_LEN + \ + PCP_3RD_PARTY_OPTION_SIZE) + +/* 60 + 20 = 80 */ +#define PCP_DSLITE_MAP_OPCODE_MAX_UDP_LEN \ + ( PCP_MAP_OPCODE_PREF_FAIL_OPTION_LEN + \ + PCP_3RD_PARTY_OPTION_SIZE) + +/* 76 + 20 = 96 */ +#define PCP_DSLITE_PEER_OPCODE_MIN_UDP_LEN \ + ( PCP_PEER_OPCODE_MIN_UDP_LEN + \ + PCP_3RD_PARTY_OPTION_SIZE) + + +#define PCP_SET_CNAT_PROTO(proto) \ + pcp_data.cnat_proto = (proto == TCP_PROT) ? CNAT_TCP: \ + (proto == UDP_PROT)? CNAT_UDP : CNAT_ICMP; + +#define PCP_SET_REQ_LIFETIME() \ + if(pcp_data.db->flags & CNAT_DB_FLAG_STATIC_PORT) { \ + pcp_data.db->proto_data.seq_pcp.pcp_lifetime = \ + PCP_STATIC_LIFETIME; \ + pcp_data.req_lifetime = PCP_STATIC_LIFETIME; \ + } else { \ + pcp_data.db->proto_data.seq_pcp.pcp_lifetime = \ + pcp_data.req_lifetime + cnat_current_time ; \ + } + + +/* per second not more than PCP_THROTTLE_LIMIT + * delete requests will be handled. + * this excludes , specific entries, in which + * only one entry needs to be deleted + */ +#define PCP_THROTTLE_LIMIT 2 + +typedef struct pcp_request { + u8 ver; + u8 r_opcode; + u16 reserved; + u32 req_lifetime; + u32 ip[4]; /* ipv4 will be represented + by the ipv4 mapped ipv6 */ +} pcp_request_t; + +typedef struct pcp_response { + u8 ver; + u8 r_opcode; + u8 reserved; + u8 result_code; + u32 lifetime; + u32 epochtime; + u32 reserved1[3]; +} pcp_response_t; + + +typedef struct pcp_options_hdr { + u8 code; + u8 reserved; + u16 len; + u8 data[0]; +} pcp_options_hdr_t; + + +/* same for both request and response */ +typedef struct pcp_map_option_specific_data { + u8 protocol; + u8 reserved[3]; + u16 int_port; + u16 ext_port; + u32 ext_ip[4]; /* ipv4 will be represnted + by the ipv4 mapped ipv6 */ +} pcp_map_option_specific_data_t; + +/* same for both request and response */ +typedef struct pcp_peer_option_specific_data { + u8 protocol; + u8 reserved[3]; + u16 int_port; + u16 ext_port; + u32 ext_ip[4]; /* ipv4 will be represented + by the ipv4 mapped ipv6 */ + u16 peer_port; + u16 reserved1; + u32 peer_ip[4]; +} pcp_peer_option_specific_data_t; + +typedef struct pcp_prefer_fail_option { + u8 option; + u8 reserved; + u16 len; +} pcp_prefer_fail_option_t; + + +typedef struct pcp_3rd_party_option{ + u8 option; + u8 reserved; + u16 len; + u32 ip[4]; +} pcp_3rd_party_option_t; + +/* structure used as pipeline data */ + +typedef struct pcp_pipeline_data { + + union { + + u8 *p; + ipv4_header *ip ; + ipv6_header_t *ipv6 ; + + } l3addr; + + udp_hdr_type_t *udp; + pcp_request_t *req; + pcp_response_t *resp; + pcp_opcode_t opcode; + u32 src_ip[4]; + u16 src_port; + u8 proto; + u16 i_vrf; + u16 o_vrf; + u32 ext_ip[4]; + u16 ext_port; + u32 third_party_ip[4]; + + /* valid for peer opcode */ + u32 peer_ip[4]; + u32 peer_port; + u32 req_lifetime; + u32 udp_len; + pcp_options_t pref_fail; + pcp_options_t third_party; + u8 *option_spec; + pcp_result_codes_t ret_code; + cnat_portmap_v2_t *pm; + cnat_main_db_entry_t *db; + cnat_vrfmap_t *vrfmap; + dslite_table_entry_t *inst_ptr; + u16 inst_id; + u32 flags; + u16 cnat_proto; + + /* is packet needs to be dropped ? */ + u8 drop; + /* nat44, dslite, nat64 */ +#define PCP_SERVICE_NAT44 1 +#define PCP_SERVICE_DSLITE 2 +#define PCP_SERVICE_NAT64 3 + u8 service_type; + +#define PCP_REQ_ENTRY_PRESENT 1 +#define PCP_REQ_EXT_MAP_PRESENT 1 + u8 state; +} pcp_pipeline_data_t; + +#endif /* __CNAT_PCP_sERVER_H__ */ diff --git a/plugins/vcgn-plugin/vcgn/cnat_ports.c b/plugins/vcgn-plugin/vcgn/cnat_ports.c new file mode 100644 index 00000000..943fb3ed --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_ports.c @@ -0,0 +1,1113 @@ +/* + *------------------------------------------------------------------ + * cnat_ports.c - port allocator + * + * Copyright (c) 2008-2014 Cisco and/or its affiliates. + * 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 +#include +#include +#include +#include +#include +#include + +#include "cnat_db.h" +#include "cnat_config.h" +#include "cnat_global.h" +#include "cnat_logging.h" +#include "spp_timers.h" +#include "platform_common.h" +#include "cgn_bitmap.h" +#include "spp_platform_trace_log.h" +#include "cnat_ports.h" + +#if 1 /* TOBE_PORTED */ +/* Following is defined elsewhere. */ +#define msg_spp_err(s) \ +do { \ + fprintf(stderr,(i8 *)s); \ + fputs("\n", stderr); \ +} while(0); +#endif + + +#define PM_90_PERCENT_USE 58980 +/* + * instance number provisioned from HW + */ +u8 my_instance_number = 0; + +typedef struct { + u32 cached_next_index; + /* $$$$ add data here */ + + /* convenience variables */ + vlib_main_t * vlib_main; + vnet_main_t * vnet_main; +} cnat_ports_main_t; + +cnat_ports_main_t cnat_ports_main; + +static u32 rseed_port; /* random number generator seed */ + +void +cnat_db_dump_portmap_for_vrf (u32 vrfmap_index) +{ + u32 i, pm_len; + cnat_vrfmap_t *my_vrfmap = cnat_map_by_vrf + vrfmap_index; + cnat_portmap_v2_t *pm, *my_pm __attribute__((unused)); + + pm = my_vrfmap->portmap_list; + pm_len = vec_len(pm); + + for (i = 0; i < pm_len; i++) { + my_pm = pm + i; + + PLATFORM_DEBUG_PRINT("pm %d: IPv4 Addr 0x%x - in use %d private_ip_users_count %d\n", + i, my_pm->ipv4_address, my_pm->inuse, + my_pm->private_ip_users_count); + + PLATFORM_DEBUG_PRINT("pm %d: IPv4 Addr 0x%x - in use %d " + "private_ip_users_count %d\n", + i, my_pm->ipv4_address, my_pm->inuse, + my_pm->private_ip_users_count); + } +} + +void +cnat_db_dump_portmaps () +{ + u32 i, vrfmap_index; + + for (i = 0; i < CNAT_MAX_VRFMAP_ENTRIES; i++) { + vrfmap_index = vrf_map_array[i]; + + if (vrfmap_index == VRF_MAP_ENTRY_EMPTY) { + continue; + } + + PLATFORM_DEBUG_PRINT("\n\nDumping the port map for uidb_index %d\n", i); + cnat_db_dump_portmap_for_vrf(vrfmap_index); + } +} + +#ifndef NO_BULK_LOGGING +static int check_if_stat_alloc_ok_for_bulk(cnat_portmap_v2_t *pm, + u16 i_port, bulk_alloc_size_t bulk_size, + u16 static_port_range) +{ + uword bit_test_result; + if(BULK_ALLOC_SIZE_NONE == bulk_size) return 1; /* No issues */ + + if(i_port < static_port_range) return 1; /* we don't want bulk */ + + i_port = (i_port/bulk_size) * bulk_size; + bit_test_result = cgn_clib_bitmap_check_if_all(pm->bm, i_port, bulk_size); + return(bit_test_result); +} +#else /* dummy */ +inline static int check_if_stat_alloc_ok_for_bulk(cnat_portmap_v2_t *pm, + u16 i_port, bulk_alloc_size_t bulk_size, + u16 static_port_range) +{ + return 1; +} +#endif /* NO_BULK_LOGGING */ +/* + * cnat_port_alloc_static_v2 + * public ipv4 address/port allocator for Static Port commands + * tries to allocate same outside port as inside port + */ +cnat_errno_t +cnat_static_port_alloc_v2 ( + cnat_portmap_v2_t *pm, + port_alloc_t atype, + port_pair_t pair_type, + u32 i_ipv4_address, + u16 i_port, + u32 *index, + u32 *o_ipv4_address, + u16 *o_port, + u16 static_port_range +#ifndef NO_BULK_LOGGING + , bulk_alloc_size_t bulk_size, + int *nfv9_log_req +#endif + , u16 ip_n_to_1 + ) +{ + u32 i, hash_value, my_index, found, max_attempts; + u16 start_bit, new_port; + cnat_portmap_v2_t *my_pm = 0; + u32 pm_len = vec_len(pm); + uword bit_test_result; + +#ifndef NO_BULK_LOGGING + *nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED; +#endif + + if (PREDICT_FALSE(pm_len == 0)) { + return (CNAT_NO_POOL_ANY); + } + + switch (atype) { + + case PORT_ALLOC_ANY: + + found = 0; + + /* + * Try to hash the IPv4 address to get an index value to select the pm + */ + hash_value = (i_ipv4_address & 0xffff) ^ + ((i_ipv4_address > 16) & 0xffff); + + /* + * If pm_len <= 256, compact the hash to 8 bits + */ + if (PREDICT_TRUE(pm_len <= 256)) { + hash_value = (hash_value & 0xff) ^ ((hash_value > 8) & 0xff); + } + + /* + * Ensure that the hash value is in the range 0 .. (pm_len-1) + */ + my_index = hash_value % pm_len; + + for (i = 0; i < PORT_PROBE_LIMIT; i++) { + my_pm = pm + my_index; + if(PREDICT_TRUE(ip_n_to_1)) { + if(PREDICT_TRUE(my_pm->private_ip_users_count < ip_n_to_1)) { + /* + * Try to find a PM with atlest 33% free and my_port free + */ + if (PREDICT_TRUE((my_pm->inuse < ((BITS_PER_INST*2)/3)) && + clib_bitmap_get_no_check(my_pm->bm, + i_port) == 1) +#ifndef NO_BULK_LOGGING + && check_if_stat_alloc_ok_for_bulk(my_pm, i_port, + bulk_size, + static_port_range) +#endif + ) { + found = 1; + break; + } + } + + } else { + /* + * Try to find a PM with atlest 33% free and my_port free + */ + if (PREDICT_TRUE((my_pm->inuse < ((BITS_PER_INST*2)/3)) && + clib_bitmap_get_no_check(my_pm->bm, + i_port) == 1) +#ifndef NO_BULK_LOGGING + && check_if_stat_alloc_ok_for_bulk(my_pm, i_port, + bulk_size, + static_port_range) +#endif + ) { + found = 1; + break; + } + } + my_index = (my_index + 1) % pm_len; + } + + /* + * If not found do it the hard way . + * "hard" way, best-fit. + */ + if (!found) { + u32 min_inuse_any, min_inuse_myport; + u32 min_index_any, min_index_myport; + + min_inuse_any = min_inuse_myport = PORTS_PER_ADDR + 1; + min_index_any = min_index_myport = ~0; + for (i = 0; i < pm_len; i++) { + my_pm = pm + i; + if(PREDICT_TRUE(ip_n_to_1)) { + if(PREDICT_TRUE(my_pm->private_ip_users_count < ip_n_to_1)) { + if (PREDICT_FALSE(my_pm->inuse < min_inuse_any)) { + min_inuse_any = my_pm->inuse; + min_index_any = my_pm - pm; + } + if (PREDICT_FALSE(my_pm->inuse < min_inuse_myport)) { + if (PREDICT_TRUE(clib_bitmap_get_no_check( + my_pm->bm,i_port) == 1) +#ifndef NO_BULK_LOGGING + && check_if_stat_alloc_ok_for_bulk(my_pm, + i_port,bulk_size,static_port_range) +#endif + ) { + min_inuse_myport = my_pm->inuse; + min_index_myport = my_pm - pm; + } + } + + } + + } else { + if (PREDICT_FALSE(my_pm->inuse < min_inuse_any)) { + min_inuse_any = my_pm->inuse; + min_index_any = my_pm - pm; + } + if (PREDICT_FALSE(my_pm->inuse < min_inuse_myport)) { + if (PREDICT_TRUE(clib_bitmap_get_no_check( + my_pm->bm, i_port) == 1) +#ifndef NO_BULK_LOGGING + && check_if_stat_alloc_ok_for_bulk(my_pm, i_port, + bulk_size, static_port_range) +#endif + ) { + min_inuse_myport = my_pm->inuse; + min_index_myport = my_pm - pm; + } + } + } + } + + /* + * Check if we have an exactly matching PM that has + * myport free. If so use it. If no such PM is + * available, use any PM + */ + if (PREDICT_TRUE(min_inuse_myport < PORTS_PER_ADDR)) { + my_pm = pm + min_index_myport; + my_index = min_index_myport; + found = 1; + } else if (PREDICT_TRUE(min_inuse_any < PORTS_PER_ADDR)) { + my_pm = pm + min_index_any; + my_index = min_index_any; + found = 1; + } + } + + if (!found) { + return (CNAT_NO_PORT_ANY); + } + break; + + case PORT_ALLOC_DIRECTED: + my_index = *index; + if (PREDICT_FALSE(my_index > pm_len)) { + return (CNAT_INV_PORT_DIRECT); + } + my_pm = pm + my_index; + break; + + default: + return (CNAT_ERR_PARSER); + } + + /* Allocate a matching port if possible */ + start_bit = i_port; + found = 0; + max_attempts = BITS_PER_INST; +#ifndef NO_BULK_LOGGING + if((BULK_ALLOC_SIZE_NONE != bulk_size) && + (i_port >= static_port_range)) { + start_bit = (start_bit/bulk_size) * bulk_size; + max_attempts = BITS_PER_INST/bulk_size; + } +#endif /* NO_BULK_LOGGING */ + + for (i = 0; i < max_attempts; i++) { +#ifndef NO_BULK_LOGGING + if((BULK_ALLOC_SIZE_NONE != bulk_size) && + (i_port >= static_port_range)) { + bit_test_result = cgn_clib_bitmap_check_if_all(my_pm->bm, + start_bit, bulk_size); + } + else +#endif /* #ifndef NO_BULK_LOGGING */ + bit_test_result = clib_bitmap_get_no_check(my_pm->bm, start_bit); + + if (PREDICT_TRUE(bit_test_result)) { +#ifndef NO_BULK_LOGGING + if((BULK_ALLOC_SIZE_NONE != bulk_size) && + (i_port >= static_port_range)) { + *nfv9_log_req = start_bit; + if(i==0) new_port = i_port; /* First go */ + else { + new_port = bit2port(start_bit); + if (pair_type == PORT_S_ODD && (new_port & 0x1) == 0) + new_port++; + } + found = 1; + break; + } + else { +#endif /* NO_BULK_LOGGING */ + new_port = bit2port(start_bit); + if (pair_type == PORT_S_ODD) { + if ((new_port & 0x1) == 1) { + found = 1; + break; + } + } else if (pair_type == PORT_S_EVEN) { + if ((new_port & 0x1) == 0) { + found = 1; + break; + } + } else { + found = 1; + break; + } +#ifndef NO_BULK_LOGGING + } +#endif + } +#ifndef NO_BULK_LOGGING + if((BULK_ALLOC_SIZE_NONE != bulk_size) && + (i_port >= static_port_range)) + start_bit = (start_bit + bulk_size) % BITS_PER_INST; + else { +#endif /* NO_BULK_LOGGING */ + start_bit = (start_bit + 1) % BITS_PER_INST; + if(PREDICT_FALSE(start_bit == 0)) { + start_bit = 1; /* Port 0 is invalid, so start from 1 */ + } +#ifndef NO_BULK_LOGGING + } +#endif + } /* End of for loop */ + + if (!found) { + /* Port allocation failure */ + if (atype == PORT_ALLOC_DIRECTED) { + return (CNAT_NOT_FOUND_DIRECT); + } else { + return (CNAT_NOT_FOUND_ANY); + } + } + + /* Accounting */ + cgn_clib_bitmap_clear_no_check(my_pm->bm, new_port); + (my_pm->inuse)++; + + *index = my_pm - pm; + *o_ipv4_address = my_pm->ipv4_address; + + *o_port = new_port; + + return (CNAT_SUCCESS); +} + +/* + * Try to allocate a portmap structure based on atype field + */ +cnat_portmap_v2_t * +cnat_dynamic_addr_alloc_from_pm ( + cnat_portmap_v2_t *pm, + port_alloc_t atype, + u32 *index, + cnat_errno_t *err, + u16 ip_n_to_1, + u32 *rseed_ip) +{ + u32 i, pm_len; + int my_index; + int min_inuse, min_index; + + cnat_portmap_v2_t *my_pm = 0; + *err = CNAT_NO_POOL_ANY; + + pm_len = vec_len(pm); + + switch(atype) { + case PORT_ALLOC_ANY: + if (PREDICT_FALSE(pm_len == 0)) { + my_pm = 0; + *err = CNAT_NO_POOL_ANY; + goto done; + } + + /* "Easy" way, first address with at least 200 free ports */ + for (i = 0; i < PORT_PROBE_LIMIT; i++) { + *rseed_ip = randq1(*rseed_ip); + my_index = (*rseed_ip) % pm_len; + my_pm = pm + my_index; + if (PREDICT_FALSE(ip_n_to_1)) { + if(PREDICT_TRUE(ip_n_to_1 == 1)) { + if (PREDICT_FALSE(0 == my_pm->inuse)) { + goto done; + } + } else { + if(PREDICT_TRUE(my_pm->private_ip_users_count < ip_n_to_1)) { + if (PREDICT_FALSE(my_pm->inuse < ((BITS_PER_INST*2)/3))) { + goto done; + } + } + } + } else { + if (PREDICT_FALSE(my_pm->inuse < ((BITS_PER_INST*2)/3))) { + goto done; + } + } + } + + /* "hard" way, best-fit. $$$$ Throttle complaint */ + min_inuse = PORTS_PER_ADDR + 1; + min_index = ~0; + for (i = 0; i < pm_len; i++) { + my_pm = pm + i; + if (PREDICT_FALSE(ip_n_to_1)) { + if(PREDICT_TRUE(ip_n_to_1 == 1)) { + if (PREDICT_FALSE(!my_pm->inuse)) { + min_inuse = my_pm->inuse; + min_index = my_pm - pm; + } + } else { + if(PREDICT_TRUE(my_pm->private_ip_users_count < ip_n_to_1)) { + if (PREDICT_TRUE(my_pm->inuse < min_inuse)) { + min_inuse = my_pm->inuse; + min_index = my_pm - pm; + } + + } + } + + } else { + if (PREDICT_TRUE(my_pm->inuse < min_inuse)) { + min_inuse = my_pm->inuse; + min_index = my_pm - pm; + } + } + } + + if (PREDICT_TRUE(min_inuse < PORTS_PER_ADDR)) { + my_pm = pm + min_index; + my_index = min_index; + goto done; + } + + /* Completely out of ports */ +#ifdef DEBUG_PRINTF_ENABLED + PLATFORM_DEBUG_PRINT("%s out of ports\n", __FUNCTION__); +#endif + + my_pm = 0; + *err = CNAT_NO_PORT_ANY; + break; + + + case PORT_ALLOC_DIRECTED: + //ASSERT(*index < pm_len); + if (PREDICT_FALSE(*index > pm_len)) { + my_pm = 0; + *err = CNAT_INV_PORT_DIRECT; + goto done; + } + my_pm = pm + *index; + my_index = *index; + break; + + default: + msg_spp_err("bad allocation type in cnat_port_alloc"); + my_pm = 0; + *err = CNAT_ERR_PARSER; + break; + } + + done: + if (PREDICT_FALSE(my_pm == NULL)) { + return (my_pm); + } + + if (PREDICT_FALSE(my_pm->inuse >= BITS_PER_INST)) { + my_pm = 0; + if (atype == PORT_ALLOC_DIRECTED) { + *err = CNAT_BAD_INUSE_DIRECT; + } else { + *err = CNAT_BAD_INUSE_ANY; + } + } + + return (my_pm); +} + + +/* + * cnat_port_alloc_v2 + * public ipv4 address/port allocator for dynamic ports + * + * 200K users / 20M translations means vec_len(cnat_portmap) will be + * around 300. + * + */ +cnat_errno_t +cnat_dynamic_port_alloc_v2 ( + cnat_portmap_v2_t *pm, + port_alloc_t atype, + port_pair_t pair_type, + u32 *index, + u32 *o_ipv4_address, + u16 *o_port, + u16 static_port_range +#ifndef NO_BULK_LOGGING + , bulk_alloc_size_t bulk_size, + int *nfv9_log_req +#endif + , u16 ip_n_to_1, + u32 *rseed_ip + ) +{ + int i; + cnat_errno_t my_err = CNAT_NO_POOL_ANY; + cnat_portmap_v2_t *my_pm = 0; + u16 start_bit; + u16 new_port; + uword bit_test_result; + uword max_trys_to_find_port; + + ASSERT(index); + ASSERT(o_ipv4_address); + ASSERT(o_port); + + my_pm = cnat_dynamic_addr_alloc_from_pm(pm, atype, index, &my_err, ip_n_to_1, + rseed_ip); + + if (PREDICT_FALSE(my_pm == NULL)) { + return (my_err); + } + if(PREDICT_FALSE(my_pm->dyn_full == 1)) { + if (atype == PORT_ALLOC_DIRECTED) { + return (CNAT_NOT_FOUND_DIRECT); + } else { + return (CNAT_NOT_FOUND_ANY); + } + } + +#if DEBUG > 1 + PLATFORM_DEBUG_PRINT("ALLOC_PORT_V2: My_Instance_Number %d: IP addr 0x%x, Inuse %d\n", + my_instance_number, my_pm->ipv4_address, my_pm->inuse); +#endif + + rseed_port = randq1(rseed_port); + + /* + * Exclude the static port range for allocating dynamic ports + */ + start_bit = (rseed_port) % (BITS_PER_INST - static_port_range); + start_bit = start_bit + static_port_range; + +#ifndef NO_BULK_LOGGING + *nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED; + if(BULK_ALLOC_SIZE_NONE != bulk_size) + { + /* We need the start port of the range to be alined on integer multiple + * of bulk_size */ + max_trys_to_find_port = BITS_PER_INST/bulk_size; + start_bit= ((start_bit + bulk_size -1)/bulk_size) * bulk_size; + } + else +#endif /* #ifndef NO_BULK_LOGGING */ + max_trys_to_find_port = BITS_PER_INST; + + /* Allocate a random port / port-pair */ + for (i = 0; i < max_trys_to_find_port; i++) { + + /* start_bit is only a u16.. so it can rollover and become zero */ + if (PREDICT_FALSE( /* (start_bit >= BITS_PER_INST) || FIXME u16 cannot be >= 65536 */ + (start_bit < static_port_range))) { + start_bit = static_port_range; +#ifndef NO_BULK_LOGGING + if(BULK_ALLOC_SIZE_NONE != bulk_size) { + start_bit= ((start_bit + bulk_size -1)/bulk_size) * bulk_size; + } +#endif /* #ifndef NO_BULK_LOGGING */ + } + /* Scan forward from random position */ +#ifndef NO_BULK_LOGGING + if(BULK_ALLOC_SIZE_NONE != bulk_size) { + bit_test_result = cgn_clib_bitmap_check_if_all(my_pm->bm, + start_bit, bulk_size); + } + else +#endif /* #ifndef NO_BULK_LOGGING */ + bit_test_result = clib_bitmap_get_no_check(my_pm->bm, start_bit); + + if (PREDICT_TRUE(bit_test_result)) { + new_port = bit2port(start_bit); +#ifndef NO_BULK_LOGGING + if(BULK_ALLOC_SIZE_NONE != bulk_size) + *nfv9_log_req = new_port; +#endif + if ((pair_type == PORT_S_ODD) && + (!(new_port & 0x1))) { +#ifndef NO_BULK_LOGGING + if(BULK_ALLOC_SIZE_NONE != bulk_size) { + start_bit++; /* Just use the next one in the bulk range */ + new_port++; + goto found2; + } +#endif /* #ifndef NO_BULK_LOGGING */ + goto notfound; + } else if ((pair_type == PORT_S_EVEN) && + (new_port & 0x1)) { + goto notfound; + } + + /* OK we got one or two suitable ports */ + goto found2; + } + + notfound: +#ifndef NO_BULK_LOGGING + if(BULK_ALLOC_SIZE_NONE != bulk_size) + start_bit += bulk_size; + else +#endif /* #ifndef NO_BULK_LOGGING */ + start_bit++; + + } /* end of for loop */ + + /* Completely out of ports */ + + /* Port allocation failure */ + /* set dyn_full flag. This would be used to verify + * for further dyn session before searching for port + */ + if (atype == PORT_ALLOC_DIRECTED) { + my_pm->dyn_full = 1; + return (CNAT_NOT_FOUND_DIRECT); + } else { + my_pm->dyn_full = 1; + return (CNAT_NOT_FOUND_ANY); + } + + + found2: + + /* Accounting */ + cgn_clib_bitmap_clear_no_check (my_pm->bm, start_bit); + (my_pm->inuse)++; + + *index = my_pm - pm; + *o_ipv4_address = my_pm->ipv4_address; + + *o_port = new_port; + return (CNAT_SUCCESS); +} + +#ifdef TOBE_PORTED +/* + * cnat_alloc_port_from_pm + * Given a portmap structure find port/port_pair that are free + * + * The assumption in this function is that bit in bm corresponds + * to a port number. This is TRUE and hence there is no call + * to the function bit2port here, though it is done in other + * places in this file. + * + */ +static u32 +cnat_alloc_port_from_pm ( + u32 start_port, + u32 end_port, + cnat_portmap_v2_t *my_pm, + port_pair_t pair_type +#ifndef NO_BULK_LOGGING + , bulk_alloc_size_t bulk_size, + int *nfv9_log_req +#endif /* #ifnded NO_BULK_ALLOCATION */ + ) +{ + u32 i; + u32 start_bit; + u32 total_ports = end_port - start_port + 1; + uword bit_test_result; + uword max_trys_to_find_port; + + rseed_port = randq1(rseed_port); + + start_bit = rseed_port % total_ports; + start_bit = start_bit + start_port; +#ifndef NO_BULK_LOGGING + *nfv9_log_req = BULK_ALLOC_NOT_ATTEMPTED; + if(BULK_ALLOC_SIZE_NONE != bulk_size) + { + /* We need the start port of the range to be alined on integer multiple + * of bulk_size */ + max_trys_to_find_port = total_ports/bulk_size; + start_bit= ((start_bit + bulk_size -1)/bulk_size) * bulk_size; + } + else +#endif /* #ifndef NO_BULK_LOGGING */ + max_trys_to_find_port = total_ports; + + /* Allocate a random port / port-pair */ + for (i = 0; i < max_trys_to_find_port; i++) { + /* start_bit is only a u16.. so it can rollover and become zero */ + if (PREDICT_FALSE((start_bit >= end_port) || + (start_bit < start_port))) { + start_bit = start_port; +#ifndef NO_BULK_LOGGING + if(BULK_ALLOC_SIZE_NONE != bulk_size) { + start_bit= ((start_bit + bulk_size -1)/bulk_size) * bulk_size; + } +#endif /* #ifndef NO_BULK_LOGGING */ + } + + /* Scan forward from random position */ +#ifndef NO_BULK_LOGGING + if(BULK_ALLOC_SIZE_NONE != bulk_size) { + bit_test_result = cgn_clib_bitmap_check_if_all(my_pm->bm, + start_bit, bulk_size); + } + else +#endif /* #ifndef NO_BULK_LOGGING */ + bit_test_result = clib_bitmap_get_no_check(my_pm->bm, start_bit); + + if (PREDICT_TRUE(bit_test_result)) { +#ifndef NO_BULK_LOGGING + if(BULK_ALLOC_SIZE_NONE != bulk_size) { + /* Got the entire bulk range */ + *nfv9_log_req = bit2port(start_bit); + return start_bit; + } else { +#endif /* #ifndef NO_BULK_LOGGING */ + /* + * For PORT_PAIR, first port has to be Even + * subsequent port <= end_port + * subsequent port should be unallocated + */ + if ((start_bit & 0x1) || + ((start_bit + 1) > end_port) || + (clib_bitmap_get_no_check(my_pm->bm, + (start_bit + 1)) == 0)) { + goto notfound; + } + return (start_bit); +#ifndef NO_BULK_LOGGING + } +#endif /* #ifndef NO_BULK_LOGGING */ + } /* if( free port found ) */ + +notfound: +#ifndef NO_BULK_LOGGING + if(BULK_ALLOC_SIZE_NONE != bulk_size) { + start_bit += bulk_size; + } else +#endif /* #ifndef NO_BULK_LOGGING */ + start_bit++; + + } + return (BITS_PER_INST); +} + +/* + * cnat_dynamic_port_alloc_rtsp + * public ipv4 address/port allocator for dynamic ports + * + * 200K users / 20M translations means vec_len(cnat_portmap) will be + * around 300. + * + */ + +cnat_errno_t +cnat_dynamic_port_alloc_rtsp ( + cnat_portmap_v2_t *pm, + port_alloc_t atype, + port_pair_t pair_type, + u16 start_range, + u16 end_range, + u32 *index, + u32 *o_ipv4_address, + u16 *o_port +#ifndef NO_BULK_LOGGING + , bulk_alloc_size_t bulk_size, + int *nfv9_log_req +#endif + , u32 *rseed_ip + ) +{ + + u32 current_timestamp; + cnat_errno_t my_err = CNAT_NO_POOL_ANY; + cnat_portmap_v2_t *my_pm = 0; + u32 alloc_bit; + + ASSERT(index); + ASSERT(o_ipv4_address); + ASSERT(o_port); + + my_pm = cnat_dynamic_addr_alloc_from_pm(pm, atype, index, &my_err, 0,rseed_ip); + + if (PREDICT_FALSE(my_pm == NULL)) { + return (my_err); + } + +#if DEBUG > 1 + PLATFORM_DEBUG_PRINT("ALLOC_PORT_V2: My_Instance_Number %d: IP addr 0x%x, Inuse %d\n", + my_instance_number, my_pm->ipv4_address, my_pm->inuse); +#endif + + alloc_bit = + cnat_alloc_port_from_pm(start_range, end_range, my_pm, pair_type +#ifndef NO_BULK_LOGGING + , bulk_size, nfv9_log_req +#endif /* #ifndef NO_BULK_LOGGING */ + ); + + if (alloc_bit < BITS_PER_INST) { + if (pair_type == PORT_PAIR) { + /* Accounting */ + cgn_clib_bitmap_clear_no_check (my_pm->bm, alloc_bit); + cgn_clib_bitmap_clear_no_check (my_pm->bm, alloc_bit+1); + (my_pm->inuse) += 2; + } else { + /* Accounting */ + cgn_clib_bitmap_clear_no_check (my_pm->bm, alloc_bit); + (my_pm->inuse)++; + } + + *index = my_pm - pm; + *o_ipv4_address = my_pm->ipv4_address; + + *o_port = bit2port(alloc_bit);; + + return (CNAT_SUCCESS); + } + + /* Completely out of ports */ + current_timestamp = spp_trace_log_get_unix_time_in_seconds(); + if (PREDICT_FALSE((current_timestamp - my_pm->last_sent_timestamp) > + 1000)) { + spp_printf(CNAT_NO_EXT_PORT_AVAILABLE, 0, NULL); + my_pm->last_sent_timestamp = current_timestamp; + } + + + /* Port allocation failure */ + if (atype == PORT_ALLOC_DIRECTED) { + return (CNAT_NOT_FOUND_DIRECT); + } else { + return (CNAT_NOT_FOUND_ANY); + } +} +#else +cnat_errno_t +cnat_dynamic_port_alloc_rtsp ( + cnat_portmap_v2_t *pm, + port_alloc_t atype, + port_pair_t pair_type, + u16 start_range, + u16 end_range, + u32 *index, + u32 *o_ipv4_address, + u16 *o_port +#ifndef NO_BULK_LOGGING + , bulk_alloc_size_t bulk_size, + int *nfv9_log_req +#endif + , u32 *rseed_ip + ) +{ + return (CNAT_NOT_FOUND_ANY); +} +#endif + + +/* + * cnat_mapped_static_port_alloc_v2 + * / + */ +cnat_errno_t +cnat_mapped_static_port_alloc_v2 ( + cnat_portmap_v2_t *pm, + port_alloc_t atype, + u32 *index, + u32 ipv4_address, + u16 port +#ifndef NO_BULK_LOGGING + , int *nfv9_log_req, + bulk_alloc_size_t bulk_size +#endif + , u16 ip_n_to_1 + ) +{ + int i; + u32 pm_len; + u16 bm_bit; + cnat_portmap_v2_t *my_pm = 0; + u32 my_index; + + ASSERT(index); + + /* + * Map the port to the bit in the pm bitmap structure. + * Note that we use ports from 1024..65535, so + * port number x corresponds to (x-1024) position in bitmap + */ + bm_bit = port2bit(port); + + pm_len = vec_len(pm); + + switch(atype) { + case PORT_ALLOC_ANY: + if (PREDICT_FALSE(pm_len == 0)) { + return (CNAT_NO_POOL_ANY); + } + + /* + * Find the pm that is allocated for this translated IP address + */ + my_index = pm_len; + + for (i = 0; i < pm_len; i++) { + my_pm = pm + i; + if (PREDICT_FALSE(my_pm->ipv4_address == ipv4_address)) { + my_index = i; + break; + } + } + + if ((PREDICT_FALSE(my_index >= pm_len)) || + ((PREDICT_FALSE(ip_n_to_1)) && (PREDICT_TRUE(my_pm->private_ip_users_count >= ip_n_to_1)))) { + return (CNAT_NO_POOL_ANY); + } + + break; + + case PORT_ALLOC_DIRECTED: + if (PREDICT_FALSE(*index > pm_len)) { + return (CNAT_INV_PORT_DIRECT); + } + + my_index = *index; + my_pm = pm + my_index; + if (PREDICT_FALSE(my_pm->ipv4_address != ipv4_address)) { + if (PREDICT_FALSE(global_debug_flag && CNAT_DEBUG_GLOBAL_ALL)) { + PLATFORM_DEBUG_PRINT("Delete all main db entry for that particular in ipv4 address\n"); + } + return (CNAT_INV_PORT_DIRECT); + } + + break; + + default: + msg_spp_err("bad allocation type in cnat_port_alloc"); + return (CNAT_ERR_PARSER); + } + + + if (PREDICT_FALSE(my_pm == NULL)) { + return (CNAT_NO_POOL_ANY); + } + + /* + * Check if the port is already allocated to some other mapping + */ + if (PREDICT_FALSE(clib_bitmap_get_no_check (my_pm->bm, bm_bit) == 0)) { + return (CNAT_NO_POOL_ANY); + } + +#if DEBUG > 1 + PLATFORM_DEBUG_PRINT("ALLOC_PORT_V2: My_Instance_Number %d: IP addr 0x%x, Inuse %d\n", + my_instance_number, my_pm->ipv4_address, my_pm->inuse); +#endif + + /* + * Indicate that the port is already allocated + */ + cgn_clib_bitmap_clear_no_check (my_pm->bm, bm_bit); + (my_pm->inuse)++; + + *index = my_index; + + return (CNAT_SUCCESS); +} + +void cnat_port_free_v2 ( + cnat_portmap_v2_t *pm, + int index, + port_pair_t pair_type, + u16 base_port, + u16 static_port_range) +{ + cnat_portmap_v2_t *my_pm; + uword bit; + + /* check for valid portmap */ + if (PREDICT_FALSE(index > vec_len(pm))) { + spp_printf(CNAT_INVALID_INDEX_TO_FREE_PORT, 0, 0); + return; + } + + my_pm = pm + index; + bit = port2bit(base_port); + +#if DEBUG > 0 + if(clib_bitmap_get_no_check(my_pm->bm, bit)) + ASSERT(clib_bitmap_get_no_check(my_pm->bm, bit) == 0); +#endif + + cgn_clib_bitmap_set_no_check(my_pm->bm, bit); + + my_pm->inuse -= 1; + if(base_port >= static_port_range) { + /* Clear the full flag. we can have a new dynamic session now */ + my_pm->dyn_full = 0; + } + + return; +} + +void cnat_portmap_dump_v2 (cnat_portmap_v2_t *pm, u16 print_limit) +{ + int i; + u32 inuse =0; + + ASSERT(pm); + + for (i = 0; i < BITS_PER_INST; i++) { + if (PREDICT_FALSE(clib_bitmap_get_no_check (pm->bm, i) == 0)) { + if (PREDICT_TRUE(inuse++ < print_limit)) + PLATFORM_DEBUG_PRINT(" %d", bit2port(i)); + } + } + if (PREDICT_FALSE(inuse >= print_limit)) { + PLATFORM_DEBUG_PRINT("%d printed, print limit is %d\n", + inuse, print_limit); + } + PLATFORM_DEBUG_PRINT("\n"); +} + + +/* + * cnat_ports_init + */ +clib_error_t *cnat_ports_init(vlib_main_t *vm) +{ + cnat_ports_main_t *mp = &cnat_ports_main; + + mp->vlib_main = vm; + mp->vnet_main = vnet_get_main(); + + /* suppress crypto-random port numbering */ +#ifdef SOON + if (spp_get_int_prop("no_crypto_random_ports") == 0) + crypto_random32(&seed); +#endif + + return 0; +} + +VLIB_INIT_FUNCTION(cnat_ports_init); + diff --git a/plugins/vcgn-plugin/vcgn/cnat_ports.h b/plugins/vcgn-plugin/vcgn/cnat_ports.h new file mode 100644 index 00000000..bc1fb0d2 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_ports.h @@ -0,0 +1,208 @@ +/* + *------------------------------------------------------------------ + * cnat_ports.h - port database definitions + * + * Copyright (c) 2007-2013 Cisco and/or its affiliates. + * 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 __CNAT_PORTS_H__ +#define __CNAT_PORTS_H__ + +#include "platform_common.h" +#include "cnat_bulk_port_defs.h" + +#define PORTS_PER_ADDR 65536 + +#define CNAT_INSTS PLATFORM_CNAT_INSTS + +#define BITS_PER_INST (PORTS_PER_ADDR) + +/* + * Ensure that atleast few 4 bit ports are available for RTSP + * in case we want to map 4 digit inside ports to 4 digit outside ports + */ +#define MIN_STATIC_PORT_RANGE_FOR_RTSP (9900) + +extern u8 my_instance_number; + +/* + * Now it is a 1-to-1 mapping between bit and port values + */ +static inline u16 bit2port (u32 bit) +{ + return bit; +} + +static inline uword port2bit (u16 port) +{ + return port; +} + +/* + * Port bitmap structure + * THIS structure is not used to be REMOVED.... + */ + + +typedef struct { + u32 ipv4_address; /* native bit order */ + u16 vrf; + u16 pad; + u32 threshold_crossed; + uword bm[(BITS_PER_INST + BITS(uword)-1)/BITS(uword)]; +} cnat_portmap_t; + +//cnat_portmap_t *cnat_portmap; + + +typedef struct { + u32 inuse; + u32 delete_time; + u32 ipv4_address; /* native bit order */ + u32 last_sent_timestamp; + uword bm[(BITS_PER_INST + BITS(uword)-1)/BITS(uword)]; + u32 dyn_full; + u32 private_ip_users_count; /* number of private ip's(subscribers) to this + public ip */ +} cnat_portmap_v2_t; + + +typedef enum { + PORT_SINGLE=0, + PORT_PAIR=1, + PORT_S_EVEN=2, + PORT_S_ODD=3, +} port_pair_t; + +typedef enum { + PORT_TYPE_DYNAMIC=0, + PORT_TYPE_STATIC=1, + PORT_TYPE_RTSP=2, +} port_type_t; + + +typedef enum { + PORT_ALLOC_ANY=1, + PORT_ALLOC_DIRECTED=2, +} port_alloc_t; + +#define PORT_PROBE_LIMIT 20 + + +/* + * randq1 + * Linear congruential random number generator with + * extensively studied properties. See Numerical Recipes in C + * 2nd Ed. page 284. Known to behave according to the test vector + * supplied in the text, on X86 and Octeon. + */ +static inline u32 randq1 (u32 prev) +{ + return (1664525L*prev + 1013904223L); +} + +cnat_errno_t +cnat_static_port_alloc_v2( + cnat_portmap_v2_t *pm, + port_alloc_t atype, + port_pair_t pair_type, + u32 i_ipv4_address, + u16 i_port, + u32 *index, + u32 *o_ipv4_address, + u16 *o_port, + u16 static_port_range +#ifndef NO_BULK_LOGGING + , bulk_alloc_size_t bulk_size, + int *nfv9_log_req +#endif /* NO_BULK_LOGGING */ + , u16 ip_n_to_1 + ); + +cnat_errno_t +cnat_mapped_static_port_alloc_v2 ( + cnat_portmap_v2_t *pm, + port_alloc_t atype, + u32 *index, + u32 ipv4_address, + u16 port +#ifndef NO_BULK_LOGGING + , int *nfv9_log_req, + bulk_alloc_size_t bulk_size +#endif + , u16 ip_n_to_1 + ); + +cnat_errno_t +cnat_dynamic_port_alloc_v2( + cnat_portmap_v2_t *pm, + port_alloc_t atype, + port_pair_t pair_type, + u32 *index, + u32 *o_ipv4_address, + u16 *o_port, + u16 static_port_range +#ifndef NO_BULK_LOGGING + , bulk_alloc_size_t bulk_size, + int *nfv9_log_req +#endif + , u16 ip_n_to_1, + u32 *rseed_ip + ); + + +cnat_errno_t +cnat_dynamic_port_alloc_rtsp ( + cnat_portmap_v2_t *pm, + port_alloc_t atype, + port_pair_t pair_type, + u16 start_range, + u16 end_range, + u32 *index, + u32 *o_ipv4_address, + u16 *o_port +#ifndef NO_BULK_LOGGING + , bulk_alloc_size_t bulk_size, + int *nfv9_log_req +#endif + , u32 *rseed_ip + ); + +void cnat_port_free_v2( + cnat_portmap_v2_t *pm, + int index, + port_pair_t ptype, + u16 base_port, + u16 static_port_range); + +void cnat_portmap_dump_v2(cnat_portmap_v2_t *pm, + u16 print_limit); + + + +cnat_errno_t +nat64_static_port_alloc ( + cnat_portmap_v2_t *pm, + port_alloc_t atype, + port_pair_t pair_type, + u32 *i_ipv6_address, + u16 i_port, + u32 *index, + u32 *o_ipv4_address, + u16 *o_port); + + + +#endif /* __CNAT_PORTS_H__ */ diff --git a/plugins/vcgn-plugin/vcgn/cnat_show.c b/plugins/vcgn-plugin/vcgn/cnat_show.c new file mode 100644 index 00000000..68c52756 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_show.c @@ -0,0 +1,810 @@ +/* + *------------------------------------------------------------------ + * cnat_show.c - translation database definitions + * + * Copyright (c) 2007-2014 Cisco and/or its affiliates. + * 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 +#include +#include +#include +#include +#include +#include + +#include "cnat_db.h" +#include "cnat_config.h" +#include "cnat_global.h" +#include "cnat_logging.h" +#include "spp_ctx.h" +#include "spp_timers.h" +#include "platform_common.h" +#include "cnat_syslog.h" +#include "cnat_v4_pptp_alg.h" +#include "platform_common.h" + +#ifndef TOBE_PORTED +/* The following variable is in cnat_config_msg_handler.c which + * is to be ported later.. if required + */ +u32 total_address_pool_allocated = 0; +#endif + +#ifndef NO_BULK_LOGGING +#define CNAT_MY_VRFMAP_PRINT \ +PLATFORM_DEBUG_PRINT("i-uidx 0x%x o-uidx 0x%x i-vrfid 0x%x o-vrfid 0x%x\n" \ + "status %d del time 0x%x tcp mss 0x%x pm list 0x%x\n" \ + "bulk size %d\n" \ + "ip n:1 %d\n" \ + "NFV9 template index 0x%x\n" \ + "SYSLOG template index 0x%x\n" \ + "Netflow Session Logging %d \n" \ + "Syslog Session Logging %d \n" \ + "PCP Server 0x%x, Port %u \n", \ + my_vrfmap->i_vrf, my_vrfmap->o_vrf, my_vrfmap->i_vrf_id, \ + my_vrfmap->o_vrf_id, my_vrfmap->status, my_vrfmap->delete_time, \ + my_vrfmap->tcp_mss, my_vrfmap->portmap_list, \ + BULKSIZE_FROM_VRFMAP(my_vrfmap), \ + my_vrfmap->ip_n_to_1, \ + my_vrfmap->nfv9_logging_index, \ + my_vrfmap->syslog_logging_index,\ + my_vrfmap->nf_logging_policy, \ + my_vrfmap->syslog_logging_policy, \ + my_vrfmap->pcp_server_addr, \ + my_vrfmap->pcp_server_port); +#else +#define CNAT_MY_VRFMAP_PRINT \ +PLATFORM_DEBUG_PRINT("i-uidx 0x%x o-uidx 0x%x i-vrfid 0x%x o-vrfid 0x%x\n" \ + "status %d del time 0x%x tcp mss 0x%x pm list 0x%x\n" \ + "NFV9 template index 0x%x\n ip n:1 %d\n", \ + my_vrfmap->i_vrf, my_vrfmap->o_vrf, my_vrfmap->i_vrf_id, \ + my_vrfmap->o_vrf_id, my_vrfmap->status, my_vrfmap->delete_time, \ + my_vrfmap->tcp_mss, my_vrfmap->portmap_list, \ + my_vrfmap->nfv9_logging_index, my_vrfmap->ip_n_to_1); +#endif /* NO_BULK_LOGGING */ + +#define CNAT_MY_LOGGING_INFO_PRINT \ +do { \ + cnat_syslog_logging_info_t *my_syslog_info = 0; \ + PLATFORM_DEBUG_PRINT("SYSLOG config: \n"); \ + pool_foreach (my_syslog_info, cnat_syslog_logging_info_pool, ({ \ + if (my_syslog_info->i_vrf == my_vrfmap->i_vrf) { \ + PLATFORM_DEBUG_PRINT(" \ + ipv4[0x%x], port[%u], hostname[%s]\n", \ + my_syslog_info->ipv4_address, my_syslog_info->port, \ + my_syslog_info->header_hostname); \ + break; \ + } \ + })); \ +}while (0) \ +; + + +void printf_ipv4(u32 ad) +{ + u8 a __attribute__((unused)), b __attribute__((unused)), + c __attribute__((unused)), d __attribute__((unused)); + + a = ad>>24; + b = (ad>>16) & 0xFF; + c = (ad>>8) & 0xFF; + d = (ad>>0) & 0xFF; + + PLATFORM_DEBUG_PRINT("%d.%d.%d.%d", a, b, c, d); +} +void cnat_main_db_entry_dump (cnat_main_db_entry_t *db) +{ + PLATFORM_DEBUG_PRINT("Main DB entry at %p, index %ld dst_ip %x\n", + db, db - cnat_main_db, db->dst_ipv4); + /* only dump hash next index if it's non EMPTY */ + if (db->out2in_hash.next != EMPTY || db->in2out_hash.next != EMPTY) + PLATFORM_DEBUG_PRINT("out2in hash %u, in2out hash %u\n", + db->out2in_hash.next, + db->in2out_hash.next); + PLATFORM_DEBUG_PRINT("out2in key ipv4 0x%08X, port 0x%04X (%5d), vrf %d, protocol %s\n", + db->out2in_key.k.ipv4, + db->out2in_key.k.port, + db->out2in_key.k.port, + db->out2in_key.k.vrf & CNAT_VRF_MASK, + (db->out2in_key.k.vrf & CNAT_PRO_MASK) == CNAT_UDP ? "UDP" : + ((db->in2out_key.k.vrf & CNAT_PRO_MASK) == CNAT_TCP ? "TCP" : + ((db->in2out_key.k.vrf & CNAT_PRO_MASK) == CNAT_ICMP ? "ICMP" : "PPTP ALG"))); + + PLATFORM_DEBUG_PRINT("in2out key ipv4 0x%08X, port 0x%04X (%5d), vrf %d, protocol %s\n", + db->in2out_key.k.ipv4, + db->in2out_key.k.port, + db->in2out_key.k.port, + db->in2out_key.k.vrf & CNAT_VRF_MASK, + (db->in2out_key.k.vrf & CNAT_PRO_MASK) == CNAT_UDP ? "UDP" : + ((db->in2out_key.k.vrf & CNAT_PRO_MASK) == CNAT_TCP ? "TCP" : + ((db->in2out_key.k.vrf & CNAT_PRO_MASK) == CNAT_ICMP ? "ICMP" : "UNKNOWN"))); + + PLATFORM_DEBUG_PRINT("user %d, user ports (nxt) %d (prev) %d, vrfmap_index 0x%x\n", + db->user_index, db->user_ports.next, db->user_ports.prev, + db->vrfmap_index); + PLATFORM_DEBUG_PRINT("timeout %d \n", db->timeout); + PLATFORM_DEBUG_PRINT("flags 0x%x ", db->flags); + + if (db->flags & CNAT_DB_FLAG_TCP_ACTIVE) { + PLATFORM_DEBUG_PRINT(" TCP_ACTIVE "); + } else if (db->flags & CNAT_DB_FLAG_UDP_ACTIVE) { + PLATFORM_DEBUG_PRINT(" UDP_ACTIVE "); + } else if (db->flags & CNAT_DB_FLAG_STATIC_PORT) { + PLATFORM_DEBUG_PRINT(" STATIC_PORT "); + } + + PLATFORM_DEBUG_PRINT(" ALG dlt0 0x%02X dlt1 0x%02X\n", db->alg.alg_dlt[0], db->alg.alg_dlt[1]); + PLATFORM_DEBUG_PRINT("\n"); + + PLATFORM_DEBUG_PRINT("out2in_pkts: %u\n", db->out2in_pkts); + PLATFORM_DEBUG_PRINT("in2out_pkts: %u\n", db->in2out_pkts); + PLATFORM_DEBUG_PRINT("entry_expires: %u current time: %u\n", db->entry_expires, cnat_current_time); + PLATFORM_DEBUG_PRINT("-------------------------\n"); +} + +void cnat_user_db_entry_dump (cnat_user_db_entry_t *up) +{ + u32 db_entry_index, first_db_entry_index; + cnat_main_db_entry_t *ep; + + PLATFORM_DEBUG_PRINT("User DB entry at %p, index %ld\n", + up, up - cnat_user_db); + PLATFORM_DEBUG_PRINT("translation list head index %u, %u translations portmapindex 0x%x\n", + up->translation_list_head_index, + up->ntranslations, up->portmap_index); + PLATFORM_DEBUG_PRINT("source ipv4 0x%x, source port 0x%x, vrf %d\n", + up->key.k.ipv4, + up->key.k.port, + up->key.k.vrf); + first_db_entry_index = db_entry_index = up->translation_list_head_index; + if (first_db_entry_index != EMPTY) { + PLATFORM_DEBUG_PRINT("Port translation list:\n"); + do { + PLATFORM_DEBUG_PRINT(" [%d]\n", db_entry_index); + ep = cnat_main_db + db_entry_index; + db_entry_index = ep->user_ports.next; + } while (first_db_entry_index != db_entry_index); + } else { + PLATFORM_DEBUG_PRINT("WARNING: empty translation list!\n"); + } + PLATFORM_DEBUG_PRINT("-------------------------\n"); +} + +void cnat_user_db_entry_dump_summary (cnat_user_db_entry_t *up) +{ + u32 db_entry_index, first_db_entry_index; + u32 total_entries = 0; + + PLATFORM_DEBUG_PRINT("User DB entry at %p, index %ld\n", + up, up - cnat_user_db); + PLATFORM_DEBUG_PRINT("translation list head index %u, %u translations portmapindex 0x%x\n", + up->translation_list_head_index, + up->ntranslations, up->portmap_index); + PLATFORM_DEBUG_PRINT("source ipv4 0x%x, source port 0x%x, vrf %d\n", + up->key.k.ipv4, + up->key.k.port, + up->key.k.vrf); + first_db_entry_index = db_entry_index = up->translation_list_head_index; + if (first_db_entry_index != EMPTY) { + PLATFORM_DEBUG_PRINT("Port translation list:\n"); + do { + total_entries++; + } while (first_db_entry_index != db_entry_index); + PLATFORM_DEBUG_PRINT("TOTAL_ENTRIES: %d\n", total_entries); + } else { + PLATFORM_DEBUG_PRINT("WARNING: empty translation list!\n"); + } + PLATFORM_DEBUG_PRINT("-------------------------\n"); +} + +/* for internal development and UT only */ +void cnat_db_dump_main_by_index (int argc, unsigned long *argv) +{ + u32 index, i, len; + u32 active_count, scan_count; + + if (argc != 1) { + PLATFORM_DEBUG_PRINT("invalid input %d\n", argc); + return; + } + + index = argv[0]; + + len = vec_len(cnat_main_db); + + active_count = pool_elts(cnat_main_db); + + if (index >= active_count) { + PLATFORM_DEBUG_PRINT("Index %u >= total active entries %u\n", index, active_count); + return; + } + + scan_count = 0; + for (i=0; i< len; i++) { + if(pool_is_free_index(cnat_main_db, i)) continue; + + if (index == scan_count) { + cnat_main_db_entry_dump(cnat_main_db + i); + break; + } + scan_count++; + } +} + +void cnat_db_dump_main (int argc, unsigned long *argv) +{ + cnat_main_db_entry_t *db; + + pool_foreach(db, cnat_main_db, ({ + cnat_main_db_entry_dump(db); + })); +} + +void cnat_db_dump_main_summary (int argc, unsigned long *argv) +{ + cnat_main_db_entry_t *db; + u32 num_entries = 0; + + pool_foreach(db, cnat_main_db, ({ + num_entries++; + })); + + PLATFORM_DEBUG_PRINT("\nNum main entries %d\n", num_entries); +} + +void cnat_db_dump_user (int argc, unsigned long *argv) +{ + cnat_user_db_entry_t *up; + + pool_foreach(up, cnat_user_db, ({ + cnat_user_db_entry_dump(up); + })); +} + +void cnat_db_dump_user_summary (int argc, unsigned long *argv) +{ + cnat_user_db_entry_t *up; + + pool_foreach(up, cnat_user_db, ({ + cnat_user_db_entry_dump_summary(up); + })); +} + +void cnat_db_dump_hashes (int argc, unsigned long *argv) +{ + int i; + + PLATFORM_DEBUG_PRINT("Main DB out2in hash:\n"); + for (i = 0; i < vec_len(cnat_out2in_hash); i++) { + if (cnat_out2in_hash[i].next != EMPTY) { + PLATFORM_DEBUG_PRINT("[%d]: %u\n", i, cnat_out2in_hash[i].next); + } + } + PLATFORM_DEBUG_PRINT("Main DB in2out hash:\n"); + for (i = 0; i < vec_len(cnat_in2out_hash); i++) { + if (cnat_in2out_hash[i].next != EMPTY) { + PLATFORM_DEBUG_PRINT("[%d]: %u\n", i, cnat_in2out_hash[i].next); + } + } + + PLATFORM_DEBUG_PRINT("User hash:\n"); + for (i = 0; i < vec_len(cnat_user_hash); i++) { + if (cnat_user_hash[i].next != EMPTY) { + PLATFORM_DEBUG_PRINT("[%d]: %u\n", i, cnat_user_hash[i].next); + } + } + PLATFORM_DEBUG_PRINT("-------------------------\n"); +} + + +#ifdef OLD_VRFMAP + +void cnat_db_dump_cdb (int argc, unsigned long *argv) +{ + int k; + int verbose=0; + int all = 0; + + if (argc > 0) { + verbose = 1; + } + + if (argc > 1) { + all = 1; + } + + PLATFORM_DEBUG_PRINT ("%d vrfmap vectors \n", vec_len(cnat_portmap_by_vrf)); + + for (k = 0; k < vec_len(cnat_portmap_by_vrf); k++) { + PLATFORM_DEBUG_PRINT("index%d: status %d i_vrf 0x%x o_vrf 0x%x\n", k, + cnat_portmap_by_vrf[k].status, + cnat_portmap_by_vrf[k].i_vrf, + cnat_portmap_by_vrf[k].o_vrf); + cnat_db_dump_address_portmap(verbose, all, + cnat_portmaps[k], + cnat_portmaps_inuse[k]); + } +} + +void cnat_db_dump_i_vrf (int argc, unsigned long *argv) +{ + u32 k; + u32 vrf =0; + int verbose=0; + int all = 0; + + if (!argc) { + PLATFORM_DEBUG_PRINT("need vrf input ,return\n"); + return; + } + + if (argc > 0) { + vrf = argv[0]; + } + + if (argc > 1) { + verbose = 1; + } + + if (argc > 2) { + all = 1; + } + + PLATFORM_DEBUG_PRINT ("%d vrfmap vectors \n", vec_len(cnat_portmap_by_vrf)); + + for (k = 0; k < vec_len(cnat_portmap_by_vrf); k++) { + if (cnat_portmap_by_vrf[k].i_vrf == vrf) { + PLATFORM_DEBUG_PRINT("%d: i_vrf 0x%x o_vrf 0x%x\n", k, + cnat_portmap_by_vrf[k].i_vrf, + cnat_portmap_by_vrf[k].o_vrf); + cnat_db_dump_address_portmap(verbose, all, + cnat_portmaps[k], + cnat_portmaps_inuse[k]); + return; + } + } + PLATFORM_DEBUG_PRINT("not found\n"); +} + +void cnat_db_dump_o_vrf (int argc, unsigned long *argv) +{ + u32 k; + int verbose=0; + int all = 0; + u32 vrf =0; + + if (!argc) { + PLATFORM_DEBUG_PRINT("need vrf input ,return\n"); + return; + } + + if (argc > 0) { + vrf = argv[0]; + } + + if (argc > 1) { + verbose = 1; + } + + if (argc > 2) { + all = 1; + } + + PLATFORM_DEBUG_PRINT ("%d vrfmap vectors \n", vec_len(cnat_portmap_by_vrf)); + + for (k = 0; k < vec_len(cnat_portmap_by_vrf); k++) { + if (cnat_portmap_by_vrf[k].o_vrf == vrf) { + PLATFORM_DEBUG_PRINT("index%d: status %d i_vrf 0x%x o_vrf 0x%x\n", k, + cnat_portmap_by_vrf[k].status, + cnat_portmap_by_vrf[k].i_vrf, + cnat_portmap_by_vrf[k].o_vrf); + cnat_db_dump_address_portmap(verbose, all, + cnat_portmaps[k], + cnat_portmaps_inuse[k]); + return; + } + } + PLATFORM_DEBUG_PRINT("not found\n"); +} +#endif + +#ifdef TOBE_PORTED +/* This does not seem to be used */ +void cnat_db_mem_usage_cmd (int argc, unsigned long *argv) +{ + pool_header_t * p; + _VEC *_v; + u32 bitmap_bytes=0, free_indices_bytes=0, vec_bytes=0, total_bytes=0; + + if (cnat_main_db) { + p = pool_header(cnat_main_db); + if (p->free_bitmap) { + _v = _vec_find(p->free_bitmap); + bitmap_bytes = _v->alen; + } else { + bitmap_bytes = 0; + } + if (p->free_indices) { + _v = _vec_find(p->free_indices); + free_indices_bytes = _v->alen; + } else { + free_indices_bytes = 0; + } + _v = _vec_find(cnat_main_db); + vec_bytes = _v->alen; + } else { + vec_bytes = 0; + } + + total_bytes = bitmap_bytes + free_indices_bytes + vec_bytes; + + PLATFORM_DEBUG_PRINT ("Main DB: %d total bytes, %d bitmap, %d indices, %d vec\n", + total_bytes, bitmap_bytes, free_indices_bytes, vec_bytes); + PLATFORM_DEBUG_PRINT (" vector length %d\n", vec_len(cnat_main_db)); + + if (cnat_user_db) { + p = pool_header(cnat_user_db); + if (p->free_bitmap) { + _v = _vec_find(p->free_bitmap); + bitmap_bytes = _v->alen; + } else { + bitmap_bytes = 0; + } + if (p->free_indices) { + _v = _vec_find(p->free_indices); + free_indices_bytes = _v->alen; + } else { + free_indices_bytes = 0; + } + _v = _vec_find(cnat_user_db); + vec_bytes = _v->alen; + } else { + vec_bytes = 0; + } + + total_bytes = bitmap_bytes + free_indices_bytes + vec_bytes; + + PLATFORM_DEBUG_PRINT ("User DB: %d total bytes, %d bitmap, %d indices, %d vec\n", + total_bytes, bitmap_bytes, free_indices_bytes, vec_bytes); + PLATFORM_DEBUG_PRINT (" vector length %d\n", vec_len(cnat_user_db)); + + _v = _vec_find(cnat_out2in_hash); + PLATFORM_DEBUG_PRINT("out2in hash: %d total bytes\n", _v->alen); + + _v = _vec_find(cnat_in2out_hash); + PLATFORM_DEBUG_PRINT("in2out hash: %d total bytes\n", _v->alen); +} +#endif + +static void print_server_ip_address (vlib_main_t *vm, u32 ip) +{ + unsigned char bytes[4]; + bytes[0] = ip & 0xFF; + bytes[1] = (ip >> 8) & 0xFF; + bytes[2] = (ip >> 16) & 0xFF; + bytes[3] = (ip >> 24) & 0xFF; + vlib_cli_output(vm, "\tIP Address : %d.%d.%d.%d\n", bytes[0], bytes[1], bytes[2], bytes[3]); +} + +void cnat_nfv9_show_collector (vlib_main_t *vm, cnat_nfv9_logging_info_t *my_nfv9_logging_info) +{ + nfv9_server_info_t *server = nfv9_server_info_pool + + my_nfv9_logging_info->server_index; +#if 0 + vlib_cli_output(vm,"\tVRF - 0x%x - %s\n", my_nfv9_logging_info->i_vrf, + my_nfv9_logging_info->deleted?"DELETED":"ACTIVE"); +#endif + print_server_ip_address(vm, clib_net_to_host_u32(server->ipv4_address)); + vlib_cli_output(vm,"\tPort : %d\n", server->port); + vlib_cli_output(vm,"\tTimeout : %d\n", server->timeout_rate); + vlib_cli_output(vm,"\tRefresh Rate : %d\n", server->refresh_rate); + vlib_cli_output(vm,"\tMax Pkt Size : %d\n", my_nfv9_logging_info->max_length_minus_max_record_size); + + return; +} + +void cnat_db_dump_policy (int argc, unsigned long *argv) +{ + + PLATFORM_CNAT_DB_DUMP_POLICY_PRINT(); + + if (cnat_nfv9_global_info.cnat_nfv9_init_done) { + if (cnat_nfv9_global_info.cnat_nfv9_global_collector_index != EMPTY) { + cnat_nfv9_logging_info_t *my_nfv9_logging_info; + nfv9_server_info_t *server __attribute__((unused)); + + my_nfv9_logging_info = cnat_nfv9_logging_info_pool + + cnat_nfv9_global_info.cnat_nfv9_global_collector_index; + server = nfv9_server_info_pool + + my_nfv9_logging_info->server_index; + + PLATFORM_DEBUG_PRINT("NFv9 logging ip 0x%x port 0x%x refresh-rate %d timeout %d\n", + server->ipv4_address, + server->port, + server->refresh_rate, + server->timeout_rate); + PLATFORM_DEBUG_PRINT("NFv9 path_mtu = %d\n", + my_nfv9_logging_info->max_length_minus_max_record_size); + } else { + PLATFORM_DEBUG_PRINT("NFv9 global logging is not configured\n"); + } + } else { + PLATFORM_DEBUG_PRINT("NFv9 LOGGING is not configured\n"); + } + +} + +#ifdef OLD_VRFMAP +void cnat_show_cdb (int verbose) +{ + int k, l, i; + for (i = 0; i < vec_len(cnat_portmap_by_vrf); i++) { + PLATFORM_DEBUG_PRINT("i_vrf %d : o_vrf %d\n", + cnat_portmap_by_vrf[i].i_vrf, + cnat_portmap_by_vrf[i].o_vrf); + } + + PLATFORM_DEBUG_PRINT("port limit %d\n", cnat_main_db_max_ports_per_user); + + PLATFORM_DEBUG_PRINT ("%d portmap vectors\n", vec_len(cnat_portmaps)); + + for (k = 0; k < vec_len(cnat_portmaps); k++) { + cnat_portmap_t *pm; + u16 *inuse; + pm = cnat_portmaps[k]; + inuse = cnat_portmaps_inuse[k]; + for (l = 0; l < vec_len(pm); l++) { + if (inuse[l] || verbose ) { + u32 net_address; + net_address = + spp_host_to_net_byte_order_32((pm+l)->ipv4_address); + printf_ipv4(net_address); + PLATFORM_DEBUG_PRINT (": %d inuse\n", inuse[l]); + if (verbose && inuse[l]) { + cnat_portmap_dump (pm+l, inuse+l); + } + } + } + } +} +#endif + + + +/* v2 show command */ +void cnat_show_address_portmap_sumary (cnat_portmap_v2_t *pm) +{ + cnat_portmap_v2_t *my_pm =0; + u32 first_address = 0; + u32 second_address = 0; + u32 last_address = 0; + u32 i, pm_len; + + if ((pm_len = vec_len(pm))) { + PLATFORM_DEBUG_PRINT("%d portmap in this list 0x%lx\n", + pm_len, (u32)pm); + for (i = 0; i < pm_len; i++) { + my_pm = pm + i; + if (!first_address) { + first_address = my_pm->ipv4_address; + } else if (!second_address) { + second_address = my_pm->ipv4_address; + } + last_address = my_pm->ipv4_address; + } + + if (first_address) { + PLATFORM_DEBUG_PRINT("1. 0x%08x", first_address); + } + if (second_address) { + PLATFORM_DEBUG_PRINT(", 2. 0x%08x", second_address); + } + + if ((last_address != first_address) && + (last_address != second_address)) { + PLATFORM_DEBUG_PRINT(", ....., %d. 0x%08x", pm_len, last_address); + } + PLATFORM_DEBUG_PRINT("\n"); + } else { + PLATFORM_DEBUG_PRINT("ZERO POOL ADDRESSES in this list 0x%x \n", (u32)pm); + } +} + + +void cnat_show_address_portmap (int verbose, int all, + cnat_portmap_v2_t *pm, u16 port_limit) +{ + cnat_portmap_v2_t *my_pm =0; + u32 i, pm_len; + + pm_len = vec_len(pm); + if (!all) { + cnat_show_address_portmap_sumary(pm); + } else { + PLATFORM_DEBUG_PRINT("%d portmap in this list 0x%x \n", pm_len, (u32)pm); + } + + for (i = 0; i < pm_len; i++) { + + my_pm = pm + i; + if (all) { + PLATFORM_DEBUG_PRINT("pm:0x%x ip address:0x%x del_time 0x%x inuse:%d\n", + (u32)my_pm, my_pm->ipv4_address, my_pm->delete_time, my_pm->inuse); + } else if (my_pm->inuse) { + PLATFORM_DEBUG_PRINT("pm:0x%x ip address:0x%x inuse:%d\n", + (u32)my_pm, my_pm->ipv4_address, my_pm->inuse); + } + + if (verbose && (my_pm->inuse)) { + if(PREDICT_FALSE(!port_limit)) { + cnat_portmap_dump_v2 (my_pm, cnat_main_db_max_ports_per_user); + } + else { + cnat_portmap_dump_v2 (my_pm, port_limit); + } + } + } + + PLATFORM_DEBUG_PRINT("\n"); +} + + +void cnat_show_cdb_v2 (int verbose, int all) +{ + cnat_vrfmap_t *my_vrfmap = 0; + cnat_portmap_v2_t *pm =0; + PLATFORM_DEBUG_PRINT("port limit %d\n", cnat_main_db_max_ports_per_user); + PLATFORM_DEBUG_PRINT("total address pool allocated %d\n", total_address_pool_allocated); + PLATFORM_DEBUG_PRINT("icmp rate limit %d (per core %d)\n", + cnat_main_db_icmp_rate_limit, cnat_main_db_icmp_rate_limit_core); + PLATFORM_DEBUG_PRINT("dynamic port range start %d\n", cnat_static_port_range); + if (pptp_cfg.enable == PPTP_DISABLED) { + PLATFORM_DEBUG_PRINT("PPTP alg disabled \n"); + } else { + PLATFORM_DEBUG_PRINT("PPTP alg enabled \n"); + } + + if (ftp_alg_enabled) { + PLATFORM_DEBUG_PRINT("FTP alg enabled\n"); + } else { + PLATFORM_DEBUG_PRINT("FTP alg disabled\n"); + } + + pool_foreach (my_vrfmap, cnat_map_by_vrf, ({ + CNAT_MY_VRFMAP_PRINT + CNAT_MY_LOGGING_INFO_PRINT + PLATFORM_DEBUG_PRINT("per vrf port limit %d\n", my_vrfmap->port_limit); + pm = my_vrfmap->portmap_list; + cnat_show_address_portmap(verbose, all, pm, my_vrfmap->port_limit); + + })); +} + + +void cnat_show_cdb_command_v2(int argc, unsigned long *argv) +{ + int verbose=0; + int all = 0; + + if (argc > 0) { + verbose = 1; + } + + if (argc > 1) { + all = 1; + } + + cnat_show_cdb_v2(verbose, all); +} + +void cnat_show_ivrf_command_v2 (int argc, unsigned long *argv) +{ + u32 vrf =0; + int verbose=0; + int all = 0; + cnat_vrfmap_t *my_vrfmap = 0; + cnat_portmap_v2_t *pm =0; + + if (!argc) { + PLATFORM_DEBUG_PRINT("need vrf input ,return\n"); + return; + } + if (argc > 0) { + vrf = argv[0]; + } + if (argc > 1) { + verbose = 1; + } + if (argc > 2) { + all = 1; + } + PLATFORM_DEBUG_PRINT ("%lld vrfmap vectors \n", pool_elts(cnat_map_by_vrf)); + pool_foreach (my_vrfmap, cnat_map_by_vrf, ({ + if (my_vrfmap->i_vrf == vrf) { + CNAT_MY_VRFMAP_PRINT + pm = my_vrfmap->portmap_list; + cnat_show_address_portmap(verbose, all, pm,my_vrfmap->port_limit); + return; + } + })); + PLATFORM_DEBUG_PRINT("not found\n"); +} + +void cnat_show_ovrf_command_v2 (int argc, unsigned long *argv) +{ + u32 not_found =1; + u32 vrf =0; + int verbose=0; + int all = 0; + cnat_vrfmap_t *my_vrfmap = 0; + cnat_portmap_v2_t *pm =0; + + if (!argc) { + PLATFORM_DEBUG_PRINT("need vrf input ,return\n"); + return; + } + if (argc > 0) { + vrf = argv[0]; + } + if (argc > 1) { + verbose = 1; + } + if (argc > 2) { + all = 1; + } + PLATFORM_DEBUG_PRINT("%d vrfmap vectors \n", pool_elts(cnat_map_by_vrf)); + pool_foreach (my_vrfmap, cnat_map_by_vrf, ({ + if (my_vrfmap->o_vrf == vrf) { + CNAT_MY_VRFMAP_PRINT + pm = my_vrfmap->portmap_list; + cnat_show_address_portmap(verbose, all, pm,my_vrfmap->port_limit); + not_found = 0; + } + })); + if (not_found) { + PLATFORM_DEBUG_PRINT("not found\n"); + } +} + +void cnat_timeout_db_entry_dump (cnat_timeout_db_entry_t *up) +{ + u32 db_entry_index __attribute__((unused)), + first_db_entry_index __attribute__((unused)); + + PLATFORM_DEBUG_PRINT("Timeout DB entry at index %ld\n", up - cnat_timeout_db); + PLATFORM_DEBUG_PRINT("Desnt key 0x%16llx\n", up->t_key.timeout_key.key64); + PLATFORM_DEBUG_PRINT("Timeout value %d\n", up->t_key.timeout_value); + PLATFORM_DEBUG_PRINT("Hash Next 0x%x\n", up->t_hash.next); + +} + +void cnat_db_dump_timeout () +{ + cnat_timeout_db_entry_t *up; + pool_header_t *h; + u32 used __attribute__((unused)), free __attribute__((unused)); + + h = pool_header(cnat_timeout_db); + free = vec_len(h->free_indices); + used = (vec_len(cnat_timeout_db) - free); + + PLATFORM_DEBUG_PRINT("Timeout DB Free %d, Used %d\n",free, used); + + pool_foreach(up, cnat_timeout_db, ({ + cnat_timeout_db_entry_dump(up); + })); +} + diff --git a/plugins/vcgn-plugin/vcgn/cnat_show_api.h b/plugins/vcgn-plugin/vcgn/cnat_show_api.h new file mode 100644 index 00000000..5904c7e2 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_show_api.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2015 Cisco and/or its affiliates. + * 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 __CNAT_SHOW_API_H__ +#define __CNAT_SHOW_API_H__ + +typedef struct _spp_api_cnat_v4_show_inside_entry_req { + u16 _spp_msg_id; + u16 vrf_id; + u32 ipv4_addr; + u16 start_port; + u16 end_port; + u8 flags; + u8 all_entries; + u8 protocol; +} spp_api_cnat_v4_show_inside_entry_req_t; + +typedef struct _spp_api_cnat_v4_show_outside_entry_req { + u16 _spp_msg_id; + u16 vrf_id; + u32 ipv4_addr; + u16 start_port; + u16 end_port; + u8 flags; + u8 protocol; +} spp_api_cnat_v4_show_outside_entry_req_t; + + +#endif diff --git a/plugins/vcgn-plugin/vcgn/cnat_show_response.h b/plugins/vcgn-plugin/vcgn/cnat_show_response.h new file mode 100644 index 00000000..bec1bd97 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_show_response.h @@ -0,0 +1,580 @@ +/* + *------------------------------------------------------------------ + * cnat_show_response.h show command response structs + * + * Copyright (c) 2007-2013 Cisco and/or its affiliates. + * 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 __CNAT_SHOW_RESPONSE_H__ +#define __CNAT_SHOW_RESPONSE_H__ + +/* + * Flags indicating the type of translation entry + */ +#define CNAT_TRANSLATION_ENTRY_ALL 0x0 +#define CNAT_TRANSLATION_ENTRY_STATIC 0x1 +#define CNAT_TRANSLATION_ENTRY_ALG 0x2 +#define CNAT_TRANSLATION_ENTRY_DYNAMIC 0x4 + +/* for PCP support */ +#define CNAT_TRANSLATION_ENTRY_PCPI_DYNAMIC 0x08 +#define CNAT_TRANSLATION_ENTRY_PCPE_DYNAMIC 0x10 + +#define MAX_NODE_NAME_LEN 18 +#define MAX_CTR_NAME_LEN 10 + +/* + * show translation entry response structures + */ +typedef struct { + u16 call_id; + u16 cnat_call_id; /* mapped call Id */ + u16 dst_call_id; /* dest call id */ +} cnat_v4_show_gre_entry; + +typedef struct { + u16 msg_id; + u16 rc; /* o/p parameter. */ + u16 num_entries; /* Number of entries sent as output */ + u16 vrf_id; /* vrf id */ + u32 pns_ip; + cnat_v4_show_gre_entry entries[0]; +} cnat_v4_show_gre_entry_resp; + +/* + * show translation entry response structures + */ +typedef struct { + u32 ipv4_addr; + u16 src_port; + u16 cnat_port; /* port which replaced the src port */ + u8 protocol; + u8 pad; + u16 flags; + u16 nsessions; + u32 in2out_packets; + u32 out2in_packets; +} cnat_v4_show_translation_entry; + +typedef struct { + u16 msg_id; + u8 rc; /* o/p parameter. */ + u8 num_entries; /* Number of entries sent as output */ + u16 vrf_id; /* vrf id */ + u16 pad; + cnat_v4_show_translation_entry entries[0]; +} cnat_v4_show_entry_resp; + +/* + * show free/used ipv4 address/port response structure + */ +typedef struct { + u32 ip_addr; + u32 free_used_ports; +} cnat_v4_show_free_used_entry; + +typedef struct { + u16 msg_id; + u8 rc; + u8 count; + u32 max_ports; + cnat_v4_show_free_used_entry entry_list[0]; +} cnat_v4_show_free_used_entry_resp; + +/* + * Node name to id mapping + */ +typedef struct { + u8 node_id; + u8 pad; + char node_name[MAX_NODE_NAME_LEN]; +} cnat_statistics_node_name; + +typedef struct { + u16 msg_id; + u8 rc; + u8 num_nodes; + cnat_statistics_node_name node_name_array[0]; +} cnat_statistics_node_name_mapping_resp; + +/* + * Counter name to id mapping + */ +typedef struct { + u8 node_id; + u8 counter_id; + char counter_name[MAX_CTR_NAME_LEN]; +} cnat_statistics_counter_name; + +typedef struct { + u16 msg_id; + u8 rc; + u8 num_counters; + cnat_statistics_counter_name counter_name_array[0]; +} cnat_statistics_counter_name_mapping_resp; + + +/* + * Node name to id mapping + */ +typedef struct { + u16 msg_id; + u8 rc; + u8 num_nodes; + u32 pad; + u64 counters [0]; +} cnat_statistics_counter_values; + +/* + * Summary Stats + */ +typedef struct { + u32 eaddr; + u32 ports_used; +} pool_address_usage_t; + +typedef struct { + u16 msg_id; + u8 rc; + u8 pad; + u16 max_pkt_size; + u16 pool_address_copied; + u32 active_translations; + u32 translation_create_rate; + u32 translation_delete_rate; + u32 in2out_forwarding_rate; + u32 out2in_forwarding_rate; + u32 dummy; + u64 in2out_drops_port_limit_exceeded; + u64 in2out_drops_system_limit_reached; + u64 in2out_drops_resource_depletion; + u64 no_translation_entry_drops; + u64 pptp_active_tunnels; + u64 pptp_active_channels; + u64 pptp_ctrlmsg_drops; + u32 no_sessions; + + u32 pool_address_totally_free; + u32 pool_address_used; /* The following array size will be lesser of + (pool_address_used, 200) */ + u32 num_subscribers; + u64 drops_sessiondb_limit_exceeded; + u64 in2out_drops_src_ip_no_config; // for deterministic nat on brahmos + pool_address_usage_t pool_address_usage[0]; +} cnat_show_statistics_summary_resp; + + +typedef struct { + u16 msg_id; + u8 rc; + u8 pad; + u64 o2i_tcp_seq_mismatch_drop; + u64 o2i_tcp_seq_mismatch; + u64 o2i_sessions_created; + u64 o2i_end_point_filter_drop; +} cnat_show_counters_summary_resp; + + +typedef struct { + u16 msg_id; + u8 rc; + u8 pad; + + /* + * XLAT statistics + */ + u64 v6_to_v4_tcp_input_count; + u64 v6_to_v4_tcp_non_translatable_drop_count; + u64 v6_to_v4_tcp_invalid_next_hdr_drop_count; + u64 v6_to_v4_tcp_no_db_drop_count; + u64 v6_to_v4_tcp_output_count; + + u64 v4_to_v6_tcp_input_count; + u64 v4_to_v6_tcp_no_db_drop_count; + u64 v4_to_v6_tcp_output_count; + + u64 v6_to_v4_udp_input_count; + u64 v6_to_v4_udp_non_translatable_drop_count; + u64 v6_to_v4_udp_invalid_next_hdr_drop_count; + u64 v6_to_v4_udp_no_db_drop_count; + u64 v6_to_v4_udp_output_count; + + u64 v4_to_v6_udp_input_count; + u64 v4_to_v6_udp_no_db_drop_count; + u64 v4_to_v6_udp_output_count; + u64 v4_to_v6_udp_frag_crc_zero_drop_count; + u64 v4_to_v6_udp_crc_zero_recycle_sent_count; + u64 v4_to_v6_udp_crc_zero_recycle_drop_count; + + u64 v6_to_v4_icmp_qry_input_count; + u64 v6_to_v4_icmp_no_db_drop_count; + u64 v6_to_v4_icmp_frag_drop_count; + u64 v6_to_v4_icmp_invalid_next_hdr_drop_count; + u64 v6_to_v4_icmp_non_translatable_drop_count; + u64 v6_to_v4_icmp_non_translatable_fwd_count; + u64 v6_to_v4_icmp_unsupported_type_drop_count; + u64 v6_to_v4_icmp_err_output_count; + u64 v6_to_v4_icmp_qry_output_count; + + u64 v4_to_v6_icmp_qry_input_count; + u64 v4_to_v6_icmp_no_db_drop_count; + u64 v4_to_v6_icmp_frag_drop_count; + u64 v4_to_v6_icmp_unsupported_type_drop_count; + u64 v4_to_v6_icmp_err_output_count; + u64 v4_to_v6_icmp_qry_output_count; + + u64 v6_to_v4_subsequent_frag_input_count; + u64 v6_to_v4_subsequent_frag_non_translatable_drop_count; + u64 v6_to_v4_subsequent_frag_invalid_next_hdr_drop_count; + u64 v6_to_v4_subsequent_frag_no_db_drop_count; + u64 v6_to_v4_subsequent_frag_output_count; + + u64 v4_to_v6_subsequent_frag_input_count; + u64 v4_to_v6_subsequent_frag_no_db_drop_count; + u64 v4_to_v6_subsequent_frag_output_count; + + u64 v4_to_v6_subsequent_frag_drop_count; + u64 v4_to_v6_subsequent_frag_throttled_count; + u64 v4_to_v6_subsequent_frag_timeout_drop_count; + u64 v4_to_v6_subsequent_frag_tcp_input_count; + u64 v4_to_v6_subsequent_frag_udp_input_count; + u64 v4_to_v6_subsequent_frag_icmp_input_count; + + u64 v6_to_v4_options_input_count; + u64 v6_to_v4_options_drop_count; + u64 v6_to_v4_options_forward_count; + u64 v6_to_v4_options_no_db_drop_count; + u64 v6_to_v4_unsupp_proto_count; + + u64 v4_to_v6_options_input_count; + u64 v4_to_v6_options_drop_count; + u64 v4_to_v6_options_forward_count; + u64 v4_to_v6_options_no_db_drop_count; + u64 v4_to_v6_unsupp_proto_count; + + u64 v4_icmp_gen_count; + u64 v6_icmp_gen_count; +} xlat_show_statistics_summary_resp; + +typedef struct { + u16 msg_id; + u8 rc; + u8 pad; + /* Total v4 packets to BR */ + u64 v4_to_v6_input_total_count; + /* Total v4 tunneled packets to BR */ + u64 v4_to_v6_41_input_total_count; + /* proto 41 packets without minimum, of 40, v6 payload */ + u64 v4_to_v6_41_insuff_v6payld_count; + /* total proto 41 packets being considered for decap */ + u64 v4_to_v6_41_valid_count; + /* proto 41 packets that failed security check*/ + u64 v4_to_v6_41_sec_check_fail_count; + /* packets with no active db entry */ + u64 v4_to_v6_no_db_drop_count; + /* proto 41 packets actually getting decapped */ + u64 v4_to_v6_41_decap_count; + /* total v4 packets which are neither icmp nor 41 */ + u64 v4_to_v6_unsupported_protocol_count; + /* v4 tunneled packets with invalid v6 source address */ + u64 v4_to_v6_41_invalid_v6_source; + /* total icmpv4 packets destined to BR */ + u64 v4_forus_icmp_input_count; + /* total icmpv4 echo replies by BR */ + u64 v4_icmp_reply_count; + /* total icmpv4 error messages translated to icmpv6 by BR */ + u64 v4_to_v6_icmp_translation_count; + /* total packets with icmpv4 type/code which are not supported by BR */ + u64 v4_icmp_unsupported_count; + /* total icmpv4 packets which are rate-limited by BR */ + u64 v4_icmp_throttled_count; + /* total ICMPv4 error messages which could not be translated */ + u64 v4_icmp_non_translatable_drop_count; + + /* ipv4 defrag stats */ + u64 v4_to_v6_frag_input_count; + u64 v4_to_v6_frag_sec_check_fail_count; + u64 v4_to_v6_frag_reassem_count; + u64 v4_to_v6_frag_timeout_drop_count; + u64 v4_to_v6_frag_icmp_input_count; + u64 v4_to_v6_frag_41_insuff_v6payld_count; + u64 v4_to_v6_frag_no_db_drop_count; + u64 v4_to_v6_frag_unsupported_protocol_count; + u64 v4_to_v6_frag_41_invalid_v6_source; + u64 v4_to_v6_frag_throttled_count; + u64 v4_to_v6_frag_dup_count; + u64 v4_to_v6_frag_reassem_frag_count; + u64 v4_to_v6_frag_disable_count; + u64 v4_to_v6_frag_drop_count; + + /* total v6 packets input to BR */ + u64 v6_to_v4_total_input_count; + /* v6 packets with no active db entry */ + u64 v6_to_v4_no_db_drop_count; + /* forus v6 packets with next header other than icmpv6 */ + u64 v6_to_v4_forus_unsupp_proto_count; + /* total v6 packets that got tunneled */ + u64 v6_to_v4_encap_count; + /* total icmpv6 packets destined to BR */ + u64 v6_forus_icmp_input_count; + /* total icmpv6 echo replies by BR */ + u64 v6_icmp_reply_count; + /* total icmpv6 PTB messages generated by BR */ + u64 v6_ptb_generated_count; + /* total ipv6 packets for which PTBv6 was NOT generated by BR */ + u64 v6_ptb_not_generated_drop_count; + /* total icmpv6 Neighbor Advertisements generated by BR */ + u64 v6_na_generated_count; + /* total icmpv6 TTL expiry messages generated by BR */ + u64 v6_ttl_expiry_generated_count; + /* total ICMPv6 fragments, which are dropped by BR */ + u64 v6_to_v4_frag_icmp_input_count; + /* total packets with icmpv6 type/code which are not supported by BR */ + u64 v6_icmp_unsupported_count; + /* total icmpv6 packets which are rate-limited by BR */ + u64 v6_icmp_throttled_count; +} v6rd_show_statistics_summary_resp; + +typedef struct { + u16 msg_id; + u8 rc; + u8 pad; + + /* Total Incoming Count */ + u64 v4_input_count; + /* Total Drop Count */ + u64 v4_drop_count; + /* Total Output Count */ + u64 v4_to_v6_output_count; + /* TCP Incoming Count */ + u64 v4_tcp_input_count; + /* TCP Output Count */ + u64 v4_tcp_output_count; + /* UDP Incoming Count */ + u64 v4_udp_input_count; + /* UDP Output Count */ + u64 v4_udp_output_count; + /* ICMPv4 Incoming Count */ + u64 v4_icmp_input_count; + /* ICMPv4 Output Count */ + u64 v4_to_v6_icmp_output_count; + /* Invalid UIDB Drop Count */ + u64 v4_invalid_uidb_drop_count; + /* NoDb Drop Count */ + u64 v4_no_db_drop_count; + /* TTL Expire Drop Count */ + u64 v4_ttl_expire_drop_count; + /* Invalid IP Destination Drop Count */ + u64 v4_invalid_destination_prefix_drop_count; + /* Packet Execeeding Path MTU Drop Count */ + u64 v4_path_mtu_exceed_count; + /* Unsupported Protocol Drop Count */ + u64 v4_invalid_proto_type_drop_count; + /* ICMPv4 Generated for TTL Expire Count */ + u64 v4_ttl_expiry_generated_count; + /* ICMPv4 Generated for Error Count */ + u64 v4_icmp_error_gen_count; + /* ICMPv4 Packets Rate-Limited Count */ + u64 v4_icmp_throttled_drop_count; + /* TCP MSS Changed Count */ + u64 v4_tcp_mss_changed_count; + + /* Total Incoming Count */ + u64 v6_input_count; + /* Total Drop Count */ + u64 v6_drop_count; + /* Total Output Count */ + u64 v6_to_v4_output_count; + /* TCP Incoming Count */ + u64 v6_tcp_input_count; + /* TCP Output Count */ + u64 v6_tcp_output_count; + /* UDP Incoming Count */ + u64 v6_udp_input_count; + /* UDP Output Count */ + u64 v6_udp_output_count; + /* ICMPv4 Incoming Count */ + u64 v6_icmpv4_input_count; + /* ICMPv4 Output Count */ + u64 v6_icmpv4_output_count; + /* Invalid UIDB Drop Count */ + u64 v6_invalid_uidb_drop_count; + /* NoDb Drop Count */ + u64 v6_no_db_drop_count; + /* TTL Expire Drop Count */ + u64 v6_ttl_expire_drop_count; + /* Invalid IPv6 Destination Drop Count */ + u64 v6_invalid_destination_drop_count; + /* Invalid Source Prefix Drop Count */ + u64 v6_invalid_source_prefix_drop_count; + /* Unsupported Protocol Drop Count */ + u64 v6_invalid_proto_type_drop_count; + /* ICMPv6 Input Count */ + u64 v6_icmp_input_count; + /* ICMPv6 Invalid UIDB Drop Count */ + u64 v6_icmp_invalid_uidb_drop_count; + /* ICMPv6 NoDb Drop Count */ + u64 v6_icmp_no_db_drop_count; + /* ICMPv6 TTL Expire Drop Count */ + u64 v6_icmp_ttl_expire_drop_count; + /* ICMPv6 Invalid IPv6 Destination Drop Count */ + u64 v6_icmp_invalid_destination_drop_count; + /* ICMPv6 Unsupported Type Drop Count */ + u64 v6_icmp_unsupported_type_drop_count; + /* ICMPv6 Invalid NxtHdr Drop Count*/ + u64 v6_icmp_unsupported_nxthdr_drop_count; + /* ICMPv6 Frag Drop Count */ + u64 v6_icmp_frag_drop_count; + /* ICMPv6 Forus Count */ + u64 v6_forus_icmp_input_count; + /* ICMPv6 Echo Response Received Count */ + u64 v6_received_echo_response_count; + /* ICMPv6 Echo Replies Count */ + u64 v6_echo_reply_count; + /* ICMPv6 Translated to ICMPV4 Output Count*/ + u64 v6_to_v4_icmp_output_count; + /* ICMPv6 Generated for TTL Expire Count */ + u64 v6_ttl_expiry_generated_count; + /* ICMPv6 Generated for Error Count */ + u64 v6_icmp_error_gen_count; + /* ICMPv6 Packets Rate-Limited Count */ + u64 v6_icmp_throttled_drop_count; + /* TCP MSS Changed Count */ + u64 v6_tcp_mss_changed_count; + + /*Total Input Count*/ + u64 v4_to_v6_frag_input_count; + /*Total Drop Count*/ + u64 v4_to_v6_frag_drop_count; + /*Reassembled Output Count*/ + u64 v4_to_v6_frag_reassem_count; + + /*TCP Input Count*/ + u64 v4_to_v6_frag_tcp_input_count; + /*UDP Input Count*/ + u64 v4_to_v6_frag_udp_input_count; + /*ICMPv4 Input Count*/ + u64 v4_to_v6_frag_icmp_input_count; + + /*Invalid UIDB Drop Count */ + u64 v4_to_v6_frag_invalid_uidb_drop_count; + /*NoDb Drop Count*/ + u64 v4_to_v6_frag_no_db_drop_count; + /*Unsupported Protocol Drop Count*/ + u64 v4_to_v6_frag_invalid_proto_type_drop_count; + /*Throttled Count*/ + u64 v4_to_v6_frag_throttled_count; + /*Timeout Drop Count*/ + u64 v4_to_v6_frag_timeout_drop_count; + /*Duplicates Drop Count*/ + u64 v4_to_v6_frag_dup_count; + + /*Total Input Count*/ + u64 v6_to_v4_inner_frag_input_count; + /*Total Drop Count*/ + u64 v6_to_v4_inner_frag_drop_count; + /*Total Output Count*/ + u64 v6_to_v4_inner_frag_output_count; + + /*TCP Input Count*/ + u64 v6_to_v4_inner_frag_tcp_input_count; + /*UDP Input Count*/ + u64 v6_to_v4_inner_frag_udp_input_count; + /*ICMPv4 Input Count*/ + u64 v6_to_v4_inner_frag_icmp_input_count; + + /*Invalid Source Prefix Drop Count*/ + u64 v6_to_v4_inner_frag_invalid_source_prefix_drop_count; + /*Unsupported Protocol Drop Count*/ + u64 v6_to_v4_inner_frag_invalid_proto_type_drop_count; + /*Throttled Count*/ + u64 v6_to_v4_inner_frag_throttled_count; + /*Timeout Drop Count*/ + u64 v6_to_v4_inner_frag_timeout_drop_count; + /*Duplicates Drop Count*/ + u64 v6_to_v4_inner_frag_dup_count; + + /*ICMPv6 Generated for Error Count */ + u64 v6_to_v4_inner_frag_icmp_error_gen_count; + /*ICMPv6 Packets Rate-Limited Count */ + u64 v6_to_v4_inner_frag_icmp_throttled_drop_count; + + /*TCP MSS Changed Count */ + u64 v6_to_v4_inner_frag_tcp_mss_changed_count; + +} mape_show_statistics_summary_resp; + +/* + * The following are the command types for Generic Command cases + */ +#define CNAT_DEBUG_GENERIC_COMMAND_READ_MEM 1 +#define CNAT_DEBUG_GENERIC_COMMAND_WRITE_MEM 2 +#define CNAT_DEBUG_GENERIC_COMMAND_DB_SUMMARY 3 +#define CNAT_DEBUG_GENERIC_COMMAND_USER_DB_PM 4 +#define CNAT_DEBUG_GET_CGN_DB_SUMMARY 5 + +typedef enum { + CNAT_DEBUG_GENERIC_COMMAND_DUMP_POLICY, + CNAT_DEBUG_GENERIC_COMMAND_DUMP_MAIN_DB, + CNAT_DEBUG_GENERIC_COMMAND_DUMP_USER_DB, + CNAT_DEBUG_GENERIC_COMMAND_DUMP_HASHES_DB, + CNAT_DEBUG_GENERIC_COMMAND_DUMP_VRF_MAP, + CNAT_DEBUG_GENERIC_COMMAND_DUMP_SUMMARY_DB, + CNAT_DEBUG_GENERIC_COMMAND_DUMP_STATS, + CNAT_DEBUG_GENERIC_COMMAND_CLEAR_STATS, + CNAT_DEBUG_GENERIC_COMMAND_DUMP_NODE_COUNTER, + CNAT_DEBUG_GENERIC_COMMAND_CLEAR_NODE_COUNTER, + CNAT_DEBUG_GENERIC_COMMAND_DUMP_CNAT_COUNTER, + CNAT_DEBUG_GENERIC_COMMAND_DUMP_VA, + CNAT_DEBUG_GENERIC_COMMAND_SHOW_CONFIG, + CNAT_DEBUG_GENERIC_COMMAND_SHOW_NFV9, + CNAT_DEBUG_GENERIC_COMMAND_SHOW_IVRF, + CNAT_DEBUG_GENERIC_COMMAND_SHOW_OVRF, + CNAT_DEBUG_SPP_LOG, + CNAT_DEBUG_GENERIC_COMMAND_DEBUG_OPTIONS, + CNAT_DEBUG_GENERIC_COMMAND_DUMP_DEBUG_LEVELS, + CNAT_DEBUG_GENERIC_COMMAND_DEBUG_FLAGS, + CNAT_READ_TEMP_SENSORS, + CNAT_BLOCK_OCTEON_SENSOR_READ, + CNAT_DEBUG_GENERIC_COMMAND_DUMP_MAIN_DB_SUMMARY, + CNAT_DEBUG_GENERIC_COMMAND_DUMP_USER_DB_SUMMARY, + CNAT_DEBUG_DUMP_6RD_STATS, + CNAT_DEBUG_TIMEOUT_DB_SUMMARY, + CNAT_NAT64_STFUL_DEBUG_COMMAND, + CNAT_DEBUG_SET_BULK_SIZE, + CNAT_DEBUG_SHOW_BULK_STAT, + CNAT_DEBUG_CLEAR_BULK_STAT, + CNAT_DEBUG_SHOW_BULK_ALLOC, + CNAT_DEBUG_NAT64, + CNAT_DEBUG_NAT44_IN2OUT_FRAG_STATS, +} cnat_debug_dump_type_t; + +typedef enum { + CNAT_DEBUG_FLAG_UDP_INSIDE_CHECKSUM_MODIFY, + CNAT_DEBUG_FLAG_UDP_OUTSIDE_CHECKSUM_MODIFY, + CNAT_DEBUG_FLAG_UDP_INSIDE_PACKET_DUMP, + CNAT_DEBUG_FLAG_UDP_OUTSIDE_PACKET_DUMP, +} cnat_debug_flag_type_t; + +typedef struct { + u16 spp_msg_id; + u8 rc; + u8 core; + u32 num_bytes; + u8 raw_data[0]; +} cnat_generic_command_resp; + +extern u32 db_free_entry (void * p); +#endif /*__CNAT_SHOW_RESPONSE_H__*/ diff --git a/plugins/vcgn-plugin/vcgn/cnat_syslog.c b/plugins/vcgn-plugin/vcgn/cnat_syslog.c new file mode 100644 index 00000000..91758f14 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_syslog.c @@ -0,0 +1,1787 @@ +/* + *------------------------------------------------------------------ + * cnat_syslog.c + * + * Copyright (c) 2011-2013 Cisco and/or its affiliates. + * 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 +#include "cnat_syslog.h" +#include "platform_common.h" +#include "cnat_db.h" +#include "cnat_log_common.h" +#include + +#define SYSLOG_DELIMITER ' ' +#define SYSLOG_FIELD_ABSENT '-' +/* #define SHOW_SYSLOG_TIMESTAMP 1 TO DO. Remove this later */ +/* + * Defining the below macro here for now. Assumption is, syslog packets + * are sent out via same channel as that of NFV9. + * Has to be overridden if this assumption is false. + */ +#define PLATFORM_SYSLOG_DISP_NODE_IDX PLATFORM_NFV9_DISP_NODE_IDX + +cnat_syslog_global_info_t cnat_syslog_global_info; +cnat_syslog_logging_info_t *cnat_syslog_logging_info_pool; +cnat_syslog_global_counters_t cnat_syslog_global_counter; +extern u32 syslog_debug_flag; + +#define CNAT_SYSLOG_DEBUG_CODE 2 + +#if CNAT_SYSLOG_DEBUG_CODE > 3 +#define SYSLOG_COND if(my_instance_number == 0) + +#define SYSLOG_DEBUG_PRINTF1(a) SYSLOG_COND printf(a); +#define SYSLOG_DEBUG_PRINTF2(a, b) SYSLOG_COND printf(a, b); +#define SYSLOG_DEBUG_PRINTF3(a, b, c) SYSLOG_COND printf(a, b, c); +#define SYSLOG_DEBUG_PRINTF4(a, b, c, d) SYSLOG_COND printf(a, b, c, d); + +#else + +#define SYSLOG_DEBUG_PRINTF1(a) +#define SYSLOG_DEBUG_PRINTF2(a, b) +#define SYSLOG_DEBUG_PRINTF3(a, b, c) +#define SYSLOG_DEBUG_PRINTF4(a, b, c, d) + +#endif + + +void syslog_params_show(u32 logging_index) +{ + cnat_syslog_logging_info_t *log_info __attribute__((unused)); + if(logging_index == EMPTY) { + PLATFORM_DEBUG_PRINT("\nSyslog logging not configured\n"); + return; + } + + log_info = cnat_syslog_logging_info_pool + logging_index; + + PLATFORM_DEBUG_PRINT("\nSyslog parameters --\n"); + PLATFORM_DEBUG_PRINT("IPV4 address: %x, port %d, max log size %d\n", + log_info->ipv4_address, + log_info->port, log_info->max_length_minus_max_record_size); + PLATFORM_DEBUG_PRINT("Host name: %s, priority %d", + log_info->header_hostname, log_info->header_priority); + +} + +/* Util function to copy a number as ASCII in to a buf in a + * faster way (should be faster than sprintf) + */ + +const unsigned char ascii_numbers[][3] = + { {'0', '0', '0'}, + {'1', '0', '0'}, + {'2', '0', '0'}, + {'3', '0', '0'}, + {'4', '0', '0'}, + {'5', '0', '0'}, + {'6', '0', '0'}, + {'7', '0', '0'}, + {'8', '0', '0'}, + {'9', '0', '0'}, + {'1', '0', '0'}, + {'1', '1', '0'}, + {'1', '2', '0'}, + {'1', '3', '0'}, + {'1', '4', '0'}, + {'1', '5', '0'}, + {'1', '6', '0'}, + {'1', '7', '0'}, + {'1', '8', '0'}, + {'1', '9', '0'}, + {'2', '0', '0'}, + {'2', '1', '0'}, + {'2', '2', '0'}, + {'2', '3', '0'}, + {'2', '4', '0'}, + {'2', '5', '0'}, + {'2', '6', '0'}, + {'2', '7', '0'}, + {'2', '8', '0'}, + {'2', '9', '0'}, + {'3', '0', '0'}, + {'3', '1', '0'}, + {'3', '2', '0'}, + {'3', '3', '0'}, + {'3', '4', '0'}, + {'3', '5', '0'}, + {'3', '6', '0'}, + {'3', '7', '0'}, + {'3', '8', '0'}, + {'3', '9', '0'}, + {'4', '0', '0'}, + {'4', '1', '0'}, + {'4', '2', '0'}, + {'4', '3', '0'}, + {'4', '4', '0'}, + {'4', '5', '0'}, + {'4', '6', '0'}, + {'4', '7', '0'}, + {'4', '8', '0'}, + {'4', '9', '0'}, + {'5', '0', '0'}, + {'5', '1', '0'}, + {'5', '2', '0'}, + {'5', '3', '0'}, + {'5', '4', '0'}, + {'5', '5', '0'}, + {'5', '6', '0'}, + {'5', '7', '0'}, + {'5', '8', '0'}, + {'5', '9', '0'}, + {'6', '0', '0'}, + {'6', '1', '0'}, + {'6', '2', '0'}, + {'6', '3', '0'}, + {'6', '4', '0'}, + {'6', '5', '0'}, + {'6', '6', '0'}, + {'6', '7', '0'}, + {'6', '8', '0'}, + {'6', '9', '0'}, + {'7', '0', '0'}, + {'7', '1', '0'}, + {'7', '2', '0'}, + {'7', '3', '0'}, + {'7', '4', '0'}, + {'7', '5', '0'}, + {'7', '6', '0'}, + {'7', '7', '0'}, + {'7', '8', '0'}, + {'7', '9', '0'}, + {'8', '0', '0'}, + {'8', '1', '0'}, + {'8', '2', '0'}, + {'8', '3', '0'}, + {'8', '4', '0'}, + {'8', '5', '0'}, + {'8', '6', '0'}, + {'8', '7', '0'}, + {'8', '8', '0'}, + {'8', '9', '0'}, + {'9', '0', '0'}, + {'9', '1', '0'}, + {'9', '2', '0'}, + {'9', '3', '0'}, + {'9', '4', '0'}, + {'9', '5', '0'}, + {'9', '6', '0'}, + {'9', '7', '0'}, + {'9', '8', '0'}, + {'9', '9', '0'}, + {'1', '0', '0'}, + {'1', '0', '1'}, + {'1', '0', '2'}, + {'1', '0', '3'}, + {'1', '0', '4'}, + {'1', '0', '5'}, + {'1', '0', '6'}, + {'1', '0', '7'}, + {'1', '0', '8'}, + {'1', '0', '9'}, + {'1', '1', '0'}, + {'1', '1', '1'}, + {'1', '1', '2'}, + {'1', '1', '3'}, + {'1', '1', '4'}, + {'1', '1', '5'}, + {'1', '1', '6'}, + {'1', '1', '7'}, + {'1', '1', '8'}, + {'1', '1', '9'}, + {'1', '2', '0'}, + {'1', '2', '1'}, + {'1', '2', '2'}, + {'1', '2', '3'}, + {'1', '2', '4'}, + {'1', '2', '5'}, + {'1', '2', '6'}, + {'1', '2', '7'}, + {'1', '2', '8'}, + {'1', '2', '9'}, + {'1', '3', '0'}, + {'1', '3', '1'}, + {'1', '3', '2'}, + {'1', '3', '3'}, + {'1', '3', '4'}, + {'1', '3', '5'}, + {'1', '3', '6'}, + {'1', '3', '7'}, + {'1', '3', '8'}, + {'1', '3', '9'}, + {'1', '4', '0'}, + {'1', '4', '1'}, + {'1', '4', '2'}, + {'1', '4', '3'}, + {'1', '4', '4'}, + {'1', '4', '5'}, + {'1', '4', '6'}, + {'1', '4', '7'}, + {'1', '4', '8'}, + {'1', '4', '9'}, + {'1', '5', '0'}, + {'1', '5', '1'}, + {'1', '5', '2'}, + {'1', '5', '3'}, + {'1', '5', '4'}, + {'1', '5', '5'}, + {'1', '5', '6'}, + {'1', '5', '7'}, + {'1', '5', '8'}, + {'1', '5', '9'}, + {'1', '6', '0'}, + {'1', '6', '1'}, + {'1', '6', '2'}, + {'1', '6', '3'}, + {'1', '6', '4'}, + {'1', '6', '5'}, + {'1', '6', '6'}, + {'1', '6', '7'}, + {'1', '6', '8'}, + {'1', '6', '9'}, + {'1', '7', '0'}, + {'1', '7', '1'}, + {'1', '7', '2'}, + {'1', '7', '3'}, + {'1', '7', '4'}, + {'1', '7', '5'}, + {'1', '7', '6'}, + {'1', '7', '7'}, + {'1', '7', '8'}, + {'1', '7', '9'}, + {'1', '8', '0'}, + {'1', '8', '1'}, + {'1', '8', '2'}, + {'1', '8', '3'}, + {'1', '8', '4'}, + {'1', '8', '5'}, + {'1', '8', '6'}, + {'1', '8', '7'}, + {'1', '8', '8'}, + {'1', '8', '9'}, + {'1', '9', '0'}, + {'1', '9', '1'}, + {'1', '9', '2'}, + {'1', '9', '3'}, + {'1', '9', '4'}, + {'1', '9', '5'}, + {'1', '9', '6'}, + {'1', '9', '7'}, + {'1', '9', '8'}, + {'1', '9', '9'}, + {'2', '0', '0'}, + {'2', '0', '1'}, + {'2', '0', '2'}, + {'2', '0', '3'}, + {'2', '0', '4'}, + {'2', '0', '5'}, + {'2', '0', '6'}, + {'2', '0', '7'}, + {'2', '0', '8'}, + {'2', '0', '9'}, + {'2', '1', '0'}, + {'2', '1', '1'}, + {'2', '1', '2'}, + {'2', '1', '3'}, + {'2', '1', '4'}, + {'2', '1', '5'}, + {'2', '1', '6'}, + {'2', '1', '7'}, + {'2', '1', '8'}, + {'2', '1', '9'}, + {'2', '2', '0'}, + {'2', '2', '1'}, + {'2', '2', '2'}, + {'2', '2', '3'}, + {'2', '2', '4'}, + {'2', '2', '5'}, + {'2', '2', '6'}, + {'2', '2', '7'}, + {'2', '2', '8'}, + {'2', '2', '9'}, + {'2', '3', '0'}, + {'2', '3', '1'}, + {'2', '3', '2'}, + {'2', '3', '3'}, + {'2', '3', '4'}, + {'2', '3', '5'}, + {'2', '3', '6'}, + {'2', '3', '7'}, + {'2', '3', '8'}, + {'2', '3', '9'}, + {'2', '4', '0'}, + {'2', '4', '1'}, + {'2', '4', '2'}, + {'2', '4', '3'}, + {'2', '4', '4'}, + {'2', '4', '5'}, + {'2', '4', '6'}, + {'2', '4', '7'}, + {'2', '4', '8'}, + {'2', '4', '9'}, + {'2', '5', '0'}, + {'2', '5', '1'}, + {'2', '5', '2'}, + {'2', '5', '3'}, + {'2', '5', '4'}, + {'2', '5', '5'} + }; + +inline static int +byte_to_ascii_decimal_unaligned( + unsigned char *ptr, unsigned char num) +{ + *ptr++ = ascii_numbers[num][0]; + if(PREDICT_FALSE(num < 10)) { + return 1; + } + *ptr++ = ascii_numbers[num][1]; + if(PREDICT_FALSE(num < 100)) { + return 2; + } + *ptr++ = ascii_numbers[num][2]; + return 3; +} + +/* Copies the dotted decimal format of ipv4 + * in to the space provided and + * returns the number of bytes copied + */ +inline static int __attribute__((unused)) +copy_ipv4_addr(unsigned char *ptr, u32 ipv4) +{ + unsigned char *temp = ptr; + temp += byte_to_ascii_decimal_unaligned(temp, (ipv4 >> 24)); + *temp++ = '.'; + temp += byte_to_ascii_decimal_unaligned(temp, ((ipv4 >> 16) & 0xFF)); + *temp++ = '.'; + temp += byte_to_ascii_decimal_unaligned(temp, ((ipv4 >> 8) & 0xFF)); + *temp++ = '.'; + temp += byte_to_ascii_decimal_unaligned(temp, (ipv4 & 0xFF)); + + return (temp - ptr); +} + +#ifdef TOBE_PORTED +/* + * edt: * * cnat_syslog_fill_ip_header + * + * Tries to fill the fields of the IP header before it + * is sent to the L3 infra node. + * + * Argument: cnat_syslog_logging_info_t *logging_info + * structure that contains the packet context + */ +inline +void cnat_syslog_fill_ip_header (cnat_syslog_logging_info_t *logging_info) +{ + spp_ctx_t *ctx; + + /* + * Fill in the IP header and port number of the Netflow collector + * The L3 Infra node will fill in the rest of the fields + */ + ctx = logging_info->current_logging_context; + fill_ip_n_udp_hdr(ctx, logging_info->ipv4_address, + logging_info->port, logging_info->pkt_length); + +} +#else +inline +void cnat_syslog_fill_ip_header (cnat_syslog_logging_info_t *logging_info) +{ + return; +} +#endif + +#ifndef TOBE_PORTED +void cnat_syslog_logging_init() +{ + return; +} + +void cnat_syslog_log_mapping_create(cnat_main_db_entry_t * db, + cnat_vrfmap_t *vrfmap) +{ + return; +} + +void cnat_syslog_log_mapping_delete(cnat_main_db_entry_t * db, + cnat_vrfmap_t *vrfmap) +{ + return; +} + +void cnat_syslog_ds_lite_port_limit_exceeded( + dslite_key_t * key, + dslite_table_entry_t *dslite_entry) +{ + return; +} + +void cnat_syslog_nat44_mapping_create(cnat_main_db_entry_t *db, + cnat_vrfmap_t *vrfmap, cnat_session_entry_t * sdb +#ifndef NO_BULK_LOGGING + , int bulk_alloc +#endif + ) +{ + return; +} + +/* Following are in cnat_util.c which are not ported */ +/* This function is defined in cnat_util.c which need to be ported */ +cnat_icmp_msg_t icmp_msg_gen_allowed () +{ + return 1; +} + +void cnat_syslog_nat44_mapping_delete(cnat_main_db_entry_t *db, + cnat_vrfmap_t *vrfmap, cnat_session_entry_t *sdb +#ifndef NO_BULK_LOGGING + , int bulk_alloc +#endif + ) +{ + return; +} + +u32 +cnat_get_unix_time_in_seconds (void) +{ + return 0; +} +#else /* TOBE_PORTED */ +void +cnat_syslog_dump_logging_context (u32 value1, + cnat_syslog_logging_info_t *logging_info, + u32 value2) +{ + u8 *pkt_ptr; + u32 i; + + if (PREDICT_TRUE(syslog_debug_flag == 0)) { + return; + } + /* + * Reduce the logging to few cores, to enable easier debugging + */ + if ((my_instance_number & 0x7) != 0) { + return; + } + printf("\nDumping %s packet at locn %d: time 0x%x", + (value2 == 1) ? "CURRENT" : "QUEUED", + value1, + cnat_get_unix_time_in_seconds()); + + printf("\ni_vrf 0x%x, ip_address 0x%x, port %d, pkt len %d", + 0 /* TO DP Add vrf like nfv9_logging_info->i_vrf */, + logging_info->ipv4_address, + logging_info->port, + logging_info->pkt_length); + printf("\n"); + + if (value2 == 1) { + pkt_ptr = logging_info->current_logging_context->packet_data; + } else { + pkt_ptr = logging_info->queued_logging_context->packet_data; + } + + /* + * Dump along with 8 bytes of SHIM header + */ + for (i = 0; i < + (logging_info->pkt_length + CNAT_NFV9_IP_HDR_OFFSET); + i = i + 1) { + u8 c1, c2, c3; + + if (i == 0) { + printf("\nL2_HEADER + SHIM_HEADER: \n"); + } else if (i == CNAT_NFV9_IP_HDR_OFFSET) { + printf("\nIP_HEADER: \n"); + } else if (i == CNAT_NFV9_UDP_HDR_OFFSET) { + printf("\nUDP_HEADER: \n"); + } else if (i == CNAT_NFV9_HDR_OFFSET) { + printf("\nSyslog content..\n"); + while(i < + (logging_info->pkt_length + CNAT_NFV9_HDR_OFFSET)) { + printf("%c", (u8)(*(pkt_ptr + i))); + i++; + if((u8)(*(pkt_ptr + i)) == '[') /* new record begins */ + printf("\n"); + } + return; + } + + c3 = *(pkt_ptr + i); + c2 = c3 & 0xf; + c1 = (c3 >> 4) & 0xf; + + printf("%c%c ", + ((c1 <= 9) ? (c1 + '0') : (c1 - 10 + 'a')), + ((c2 <= 9) ? (c2 + '0') : (c2 - 10 + 'a'))); + + } + + printf("\n"); +} + + +/* + * edt: * * cnat_syslog_send_pkt + * + * Tries to send a logging pkt. If the packet cannot be sent + * because of rewrite_output node cannot process it, queue + * it temporarily and try to send it later. + * + * Argument: cnat_syslog_logging_info_t *logging_info + * structure that contains the packet context + */ +inline +void cnat_syslog_send_pkt (cnat_syslog_logging_info_t *logging_info) +{ + spp_node_t *output_node; + + cnat_syslog_fill_ip_header(logging_info); + + output_node = spp_get_nodes() + + cnat_syslog_global_info.cnat_syslog_disp_node_index; + + cnat_syslog_dump_logging_context (2, logging_info, 1); + + if (PREDICT_TRUE(output_node->sf.nused < SPP_MAXDISPATCH)) { + /* + * Move the logging context to output node + */ + logging_info->current_logging_context->current_length = + logging_info->pkt_length; + PLATFORM_SET_CTX_RU_TX_FROM_NODE(logging_info->current_logging_context, \ + NODE_LOGGING); + spp_dispatch_make_node_runnable(output_node); + output_node->sf.ctxs[output_node->sf.nused++] = + logging_info->current_logging_context; + + if(PREDICT_FALSE(syslog_debug_flag > 10)) + printf("\nSyslog: 2. Sending Current packet\n"); + } else { + /* + * Queue the context into the logging_info structure, + * We will try to send it later. Currently, we will + * restrict to only one context queued. + */ + cnat_syslog_global_counter.downstream_constipation_count++; + if(PREDICT_FALSE(syslog_debug_flag > 10)) + printf("\nSyslog: 2. Downstream congestion \n"); + + /* + * Attach the current logging context which is full to the + * queued context list in logging_info structure + */ + logging_info->queued_logging_context = + logging_info->current_logging_context; + } + + /* + * Whether the context is queued or not, set the current context index + * to EMPTY, as the earlier context can no more be used to send + * more logging records. + */ + logging_info->current_logging_context = NULL; +} + + +/* + * edt: * * cnat_syslog_send_queued_pkt + * + * Tries to send a logging pkt that has been queued earlier + * because it could not be sent due to downstream constipation + * + * Argument: cnat_syslog_logging_info_t *logging_info + * structure that contains the packet context + */ +inline +void cnat_syslog_send_queued_pkt (cnat_syslog_logging_info_t *logging_info) +{ + spp_node_t *output_node; + + output_node = spp_get_nodes() + + cnat_syslog_global_info.cnat_syslog_disp_node_index; + + cnat_syslog_dump_logging_context(1, logging_info, 2); + + if(PREDICT_TRUE(output_node->sf.nused < SPP_MAXDISPATCH)) { + /* + * Move the logging context to output node + */ + /** This looks like a bug to me .. need to confirm ***** + logging_info->queued_logging_context->current_length = + nfv9_logging_info->pkt_length; ***/ + PLATFORM_SET_CTX_RU_TX_FROM_NODE(logging_info->queued_logging_context, + NODE_LOGGING) + spp_dispatch_make_node_runnable(output_node); + output_node->sf.ctxs[output_node->sf.nused++] = + logging_info->queued_logging_context; + + SYSLOG_DEBUG_PRINTF1("\nSYSLOG: 1. Sending Queued packet\n") + + /* + * Context has been queued, it will be freed after the pkt + * is sent. Clear this from the logging_context_info structure + */ + logging_info->queued_logging_context = NULL; + + } else { + cnat_syslog_global_counter.downstream_constipation_count++; + } +} + +/* + * edt: * * handle_pending_syslog_pkts + * + * Timer handler for sending any pending syslog record + * + */ +inline +void handle_pending_syslog_pkts() +{ + spp_node_t *output_node; + cnat_syslog_logging_info_t *my_logging_info = 0; + u32 current_timestamp = cnat_get_sys_up_time_in_ms(); + i16 sf_nused; + + output_node = spp_get_nodes() + + cnat_syslog_global_info.cnat_syslog_disp_node_index; + + sf_nused = output_node->sf.nused; + + pool_foreach (my_logging_info, cnat_syslog_logging_info_pool, ({ + /* + * Check if no more logging contexts can be queued + */ + if (PREDICT_FALSE(sf_nused >= SPP_MAXDISPATCH)) { + break; + } + if (my_logging_info->queued_logging_context) + cnat_syslog_send_queued_pkt (my_logging_info); + + if(my_logging_info->current_logging_context && + ((current_timestamp - + my_logging_info->current_logging_context_timestamp) + > 1000)) { + /* + * If there is a current logging context and timestamp + * indicates it is pending for long, send it out + * Also if there is a queued context send it out as well + */ + SYSLOG_DEBUG_PRINTF4("\nLOG_TIMER: queued %p, curr %p, sf_nused %d", + my_logging_info->queued_logging_context, + my_logging_info->current_logging_context, + sf_nused); + cnat_syslog_send_pkt(my_logging_info); + } + })); +} + +const unsigned char hex_numbers_single_digit[] = + { '0', '1', '2', '3', '4', '5', '6', '7', '8', + '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + +inline static int u16_to_ascii_decimal_aligned( + unsigned char *ptr, u16 num, u16 min_digits) +{ + /* The logic below is replicated in + * function u16_to_ascii_decimal_unaligned + * except the use of min_digits + * Replication is done to optimize run time + * if you fix a bug here, check u16_to_ascii_decimal_unaligned + * as well (and vice versa) + */ + unsigned char *temp = ptr; + int no_leading_zeros = 0; + + if(num > 9999 || min_digits == 5) { + *temp++ = hex_numbers_single_digit[num/10000]; + num = num%10000; + no_leading_zeros = 1; + } + + if(no_leading_zeros || num > 999 || min_digits == 4) { + *temp++ = hex_numbers_single_digit[num/1000]; + num = num%1000; + no_leading_zeros = 1; + } + + if(no_leading_zeros || num > 99 || min_digits == 3) { + *temp++ = hex_numbers_single_digit[num/100]; + num = num%100; + no_leading_zeros = 1; + } + + if(no_leading_zeros || num > 9 || min_digits == 2) { + *temp++ = hex_numbers_single_digit[num/10]; + num = num%10; + } + + *temp++ = hex_numbers_single_digit[num]; + + return temp-ptr; +} + +inline static int u16_to_ascii_decimal_unaligned( + unsigned char *ptr, u16 num) +{ + /* + * return u16_to_ascii_decimal_aligned(ptr, num, 0); + * should do the job.. however, to opimize the run time + * the code of u16_to_ascii_decimal_aligned is being + * repeated here without the use of min_digits + * if you fix a bug here, please check + * u16_to_ascii_decimal_aligned as well (and vice versa) + */ + unsigned char *temp = ptr; + int no_leading_zeros = 0; + + if(num > 9999) { + *temp++ = hex_numbers_single_digit[num/10000]; + num = num%10000; + no_leading_zeros = 1; + } + + if(no_leading_zeros || num > 999) { + *temp++ = hex_numbers_single_digit[num/1000]; + num = num%1000; + no_leading_zeros = 1; + } + + if(no_leading_zeros || num > 99) { + *temp++ = hex_numbers_single_digit[num/100]; + num = num%100; + no_leading_zeros = 1; + } + + if(no_leading_zeros || num > 9) { + *temp++ = hex_numbers_single_digit[num/10]; + num = num%10; + } + + *temp++ = hex_numbers_single_digit[num]; + + return temp-ptr; +} + +static int syslog_get_timestamp(unsigned char *ts) +{ + static const char *months[] = {"Jan ", "Feb ", "Mar ", "Apr ", "May ", + "Jun ", "Jul ", "Aug ", "Sep ", "Oct ", "Nov ", "Dec " }; + + unsigned char *temp = ts; + /* Inserts time stamp in the syslog format and returns lenght + * assumes that ts has sufficient space + */ + /* China Telecom has demanded that the time stamp has to be + * in the format '2011 Jun 7 12:34:08' + */ + time_t time = (time_t)cnat_get_unix_time_in_seconds(); + struct tm tm1; + + gmtime_r(&time, &tm1); + /* Now put the pieces together */ + /* Year */ + ts += u16_to_ascii_decimal_unaligned(ts, (tm1.tm_year + 1900)); + *ts++ = SYSLOG_DELIMITER; + /* Month */ + clib_memcpy(ts, months[tm1.tm_mon], 4); + ts += 4; /* DELIMITER taken care */ + /* day */ + ts += u16_to_ascii_decimal_unaligned(ts, tm1.tm_mday); + *ts++ = SYSLOG_DELIMITER; + /* hours */ + ts += u16_to_ascii_decimal_aligned(ts, tm1.tm_hour, 2); + *ts++ = ':'; + /* minutes */ + ts += u16_to_ascii_decimal_aligned(ts, tm1.tm_min, 2); + *ts++ = ':'; + /* seconds */ + ts += u16_to_ascii_decimal_aligned(ts, tm1.tm_sec, 2); + return ts - temp; +} + +/* Ensure that the order of the below array matches with + * syslog_service_type enum + */ +static char *syslog_service_string[] = { "NAT44", "DSLITE" }; + +/* Ensure that the order of below array matches with + * syslog_event_type_t enum + */ +typedef struct { + char *event_name; + int name_length; +} syslog_event_description_type; + +const static syslog_event_description_type sys_log_event[] = { + { "UserbasedA", 10 }, /* yes, 10 is strlen of "UserbasedA" */ + { "UserbasedW", 10 }, + { "SessionbasedA", 13 }, + { "SessionbasedW", 13 }, + { "SessionbasedAD", 14 }, + { "SessionbasedWD", 14 }, + { "Portblockrunout", 15 }, + { "TCPseqmismatch", 14}, + { "Invalid", 7 } +}; + +inline static int syslog_fill_header(const cnat_syslog_logging_info_t *log_info, + syslog_service_type_t s_type) +{ + /* Forms the syslog header and returns the lenght + * Assumes that header has sufficient space + */ + + /* Sample header (as agreed for China Telecom requirements -- + * <134> 1 2011 May 31 10:30:45 192.168.2.3 - - NAT44 - + */ + + unsigned char *temp, *header; + int count; + temp = header = (unsigned char *) + &(log_info->current_logging_context->packet_data[CNAT_NFV9_HDR_OFFSET]); + *temp++ = '<'; + temp += byte_to_ascii_decimal_unaligned(temp, + log_info->header_priority); + *temp++ = '>'; + *temp++ = SYSLOG_DELIMITER; + *temp++ = '1'; /* Syslog version -- always set to 1 */ + *temp++ = SYSLOG_DELIMITER; + temp += syslog_get_timestamp(temp); + *temp++ = SYSLOG_DELIMITER; + count = strlen(log_info->header_hostname); + clib_memcpy(temp, log_info->header_hostname, count); + temp += count; + *temp++ = SYSLOG_DELIMITER; + *temp++ = SYSLOG_FIELD_ABSENT; /* App name - nil value */ + *temp++ = SYSLOG_DELIMITER; + *temp++ = SYSLOG_FIELD_ABSENT; /* Proc ID - nil value for now */ + *temp++ = SYSLOG_DELIMITER; + /* Now the msg id */ + count = strlen(syslog_service_string[s_type]); + clib_memcpy(temp, syslog_service_string[s_type], count); + temp += count; + *temp++ = SYSLOG_DELIMITER; + *temp++ = SYSLOG_FIELD_ABSENT; /* No structured elements */ + *temp++ = SYSLOG_DELIMITER; +#ifdef SHOW_SYSLOG_TIMESTAMP + printf("\nSysLog TS: %s : Length %d", header, temp - header); +#endif /* SHOW_SYSLOG_TIMESTAMP */ + return temp-header; +} + +extern void cnat_logging_init(); + +/* one time call at the beginning */ +void cnat_syslog_logging_init() +{ + if(PREDICT_TRUE(cnat_syslog_global_info.cnat_syslog_init_done)) + return; /* Already done */ + + cnat_logging_init(); + cnat_syslog_global_info.cnat_syslog_disp_node_index = + spp_lookup_node_index(PLATFORM_SYSLOG_DISP_NODE_IDX); + ASSERT(cnat_syslog_global_info.cnat_syslog_disp_node_index != (u16)~0); + + cnat_syslog_global_info.cnat_syslog_init_done = 1; +} + +/* + * edt: * * cnat_syslog_create_logging_context + * + * Tries to create a logging context with packet buffer + * to send a new logging packet + * + * Argument: cnat_syslog_logging_info_t *logging_info + * structure that contains the logging info and will store + * the packet context as well. + */ +inline +void cnat_syslog_create_logging_context ( + cnat_syslog_logging_info_t *logging_info, + syslog_service_type_t s_type) +{ + spp_ctx_t *ctx; + + /* + * If queued_logging_context_index is non-EMPTY, we already have a logging + * packet queued to be sent. First try sending this before allocating + * a new context. We can have only one active packet context per + * logging_info structure + */ + + if (PREDICT_FALSE(logging_info->queued_logging_context != NULL)) { + cnat_syslog_send_queued_pkt(logging_info); + /* + * If we cannot still send the queued pkt, just return + * Downstream Constipation count would have increased anyway + */ + if (logging_info->queued_logging_context != NULL) { + cnat_syslog_global_counter.logging_context_creation_deferred_count++; + return; + } + } + + /* + * If no context can be allocated, return silently + * calling routine will handle updating the error counters + */ + if (spp_ctx_alloc(&ctx, 1) < 1) { + cnat_syslog_global_counter.logging_context_creation_fail_count++; + SYSLOG_DEBUG_PRINTF1("\nCould not allocate ctx for syslog"); + return; + } + + // Allocate packet buffer (used for AVSM currently) + PLATFORM_ALLOC_NFV9_PKT_BUFFER(ctx, 0); + + logging_info->current_logging_context = ctx; + + PLATFORM_SET_CTX_RU_TX_FROM_NODE(ctx, NODE_LOGGING); + + ctx->flags = SPP_CTX_END_OF_PACKET; + ctx->next_ctx_this_packet = (spp_ctx_t*) SPP_CTX_NO_NEXT_CTX; + ctx->current_header = &ctx->packet_data[CNAT_NFV9_HDR_OFFSET]; + + logging_info->pkt_length = syslog_fill_header(logging_info, s_type); + logging_info->pkt_length += (CNAT_NFV9_HDR_OFFSET - + CNAT_NFV9_IP_HDR_OFFSET); + logging_info->current_logging_context_timestamp = + cnat_get_sys_up_time_in_ms(); + +} + +inline static int u16_to_ascii_hex_unaligned( + unsigned char *ptr, u16 num) +{ + unsigned char nibble, *temp; + int no_leading_zeros = 0; + temp = ptr; + nibble = (num >> 12); + if(nibble) { + *temp++ = hex_numbers_single_digit[nibble]; + no_leading_zeros = 1; + } + + nibble = (num >> 8) & 0xF; + if(nibble || no_leading_zeros) { + *temp++ = hex_numbers_single_digit[nibble]; + no_leading_zeros = 1; + } + + nibble = (num >> 4) & 0xF; + if(nibble || no_leading_zeros) { + *temp++ = hex_numbers_single_digit[nibble]; + } + + *temp++ = hex_numbers_single_digit[num & 0xF]; + + return temp-ptr; +} + +inline static int ipv6_int_2_str(u32 ipv6[], unsigned char *ipv6_str) +{ +/* DC stands for Double Colon. + * Refer http://tools.ietf.org/html/rfc5952 for + * more details on text representations of + * IPV6 address + */ +#define DC_NOT_USED_YET 0 +#define DC_IN_USE 1 /* Zeros are skipped */ +#define DC_ALREADY_USED 2 /* Cannot skip zeros anymore */ + int i; + u16 *ipv6_temp = (u16 *)ipv6; + unsigned char *temp = ipv6_str; + int double_colon = DC_NOT_USED_YET; + for(i = 0; i < 7; i++) { + if(ipv6_temp[i]) { + ipv6_str += u16_to_ascii_hex_unaligned(ipv6_str, ipv6_temp[i]); + *ipv6_str++ = ':'; + if(double_colon == DC_IN_USE) { /* Cannot use DC anymore */ + double_colon = DC_ALREADY_USED; + } + } else { + if(double_colon == DC_IN_USE) { + /* Skip this zero as well */ + continue; + } else if((ipv6_temp[i+1]) + /* DC makes sense if there is more than one contiguous zero */ + || (double_colon != DC_NOT_USED_YET)) { + ipv6_str += u16_to_ascii_hex_unaligned(ipv6_str, + ipv6_temp[i]); + *ipv6_str++ = ':'; + } else { /* Start using DC */ + *ipv6_str++ = ':'; /* The 2nd colon */ + double_colon = DC_IN_USE; + } + } + } + if(ipv6_temp[7]) { + ipv6_str += u16_to_ascii_hex_unaligned(ipv6_str, ipv6_temp[7]); + } else if(double_colon != DC_IN_USE) { + *ipv6_str++ = '0'; + } + *ipv6_str = 0; + + return ipv6_str - temp; +} + +/* insert syslog record for nat44 */ + +void cnat_syslog_insert_nat44_record( + cnat_syslog_logging_info_t *log_info, + cnat_main_db_entry_t *db, cnat_vrfmap_t *vrfmap, + cnat_session_entry_t *sdb, int bulk_alloc, syslog_event_type_t e_type) +{ + /* This record should like this - + * [EventName + * < Translated Source IP> + * + * ] + */ + u32 original_source = db->in2out_key.k.ipv4; + u32 translated_ip = db->out2in_key.k.ipv4; + cnat_user_db_entry_t *udb = cnat_user_db + db->user_index; + unsigned char *temp, *record; + u32 network_order_ipv6[4]; + + SYSLOG_CONFIG_DEBUG_PRINTF(4,"In Function %s\n", __func__); + temp = record = &(log_info->current_logging_context->packet_data[ + CNAT_NFV9_IP_HDR_OFFSET + log_info->pkt_length]); + + if (PREDICT_FALSE(!udb)) { + SYSLOG_DEBUG_PRINTF1("\nnull udb!"); + return; + } + + /* Now we point to the location where record needs to be inserted */ + *record++ = '['; /* Open the record */ + + /* Copy the record type */ + clib_memcpy(record, sys_log_event[e_type].event_name, + sys_log_event[e_type].name_length); + record += sys_log_event[e_type].name_length; + *record++ = SYSLOG_DELIMITER; + + /* Copy the Protocol type */ + if(PREDICT_FALSE( + e_type == sessionbased_assign || e_type == sessionbased_withdraw || + e_type == sessionbased_assignD || e_type == sessionbased_withdrawD)) { + u16 my_proto_mask; + my_proto_mask = db->in2out_key.k.vrf & CNAT_PRO_MASK; + if(PREDICT_TRUE(my_proto_mask == CNAT_TCP)) { + *record++ = '6'; + } else if(PREDICT_TRUE(my_proto_mask == CNAT_UDP)) { + *record++ = '1'; + *record++ = '7'; + } else if(PREDICT_TRUE(my_proto_mask == CNAT_ICMP)) { + *record++ = '1'; + } else { /* Default, assume GRE (for PPTP) */ + *record++ = '4'; + *record++ = '7'; + } + } else { + *record++ = SYSLOG_FIELD_ABSENT; + } + *record++ = SYSLOG_DELIMITER; + + /* Copy the Original Source IP */ + record += copy_ipv4_addr(record, original_source); + *record++ = SYSLOG_DELIMITER; + + /* copy configured VRF NAME */ + clib_memcpy(record, log_info->vrf_name, log_info->vrf_name_len); + record += log_info->vrf_name_len; + *record++ = SYSLOG_DELIMITER; + + /* No IPV6 source address for nat44 */ + *record++ = SYSLOG_FIELD_ABSENT; + *record++ = SYSLOG_DELIMITER; + + /* Copy the translated IP address */ + record += copy_ipv4_addr(record, translated_ip); + *record++ = SYSLOG_DELIMITER; + + /* Copy the Original port */ + if(e_type == sessionbased_assign || e_type == sessionbased_withdraw || + e_type == sessionbased_assignD || e_type == sessionbased_withdrawD) { + record += u16_to_ascii_decimal_unaligned( + record, db->in2out_key.k.port); + } else { + *record++ = SYSLOG_FIELD_ABSENT; + } + *record++ = SYSLOG_DELIMITER; + + /* Copy the start outside port */ + record += u16_to_ascii_decimal_unaligned(record, bulk_alloc); + *record++ = SYSLOG_DELIMITER; + + /* Copy the last outside port */ + if(e_type == userbased_assign || e_type == userbased_withdraw) { + record += u16_to_ascii_decimal_unaligned(record, + (bulk_alloc + BULKSIZE_FROM_VRFMAP(vrfmap) - 1)); + } else { + *record++ = SYSLOG_FIELD_ABSENT; + } + *record++ = SYSLOG_DELIMITER; + + /* Copy destination ip and port in case for DBL*/ + if(PREDICT_FALSE(e_type == sessionbased_assignD || e_type == sessionbased_withdrawD)) { + if(PREDICT_TRUE(sdb == NULL)) { + record += copy_ipv4_addr(record,db->dst_ipv4); + *record++ = SYSLOG_DELIMITER; + record += u16_to_ascii_decimal_unaligned(record, db->dst_port); + } else { + record += copy_ipv4_addr(record, sdb->v4_dest_key.k.ipv4); + *record++ = SYSLOG_DELIMITER; + record += u16_to_ascii_decimal_unaligned(record, sdb->v4_dest_key.k.port); + } + } else { + *record++ = '-'; + *record++ = SYSLOG_DELIMITER; + *record++ = '-'; + } + *record++ = SYSLOG_DELIMITER; + + *record++ = ']'; /* End of the reocrd */ + + log_info->pkt_length += record - temp; +} + +void cnat_syslog_insert_record( + cnat_syslog_logging_info_t *log_info, + cnat_main_db_entry_t *db, dslite_table_entry_t *dslite_entry, + cnat_session_entry_t *sdb, int bulk_alloc, syslog_event_type_t e_type) +{ + /* This record should like this - + * [EventName + * < Translated Source IP> + * + * ] + */ + u32 original_source = db->in2out_key.k.ipv4; + u32 translated_ip = db->out2in_key.k.ipv4; + cnat_user_db_entry_t *udb = cnat_user_db + db->user_index; + unsigned char *temp, *record; + u32 network_order_ipv6[4]; + + temp = record = &(log_info->current_logging_context->packet_data[ + CNAT_NFV9_IP_HDR_OFFSET + log_info->pkt_length]); + + if (PREDICT_FALSE(!udb)) { + SYSLOG_DEBUG_PRINTF1("\nnull udb!"); + return; + } + + /* Now we point to the location where record needs to be inserted */ + *record++ = '['; /* Open the record */ + + /* Copy the record type */ + clib_memcpy(record, sys_log_event[e_type].event_name, + sys_log_event[e_type].name_length); + record += sys_log_event[e_type].name_length; + *record++ = SYSLOG_DELIMITER; + + /* Copy the Protocol type */ + if(PREDICT_FALSE( + e_type == sessionbased_assign || e_type == sessionbased_withdraw || + e_type == sessionbased_assignD || e_type == sessionbased_withdrawD)) { + u16 my_proto_mask; + my_proto_mask = db->in2out_key.k.vrf & CNAT_PRO_MASK; + if(PREDICT_TRUE(my_proto_mask == CNAT_TCP)) { + *record++ = '6'; + } else if(PREDICT_TRUE(my_proto_mask == CNAT_UDP)) { + *record++ = '1'; + *record++ = '7'; + } else { + *record++ = '1'; + } + } else { + *record++ = SYSLOG_FIELD_ABSENT; + } + + *record++ = SYSLOG_DELIMITER; + + /* Copy the Original Source IP */ +#ifdef DSLITE_USER_IPV4 + record += copy_ipv4_addr(record, original_source); +#else + /* + * Do not include inside ipv4 address for B4 element level port limiting + */ + *record++ = SYSLOG_FIELD_ABSENT; +#endif + *record++ = SYSLOG_DELIMITER; + + /* copy configured VRF NAME */ + clib_memcpy(record, log_info->vrf_name, log_info->vrf_name_len); + record += log_info->vrf_name_len; + *record++ = SYSLOG_DELIMITER; + + /* Copy the IPV6 source address */ + /* CSCtt16960 Fix. */ + network_order_ipv6[0] = htonl(udb->ipv6[0]); + network_order_ipv6[1] = htonl(udb->ipv6[1]); + network_order_ipv6[2] = htonl(udb->ipv6[2]); + network_order_ipv6[3] = htonl(udb->ipv6[3]); + + inet_ntop(AF_INET6,network_order_ipv6,record,INET6_ADDRSTRLEN); + record += strlen(record); + *record++ = SYSLOG_DELIMITER; + + /* Copy the translated IP address */ + record += copy_ipv4_addr(record, translated_ip); + *record++ = SYSLOG_DELIMITER; + + /* Copy the Original port */ + if(e_type == sessionbased_assign || e_type == sessionbased_withdraw || + e_type == sessionbased_assignD || e_type == sessionbased_withdrawD) { + record += u16_to_ascii_decimal_unaligned( + record, db->in2out_key.k.port); + } else { + *record++ = SYSLOG_FIELD_ABSENT; + } + *record++ = SYSLOG_DELIMITER; + + /* Copy the start outside port */ + record += u16_to_ascii_decimal_unaligned(record, bulk_alloc); + *record++ = SYSLOG_DELIMITER; + + /* Copy the last outside port */ + if(e_type == userbased_assign || e_type == userbased_withdraw) { + record += u16_to_ascii_decimal_unaligned(record, + (bulk_alloc + BULKSIZE_FROM_VRFMAP(dslite_entry) - 1)); + } else { + *record++ = SYSLOG_FIELD_ABSENT; + } + *record++ = SYSLOG_DELIMITER; + + if(PREDICT_FALSE(e_type == sessionbased_assignD || e_type == sessionbased_withdrawD)) { + if(sdb == NULL) { + record += copy_ipv4_addr(record, db->dst_ipv4); + *record++ = SYSLOG_DELIMITER; + record += u16_to_ascii_decimal_unaligned(record, db->dst_port); + } else { + record += copy_ipv4_addr(record, sdb->v4_dest_key.k.ipv4); + *record++ = SYSLOG_DELIMITER; + record += u16_to_ascii_decimal_unaligned(record, sdb->v4_dest_key.k.port); + } + } else { + *record++ = '-'; + *record++ = SYSLOG_DELIMITER; + *record++ = '-'; + } + *record++ = SYSLOG_DELIMITER; + + *record++ = ']'; /* End of the reocrd */ + + log_info->pkt_length += record - temp; +} + +#define SYSLOG_PRECHECK(entry, s_type) \ + if(PREDICT_FALSE((entry)->syslog_logging_index == EMPTY)) { \ + SYSLOG_DEBUG_PRINTF1("\n1. Log Mapping failed") \ + return; \ + } \ + logging_info = \ + cnat_syslog_logging_info_pool + (entry)->syslog_logging_index; \ + if(PREDICT_FALSE(logging_info->current_logging_context == NULL)) { \ + cnat_syslog_create_logging_context(logging_info, s_type); \ + if(PREDICT_FALSE(logging_info->current_logging_context == NULL)) { \ + SYSLOG_DEBUG_PRINTF1("\n2. Log Mapping failed") \ + return; \ + } \ + } + +void cnat_syslog_nat44_mapping_create(cnat_main_db_entry_t *db, + cnat_vrfmap_t *vrfmap, cnat_session_entry_t * sdb +#ifndef NO_BULK_LOGGING + , int bulk_alloc +#endif + ) +{ + cnat_syslog_logging_info_t *logging_info = 0; + syslog_event_type_t e_type; + int start_port; + + SYSLOG_CONFIG_DEBUG_PRINTF(4,"In Function %s\n", __func__); + SYSLOG_PRECHECK(vrfmap, NAT44) + +#ifndef NO_BULK_LOGGING + if(bulk_alloc > 0) { /* new bulk alloc - use bulk add template */ + e_type = userbased_assign; + start_port = bulk_alloc; + } else if(bulk_alloc == CACHE_ALLOC_NO_LOG_REQUIRED) { + return; /* No logging required.. bulk port usage */ + } + else { /* Individual logging .. fall back to old method */ +#endif + if(vrfmap->syslog_logging_policy == SESSION_LOG_ENABLE) { + e_type = sessionbased_assignD; + } else { + e_type = sessionbased_assign; + } + start_port = db->out2in_key.k.port; +#ifndef NO_BULK_LOGGING + } +#endif + + cnat_syslog_insert_nat44_record(logging_info, db, vrfmap, sdb, + start_port, e_type); + + /* + * If we have exceeded the packet length, let us send the + * packet now. There is buffer of additional bytes beyond + * max_pkt_length to ensure that the last add/delete record + * can be stored safely. + */ + + if (PREDICT_FALSE(logging_info->pkt_length > + logging_info->max_length_minus_max_record_size)) { + cnat_syslog_send_pkt(logging_info); + } +} + +void cnat_syslog_ds_lite_mapping_create(cnat_main_db_entry_t *db, + dslite_table_entry_t *dslite_entry, cnat_session_entry_t *sdb +#ifndef NO_BULK_LOGGING + , int bulk_alloc +#endif + ) +{ + cnat_syslog_logging_info_t *logging_info = 0; + syslog_event_type_t e_type; + int start_port; + + SYSLOG_PRECHECK(dslite_entry, DSLite) + +#ifndef NO_BULK_LOGGING + if(bulk_alloc > 0) { /* new bulk alloc - use bulk add template */ + e_type = userbased_assign; + start_port = bulk_alloc; + } else if(bulk_alloc == CACHE_ALLOC_NO_LOG_REQUIRED) { + return; /* No logging required.. bulk port usage */ + } + else { /* Individual logging .. fall back to old method */ +#endif + if(PREDICT_FALSE(dslite_entry->syslog_logging_policy == SESSION_LOG_ENABLE)) { + e_type = sessionbased_assignD; + } else { + e_type = sessionbased_assign; + } + start_port = db->out2in_key.k.port; +#ifndef NO_BULK_LOGGING + } +#endif + + cnat_syslog_insert_record(logging_info, db, dslite_entry, sdb, + start_port, e_type); + + /* + * If we have exceeded the packet length, let us send the + * packet now. There is buffer of additional bytes beyond + * max_pkt_length to ensure that the last add/delete record + * can be stored safely. + */ + + if (PREDICT_FALSE(logging_info->pkt_length > + logging_info->max_length_minus_max_record_size)) { + cnat_syslog_send_pkt(logging_info); + } +} + +void cnat_syslog_nat44_mapping_delete(cnat_main_db_entry_t *db, + cnat_vrfmap_t *vrfmap, cnat_session_entry_t *sdb +#ifndef NO_BULK_LOGGING + , int bulk_alloc +#endif + ) +{ + cnat_syslog_logging_info_t *logging_info = 0; + syslog_event_type_t e_type; + int start_port; + + SYSLOG_CONFIG_DEBUG_PRINTF(4,"In Function %s\n", __func__); + SYSLOG_PRECHECK(vrfmap, NAT44) + +#ifndef NO_BULK_LOGGING + if(bulk_alloc > 0) { /* new bulk alloc - use bulk add template */ + e_type = userbased_withdraw; + start_port = bulk_alloc; + } else if(bulk_alloc == CACHE_ALLOC_NO_LOG_REQUIRED) { + return; /* No logging required.. bulk port usage */ + } + else { /* Individual logging .. fall back to old method */ +#endif + if(vrfmap->syslog_logging_policy == SESSION_LOG_ENABLE) { + e_type = sessionbased_withdrawD; + } else { + e_type = sessionbased_withdraw; + } + start_port = db->out2in_key.k.port; +#ifndef NO_BULK_LOGGING + } +#endif + cnat_syslog_insert_nat44_record(logging_info, db, vrfmap, sdb, + start_port, e_type); + /* + * If we have exceeded the packet length, let us send the + * packet now. There is buffer of additional bytes beyond + * max_pkt_length to ensure that the last add/delete record + * can be stored safely. + */ + if (PREDICT_FALSE(logging_info->pkt_length > + logging_info->max_length_minus_max_record_size)) { + cnat_syslog_send_pkt(logging_info); + } +} + +void cnat_syslog_ds_lite_mapping_delete(cnat_main_db_entry_t *db, + dslite_table_entry_t *dslite_entry, cnat_session_entry_t *sdb +#ifndef NO_BULK_LOGGING + , int bulk_alloc +#endif + ) +{ + cnat_syslog_logging_info_t *logging_info = 0; + syslog_event_type_t e_type; + int start_port; + + SYSLOG_PRECHECK(dslite_entry, DSLite) + +#ifndef NO_BULK_LOGGING + if(bulk_alloc > 0) { /* new bulk alloc - use bulk add template */ + e_type = userbased_withdraw; + start_port = bulk_alloc; + } else if(bulk_alloc == CACHE_ALLOC_NO_LOG_REQUIRED) { + return; /* No logging required.. bulk port usage */ + } + else { /* Individual logging .. fall back to old method */ +#endif + if(PREDICT_FALSE(dslite_entry->syslog_logging_policy == SESSION_LOG_ENABLE)) { + e_type = sessionbased_withdrawD; + } else { + e_type = sessionbased_withdraw; + } + start_port = db->out2in_key.k.port; +#ifndef NO_BULK_LOGGING + } +#endif + cnat_syslog_insert_record(logging_info, db, dslite_entry, sdb, + start_port, e_type); + + /* + * If we have exceeded the packet length, let us send the + * packet now. There is buffer of additional bytes beyond + * max_pkt_length to ensure that the last add/delete record + * can be stored safely. + */ + + if (PREDICT_FALSE(logging_info->pkt_length > + logging_info->max_length_minus_max_record_size)) { + cnat_syslog_send_pkt(logging_info); + } +} + +void cnat_syslog_dslite_insert_port_exceeded( + cnat_syslog_logging_info_t *log_info, + dslite_key_t * key) +{ + /* This record should like this - + * [Portblockrunout + * - - - - -] + */ + u32 network_order_ipv6[4]; + unsigned char *temp, *record; + + temp = record = &(log_info->current_logging_context->packet_data[ + CNAT_NFV9_IP_HDR_OFFSET + log_info->pkt_length]); + + /* Now we point to the location where record needs to be inserted */ + *record++ = '['; /* Open the record */ + + /* Copy the record type */ + clib_memcpy(record, sys_log_event[port_block_runout].event_name, + sys_log_event[port_block_runout].name_length); + record += sys_log_event[port_block_runout].name_length; + *record++ = SYSLOG_DELIMITER; + + u16 my_proto_mask; + my_proto_mask = key->ipv4_key.k.vrf & CNAT_PRO_MASK; + if(PREDICT_TRUE(my_proto_mask == CNAT_TCP)) { + *record++ = '6'; + } else if(PREDICT_TRUE(my_proto_mask == CNAT_UDP)) { + *record++ = '1'; + *record++ = '7'; + } else { + *record++ = '1'; + } + *record++ = SYSLOG_DELIMITER; + + /* Copy the Original Source IP */ + record += copy_ipv4_addr(record, key->ipv4_key.k.ipv4); + *record++ = SYSLOG_DELIMITER; + + /* copy configured VRF NAME */ + clib_memcpy(record, log_info->vrf_name, log_info->vrf_name_len); + record += log_info->vrf_name_len; + *record++ = SYSLOG_DELIMITER; + + /* Copy the IPV6 source address */ + network_order_ipv6[0] = htonl(key->ipv6[0]); + network_order_ipv6[1] = htonl(key->ipv6[1]); + network_order_ipv6[2] = htonl(key->ipv6[2]); + network_order_ipv6[3] = htonl(key->ipv6[3]); + + inet_ntop(AF_INET6,network_order_ipv6,record,INET6_ADDRSTRLEN); + record += strlen(record); + *record++ = SYSLOG_DELIMITER; + + *record++ = SYSLOG_FIELD_ABSENT; /* No translated source ip */ + *record++ = SYSLOG_DELIMITER; + + record += u16_to_ascii_decimal_unaligned( + record, key->ipv4_key.k.port); + *record++ = SYSLOG_DELIMITER; + + *record++ = SYSLOG_FIELD_ABSENT; /* No translated start port */ + *record++ = SYSLOG_DELIMITER; + + *record++ = SYSLOG_FIELD_ABSENT; /* No translated end port */ + *record++ = SYSLOG_DELIMITER; + + /*No Destination Info*/ + *record++ = '-'; + *record++ = SYSLOG_DELIMITER; + *record++ = '-'; + *record++ = SYSLOG_DELIMITER; + + *record++ = ']'; /* End of the reocrd */ + + log_info->pkt_length += record - temp; +} + +void cnat_syslog_ds_lite_port_limit_exceeded( + dslite_key_t * key, + dslite_table_entry_t *dslite_entry) +{ + cnat_syslog_logging_info_t *logging_info = 0; + + SYSLOG_PRECHECK(dslite_entry, DSLite) + + cnat_syslog_dslite_insert_port_exceeded(logging_info, key); + + /* + * If we have exceeded the packet length, let us send the + * packet now. There is buffer of additional bytes beyond + * max_pkt_length to ensure that the last add/delete record + * can be stored safely. + */ + + if (PREDICT_FALSE(logging_info->pkt_length > + logging_info->max_length_minus_max_record_size)) { + cnat_syslog_send_pkt(logging_info); + } +} + +void cnat_syslog_nat44_insert_port_exceeded( + cnat_syslog_logging_info_t *log_info, + cnat_key_t * key) +{ + /* This record should like this - + * [Portblockrunout + * - - - - - -] + */ + unsigned char *temp, *record; + + temp = record = &(log_info->current_logging_context->packet_data[ + CNAT_NFV9_IP_HDR_OFFSET + log_info->pkt_length]); + + /* Now we point to the location where record needs to be inserted */ + *record++ = '['; /* Open the record */ + + /* Copy the record type */ + clib_memcpy(record, sys_log_event[port_block_runout].event_name, + sys_log_event[port_block_runout].name_length); + record += sys_log_event[port_block_runout].name_length; + *record++ = SYSLOG_DELIMITER; + + u16 my_proto_mask; + my_proto_mask = key->k.vrf & CNAT_PRO_MASK; + if(PREDICT_TRUE(my_proto_mask == CNAT_TCP)) { + *record++ = '6'; + } else if(PREDICT_TRUE(my_proto_mask == CNAT_UDP)) { + *record++ = '1'; + *record++ = '7'; + } else { + *record++ = '1'; + } + *record++ = SYSLOG_DELIMITER; + + /* Copy the Original Source IP */ + record += copy_ipv4_addr(record, key->k.ipv4); + *record++ = SYSLOG_DELIMITER; + + /* copy configured VRF NAME */ + clib_memcpy(record, log_info->vrf_name, log_info->vrf_name_len); + record += log_info->vrf_name_len; + *record++ = SYSLOG_DELIMITER; + + /* No IPV6 source address for nat44 */ + *record++ = '-'; + *record++ = SYSLOG_DELIMITER; + + *record++ = '-'; /* No translated source ip */ + *record++ = SYSLOG_DELIMITER; + + record += u16_to_ascii_decimal_unaligned( + record, key->k.port); + *record++ = SYSLOG_DELIMITER; + + *record++ = '-'; /* No translated start port */ + *record++ = SYSLOG_DELIMITER; + + *record++ = '-'; /* No translated end port */ + *record++ = SYSLOG_DELIMITER; + + /*No Destination Info*/ + *record++ = '-'; + *record++ = SYSLOG_DELIMITER; + *record++ = '-'; + *record++ = SYSLOG_DELIMITER; + + *record++ = ']'; /* End of the reocrd */ + + log_info->pkt_length += record - temp; +} + +void cnat_syslog_nat44_port_limit_exceeded( + cnat_key_t * key, + cnat_vrfmap_t *vrfmap) +{ + cnat_syslog_logging_info_t *logging_info = 0; + + SYSLOG_PRECHECK(vrfmap, NAT44) + + cnat_syslog_nat44_insert_port_exceeded(logging_info, key); + + /* + * If we have exceeded the packet length, let us send the + * packet now. There is buffer of additional bytes beyond + * max_pkt_length to ensure that the last add/delete record + * can be stored safely. + */ + + if (PREDICT_FALSE(logging_info->pkt_length > + logging_info->max_length_minus_max_record_size)) { + cnat_syslog_send_pkt(logging_info); + } +} + +void cnat_syslog_nat44_insert_tcp_seq_mismatch( + cnat_syslog_logging_info_t *log_info, + cnat_main_db_entry_t *db) +{ + /* This record should like this - + * [TCPseqmismatch + * - - - -] + */ + unsigned char *temp, *record; + + temp = record = &(log_info->current_logging_context->packet_data[ + CNAT_NFV9_IP_HDR_OFFSET + log_info->pkt_length]); + + /* Now we point to the location where record needs to be inserted */ + *record++ = '['; /* Open the record */ + + /* Copy the record type */ + clib_memcpy(record, sys_log_event[tcp_seq_mismatch].event_name, + sys_log_event[tcp_seq_mismatch].name_length); + record += sys_log_event[tcp_seq_mismatch].name_length; + *record++ = SYSLOG_DELIMITER; + + /* Next field is TCP */ + *record++ = '6'; + *record++ = SYSLOG_DELIMITER; + + /* Copy the Original Source IP */ + record += copy_ipv4_addr(record, db->in2out_key.k.ipv4); + *record++ = SYSLOG_DELIMITER; + + /* copy configured VRF NAME */ + clib_memcpy(record, log_info->vrf_name, log_info->vrf_name_len); + record += log_info->vrf_name_len; + *record++ = SYSLOG_DELIMITER; + + /* No IPV6 source address for nat44 */ + *record++ = '-'; + *record++ = SYSLOG_DELIMITER; + + record += copy_ipv4_addr(record, db->out2in_key.k.ipv4); + *record++ = SYSLOG_DELIMITER; + + record += u16_to_ascii_decimal_unaligned( + record, db->in2out_key.k.port); + *record++ = SYSLOG_DELIMITER; + + record += u16_to_ascii_decimal_unaligned( + record, db->out2in_key.k.port); + *record++ = SYSLOG_DELIMITER; + + *record++ = '-'; /* No translated end port */ + *record++ = SYSLOG_DELIMITER; + + /*No Destination Info*/ + *record++ = '-'; + *record++ = SYSLOG_DELIMITER; + *record++ = '-'; + *record++ = SYSLOG_DELIMITER; + + *record++ = ']'; /* End of the reocrd */ + + log_info->pkt_length += record - temp; +} + +void cnat_syslog_nat44_tcp_seq_mismatch( + cnat_main_db_entry_t *db, + cnat_vrfmap_t *vrfmap) +{ + cnat_syslog_logging_info_t *logging_info = 0; + + SYSLOG_PRECHECK(vrfmap, NAT44) + + cnat_syslog_nat44_insert_tcp_seq_mismatch(logging_info, db); + + /* + * If we have exceeded the packet length, let us send the + * packet now. There is buffer of additional bytes beyond + * max_pkt_length to ensure that the last add/delete record + * can be stored safely. + */ + + if (PREDICT_FALSE(logging_info->pkt_length > + logging_info->max_length_minus_max_record_size)) { + cnat_syslog_send_pkt(logging_info); + } +} +#endif diff --git a/plugins/vcgn-plugin/vcgn/cnat_syslog.h b/plugins/vcgn-plugin/vcgn/cnat_syslog.h new file mode 100644 index 00000000..931f4b9c --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_syslog.h @@ -0,0 +1,190 @@ +/* + *------------------------------------------------------------------ + * cnat_syslog.h + * + * Copyright (c) 2011-2013 Cisco and/or its affiliates. + * 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 __CNAT_SYSLOG_H__ +#define __CNAT_SYSLOG_H__ + +#include +#include +#include +#include + +#include "cnat_db.h" +#include "nat64_db.h" +#include "cnat_log_common.h" +#include "dslite_defs.h" + +#define SYSLOG_CONFIG_DEBUG_PRINTF(level, ...) \ + if (config_debug_level > level) PLATFORM_DEBUG_PRINT(__VA_ARGS__); + + +/* one time call at the beginning */ +void cnat_syslog_logging_init(); + +/* + * unconditional call + * will check logging config inside + */ +void cnat_syslog_log_mapping_create(cnat_main_db_entry_t * db, + cnat_vrfmap_t *vrfmap); + +/* + * unconditional call + * will check logging config inside + */ +void cnat_syslog_log_mapping_delete(cnat_main_db_entry_t * db, + cnat_vrfmap_t *vrfmap); + +void cnat_syslog_ds_lite_mapping_create(cnat_main_db_entry_t *db, + dslite_table_entry_t *dslite_entry, cnat_session_entry_t *sdb +#ifndef NO_BULK_LOGGING + , int bulk_alloc +#endif + ); + +void cnat_syslog_ds_lite_port_limit_exceeded( + dslite_key_t * key, + dslite_table_entry_t *dslite_entry); + +#define SYSLOG_TIMESTAMP_LENGTH 20 + +#define CNAT_SYSLOG_VERSION_NUMBER 1 +#define CNAT_SYSLOG_PRIORITY 16*8+6 +/* facility = local0 + severity = info */ + +#define MAX_SYSLOG_HOSTNAME_LEN 32 + +/* 6 for priority + space + * 2 for version + space + * 21 YYYY MMM DD HH:MM:SS + space + * 33 for hostname + space + * 4 for App Name (-) + space + Proc ID (-) + space + * 7 for Msg ID (DSLite is the longest Msg ID so far + space + * 2 for Structured data (-) + space + */ +#define MAX_SYSLOG_HEADER_LEN 75 + +/* 18 for Event Name (Portblockrunout is the longest as of now) + * 3 for L4 (including space) + * 16 for original souce IP + space + * 33 for inside vrf name + space + * 40 for original source IPV6 + space + * 16 for translated source IP + space + * 6 for original port + space + * 6 for translated first source port + space + * 5 for translated last source port + * 2 for [] enclosure + */ +#define MAX_SYSLOG_RECORD_LEN 145 + +typedef enum { + NAT44, + DSLite +} syslog_service_type_t; + +typedef enum { + userbased_assign, + userbased_withdraw, + sessionbased_assign, + sessionbased_withdraw, + sessionbased_assignD, + sessionbased_withdrawD, + port_block_runout, + tcp_seq_mismatch, + max_syslog_event_type +} syslog_event_type_t; + +/* + * This structure store the Syslog Logging information on per + * collector basis. This structure is allocated from a pool and index + * to this structure is stored VRF MAP structures + */ +typedef struct { + /* + * nat64_id will be 0 for nat44 config and i_vrf_id, i_vrf will be 0 + * for nat64 config. Nat64_id will be used while nat64 collector is + * search and i_vrf* for nat44 collector + */ + /* Similarly for ds_lite, ds_lite_id will be used and nat64_id, + * ivrf_id shall be set to 0 + */ + u32 i_vrf_id; /* Inside VRF ID corresponding to this collector */ + u16 i_vrf; /* Inside VRF (uidb_index) corresponding to this collector */ + u16 ds_lite_id; /* DS Lite instance for this collector */ + u16 port; /* Destination port number of the collector */ + + /* + * This field determines the maximum size of the Syslog information + * that can be stored in a logging packet + */ + u16 max_length_minus_max_record_size; + u32 ipv4_address; /* Destination IP address of the collector */ + /* + * Timestamp in UNIX seconds corresponding to when the current + * logging packet was created + */ + u32 current_logging_context_timestamp; + + /* + * Indicates if the entry is already deleted + */ + u8 deleted; + + u8 header_priority; + u16 pkt_length; + + char header_hostname[MAX_SYSLOG_HOSTNAME_LEN]; + char vrf_name[VRF_NAME_LEN_STORED]; + u16 vrf_name_len; + u8 logging_policy; + /* + * current logging context + */ + spp_ctx_t *current_logging_context; + spp_ctx_t *queued_logging_context; + +} cnat_syslog_logging_info_t; + + +/* + * Global structure for CGN APP configuration + */ +typedef struct { + + u16 cnat_syslog_disp_node_index; + + /* + * Whether we have initialized the Syslog information + */ + u8 cnat_syslog_init_done; + +} cnat_syslog_global_info_t; + +typedef struct { + u64 logging_context_creation_fail_count; + u64 downstream_constipation_count; + u64 logging_context_creation_deferred_count; +} cnat_syslog_global_counters_t; + +extern cnat_syslog_logging_info_t *cnat_syslog_logging_info_pool; +extern cnat_syslog_global_info_t cnat_syslog_global_info; + +#define SYSLOG_DEF_PATH_MTU 1500 + +#endif /* __CNAT_SYSLOG_H__ */ diff --git a/plugins/vcgn-plugin/vcgn/cnat_util.c b/plugins/vcgn-plugin/vcgn/cnat_util.c new file mode 100644 index 00000000..c3697b6b --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_util.c @@ -0,0 +1,2256 @@ +/* + *------------------------------------------------------------------ + * cnat_util.c - cnat helpers + * + * Copyright (c) 2009-2014 Cisco and/or its affiliates. + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include "tcp_header_definitions.h" + +#if 0 +void spp_api_cnat_v4_config_dummy_t_handler +(spp_api_cnat_v4_config_dummy_t *mp); + +void spp_api_cnat_v4_config_dummy_max_t_handler +(spp_api_cnat_v4_config_dummy_max_t *mp); + +void spp_api_cnat_v4_config_icmp_timeout_t_handler +(spp_api_cnat_v4_config_icmp_timeout_t *mp); + +void spp_api_cnat_clear_db_request_t_handler +(spp_api_cnat_clear_db_request_t *mp); + +void spp_api_cnat_v4_debug_global_t_handler +(spp_api_cnat_v4_debug_global_t *mp); + +void spp_api_cnat_v4_show_outside_entry_req_t_handler +(spp_api_cnat_v4_show_outside_entry_req_t *mp); + +void spp_api_cnat_v4_show_inside_entry_req_t_handler +(spp_api_cnat_v4_show_inside_entry_req_t *mp); + +void spp_api_cnat_show_statistics_summary_req_t_handler +(spp_api_cnat_show_statistics_summary_req_t *mp); + +void cnat_db_create_db_entries_cmd (int argc, unsigned long *argv) +{ + int i, j ; + int nusers = 3000; + + cnat_db_key_bucket_t key_info; + cnat_main_db_entry_t *db; + cnat_gen_icmp_info info; + cnat_key_t dest_info_dummy; + + memset(&dest_info_dummy, 0, sizeof(cnat_key_t)); + printf ("Create %d users, 100 translations each...\n", nusers); + + for (i = 0; i < nusers; i++) { + for (j = 0; j < 100; j++) { + + key_info.k.k.vrf = CNAT_TCP | (1 & CNAT_VRF_MASK); + key_info.k.k.ipv4 = 0x0c000001+i; + key_info.k.k.port = 1024+j; + + db = cnat_get_main_db_entry_v2(&key_info, PORT_SINGLE, + PORT_TYPE_DYNAMIC, &info, &dest_info_dummy); + + if (db == 0) { + printf ("OOPS: cnat_main_db_create failed users %d trans %d\n", i, j); + return; /*jli*/ + } + + db->entry_expires = cnat_current_time; + + } + } +} + +void db_test_clear (int argc, unsigned long *argv) +{ + spp_api_cnat_clear_db_request_t mp; + + mp.wildcard = argv[0]; + mp.protocol = argv[1]; + mp.port_num = argv[2]; + mp.inside_vrf = argv[3]; + mp.ip_addr = argv[4]; + spp_api_cnat_clear_db_request_t_handler(&mp); +} + +/* test code*/ +void cnat_db_test_show (int argc, unsigned long *argv) +{ + + spp_api_cnat_v4_show_inside_entry_req_t mp1[2000]; + spp_api_cnat_v4_show_outside_entry_req_t mp2[30000]; + + if (argc > 1) { + if (argc != 7) { + printf("Usage: db test show dec((which)) dec((vrf)) dec((proto)) dec((ip)) dec((start_port)) dec((end_port)) dec((flags))\n"); + return; + } + + mp1[0].vrf_id = argv[1]; + mp1[0].protocol = argv[2];; + mp1[0].ipv4_addr = argv[3]; + mp1[0].start_port = argv[4]; + mp1[0].end_port = argv[5]; + mp1[0].flags = argv[6]; + mp1[0].all_entries = 0; + + if (argv[0] == 1) { + spp_api_cnat_v4_show_inside_entry_req_t_handler (&(mp1[0])); + } else { + spp_api_cnat_v4_show_outside_entry_req_t_handler (&(mp2[0])); + } + + return; + } else { + printf("inside entries \n"); + mp1[0].ipv4_addr = 0x016994CA; + mp1[0].vrf_id = 1; + mp1[0].all_entries = 0; + mp1[0].start_port = 32765; + mp1[0].end_port = 65535; + mp1[0].protocol = 2; + mp1[0].flags = 3; + + spp_api_cnat_v4_show_inside_entry_req_t_handler (&(mp1[0])); + + mp2[0].ipv4_addr = 0x640200c1; + mp2[0].vrf_id = 0; + mp2[0].start_port = 1025; + mp2[0].end_port = 62235; + mp2[0].protocol = 2; + mp2[0].flags = 3; + + spp_api_cnat_v4_show_outside_entry_req_t_handler (&(mp2[0])); + } + +#if 1 + { + spp_api_cnat_stats_node_mapping_t mp3[20000]; + spp_api_cnat_stats_counter_mapping_t mp4[20000]; + spp_api_cnat_stats_counter_values_t mp5[23000]; + + mp3[0].rc = 0; + spp_api_cnat_stats_node_mapping_t_handler (&mp3); + mp4[0].rc = 0; + spp_api_cnat_stats_counter_mapping_t_handler (&mp4); + + mp5[0].flag = 1; + spp_api_cnat_stats_counter_values_t_handler(&mp5); + } +#endif + +#if 0 + mp1.ipv4_addr = 0x0A010102; + mp1.vrf_id = 1; + mp1.all_entries = 1; + mp1.protocol = 1; + + spp_api_cnat_v4_show_inside_entry_req_t_handler (&mp1); + + + mp1.ipv4_addr = 0x0A010103; + mp1.vrf_id = 1; + mp1.all_entries = 1; + mp1.protocol = 2; + + spp_api_cnat_v4_show_inside_entry_req_t_handler (&mp1); + + mp6[0].inside_vrf_id = 1; + mp6[0].start_ipv4_address = 0x64020001; + mp6[0].end_ipv4_address = 0x64020101; + mp6[0].free_addr = 0; + mp6[0].flags = CNAT_TRANSLATION_ENTRY_STATIC; + + spp_api_cnat_v4_show_freeUsed_entry_req_t_handler(&mp6); + +#endif + printf("returned here"); + + return; +} + + + +void cnat_db_clear_all_entries (int argc, unsigned long *argv) +{ + cnat_main_db_entry_t * db; + u32 index; + + pool_header_t * p = vec_header(cnat_main_db, sizeof(pool_header_t) ); + + for(index = 0; index < vec_len(cnat_main_db); index++) { + + if ( !clib_bitmap_get(p->free_bitmap, index)) { + + db = cnat_main_db + index; + cnat_delete_main_db_entry_v2(db); + + } + } + +} + + +void spp_log_cmd (int argc, unsigned long *argv) +{ + u16 num_traces; + u16 error_code; + u16 num_args; + u32 arg[7]; + u8 i; + + num_traces = argv[0]; + + for (i = 0; i < num_traces; i++) { + error_code = argv[1 + 4*i]; + num_args = argv[2 + 4*i]; + arg[0] = argv[3 + 4*i]; + arg[1] = argv[4 + 4*i]; + + spp_printf(error_code, num_args, arg); + } +} + + +void cnat_db_create_random_entries (int argc, unsigned long *argv) +{ + + platform_cnat_db_create_random_entries(); +} + +#define MAX_DEPTH 10 + +void show_user_db_hash_chain_len() { + + u32 max_len, len, n, i, max_idx, index, used; + cnat_user_db_entry_t * udb; + u32 hash_depth[MAX_DEPTH]; + + memset(hash_depth, 0, sizeof(u32)*MAX_DEPTH); + + n = vec_len(cnat_user_hash); + + used = 0; + max_len = 0; + for(i=0;iuser_hash.next; + } + + if(len < (MAX_DEPTH-1) ) { + hash_depth[len]++; + } else { + hash_depth[MAX_DEPTH-1]++; + } + + if (max_len < len) { + max_len = len; + max_idx = cnat_user_hash[i].next; + } + } + + printf("Max user db hash length %u, total buckets %u used %u\n", + max_len, n, used); + + for( i=1; i<(MAX_DEPTH - 1); i++) { + printf("Hash chain len %02d, entries count %d\n", i, hash_depth[i]); + } + + printf("Hash chain len >%02d, entries count %d\n", + MAX_DEPTH-1, hash_depth[MAX_DEPTH-1]); + +} + +void show_main_db_hash_chain_len() { + + u32 max_len, len, n, i, max_idx, index, used; + cnat_main_db_entry_t * db; + u32 hash_depth[MAX_DEPTH]; + + memset(hash_depth, 0, sizeof(u32)*MAX_DEPTH); + + n = vec_len(cnat_in2out_hash); + + used = 0; + max_len = 0; + for(i=0;iin2out_hash.next; + } + + if(len < (MAX_DEPTH-1) ) { + hash_depth[len]++; + } else { + hash_depth[MAX_DEPTH-1]++; + } + + if (max_len < len) { + max_len = len; + max_idx = cnat_in2out_hash[i].next; + } + } + + printf("Max main db I2O hash length %u, total buckets %u used %u\n", + max_len, n, used); + + for( i=1; i<(MAX_DEPTH - 1); i++) { + printf("Hash chain len %02d, entries count %d\n", i, hash_depth[i]); + } + + printf("Hash chain len >%02d, entries count %d\n", + MAX_DEPTH-1, hash_depth[MAX_DEPTH-1]); + + + memset(hash_depth, 0, sizeof(u32)*MAX_DEPTH); + + n = vec_len(cnat_out2in_hash); + used = 0; + max_len = 0; + + for(i=0;iout2in_hash.next; + } + + if(len < (MAX_DEPTH-1) ) { + hash_depth[len]++; + } else { + hash_depth[MAX_DEPTH-1]++; + } + + if (max_len < len) { + max_len = len; + max_idx = cnat_in2out_hash[i].next; + } + } + + printf("Max main db O2I hash length %u, total buckets %u used %u\n", + max_len, n, used); + + for( i=1; i<(MAX_DEPTH - 1); i++) { + printf("Hash chain len %02d, entries count %d\n", i, hash_depth[i]); + } + + printf("Hash chain len >%02d, entries count %d\n", + MAX_DEPTH-1, hash_depth[MAX_DEPTH-1]); + + +} + +u32 db_free_entry (void * p) { + + pool_header_t * h; + u32 free; + + h = pool_header(p); + + free = p == 0 ? 0: vec_len(h->free_indices); + + return free; +} + +void cnat_db_summary (int argc, unsigned long *argv) { + + PLATFORM_DEBUG_PRINT("\n-----------------------------------------"); + PLATFORM_DEBUG_PRINT("\nSummary DB"); + PLATFORM_DEBUG_PRINT("\n-----------------------------------------\n"); + u32 count1, count2, i; +#ifndef NO_NAT64_DEF + extern void nat64_session_db_summary(); +#endif + /* main db active entry count*/ + count1 = vec_len(cnat_main_db); + count2 = db_free_entry(cnat_main_db); + + PLATFORM_DEBUG_PRINT("main db entries: total %u, active %u, free %u\n", count1, count1 - count2, count2); + + /* user db active entry count */ + count1 = vec_len(cnat_user_db); + count2 = db_free_entry(cnat_user_db); + + PLATFORM_DEBUG_PRINT("user db entries: total %u, active %u, free %u\n", count1, count1 - count2, count2); + + + /* user db active entry count */ +#ifndef NO_NAT64_DEF + nat64_session_db_summary(); +#endif + + /* main db hash i2o o2i usage count */ + count1 = 0; + count2 = 0; + + for (i=0; i< CNAT_MAIN_HASH_SIZE; i++) { + + if(cnat_in2out_hash[i].next != ~0) count1++; + if(cnat_out2in_hash[i].next != ~0) count2++; + + } + + PLATFORM_DEBUG_PRINT("main hash in2out: total %6u, used %u (%.2f%%)\n", + CNAT_MAIN_HASH_SIZE, count1, + (100.0*count1)/CNAT_MAIN_HASH_SIZE); + + PLATFORM_DEBUG_PRINT("main hash out2in: total %6u, used %u (%.2f%%)\n", + CNAT_MAIN_HASH_SIZE, count2, + (100.0 * count1)/CNAT_MAIN_HASH_SIZE); + + /* use db hashing usage count */ + + count1 = 0; + + for (i=0; i< CNAT_USER_HASH_SIZE; i++) { + if(cnat_user_hash[i].next != ~0) count1++; + } + + PLATFORM_DEBUG_PRINT("user db hash: total %6u, used %u (%.2f%%)\n", + CNAT_USER_HASH_SIZE, count1, + (100.0*count1)/CNAT_USER_HASH_SIZE); + + PLATFORM_DEBUG_PRINT("\nNull pointer exceptions:\n"); + PLATFORM_DEBUG_PRINT("packet_pool: null enq : %10u, null deq : %10u\n",null_enq_pkt, null_deq_pkt); + PLATFORM_DEBUG_PRINT("ctx_pool : null enq : %10u, null deq : %10u\n",null_enq_ctx, null_deq_ctx); + PLATFORM_DEBUG_PRINT("wqe_pool : null enq : %10u, null deq : %10u\n",null_enq_wqe, null_deq_wqe); + + PLATFORM_DEBUG_PRINT("\nReceived Packet Errors on SPI:\n"); + PLATFORM_DEBUG_PRINT("rcv_pkt_errs: %10u\n",rcv_pkt_errs); + + PLATFORM_DEBUG_PRINT("\nctx/sf allocation failure errors: \n"); +#ifndef CGN_PERF_SCALE_DEBUG + PLATFORM_DEBUG_PRINT("Warning: collection of error counts is disabled.\n"); + PLATFORM_DEBUG_PRINT("sf alloc errors: %10u, ctx alloc errors: %10u\n",sf_alloc_errs,ctx_alloc_errs); +#else + for(i=0;iTimestamp : %10u, sf errors: %10u, ctx errors: %10u\n",\ + i,err_cnt_arr[i].timestamp,\ + err_cnt_arr[i].sf_error_counter, \ + err_cnt_arr[i].ctx_error_counter); +#endif +} + +void cnat_db_hash_summary (int argc, unsigned long *argv) { + + show_main_db_hash_chain_len(); + + show_user_db_hash_chain_len(); +} + +/* + * cnat_port_alloc + * This function is now deprecated... + * + */ +#ifdef LB_PORT +int cnat_port_alloc (cnat_portmap_t *cnat_portmap, u16 *portmap_inuse, + int cnat_instance, + port_alloc_t atype, port_pair_t ptype, + int *index, u32 *ipv4_address, u16 *base_port) +#else +int cnat_port_alloc (cnat_portmap_t *cnat_portmap, u16 *portmap_inuse, + port_alloc_t atype, port_pair_t ptype, + int *index, u32 *ipv4_address, u16 *base_port) +#endif +{ + + return (0); +} + +/* + * cnat_port_free + * This function is now deprecated... + * + */ +#ifdef LB_PORT +void cnat_port_free (cnat_portmap_t *cnat_portmap, u16 *portmap_inuse, + int instance, int index, port_pair_t ptype, u16 base_port) +#else +void cnat_port_free (cnat_portmap_t *cnat_portmap, u16 *portmap_inuse, + int index, port_pair_t ptype, u16 base_port) +#endif +{ +} + +void spp_api_cnat_port_allocate_t_handler(spp_api_cnat_port_allocate_t *mp) +{ + int i, j, k1, k2; + int pm_index; + u32 ipv4_address; + u16 aport; + int rv; + char *out1, *out2, *out_f; + port_alloc_t pt1, pt2; + cnat_portmap_t *pm = 0; + u16 *pm_inuse = 0; + u32 *firstp =0; + u32 nr_ports =0; + u32 nodd_ports = 0; + u32 neven_ports = 0; +#ifdef LB_PORT + u32 my_instance = 1; +#endif + char out_r[12] = "allocated-r"; + char out_o[12] = "allocated-o"; + char out_e[12] = "allocated-e"; + + + /* + * this command is run after db create portmap + * vrf is hardcode to 1 + */ + + /* Already have a portmap vector for this VRF? */ + for (i = 0; i < vec_len(cnat_portmap_indices_by_vrf); i++) { + if (cnat_portmap_indices_by_vrf[i] == mp->vrf) { + pm = cnat_portmaps[i]; + pm_inuse = cnat_portmaps_inuse[i]; + goto found_portmaps; + } + } + + printf("need to run db create portmaps first 0x%d\n", + vec_len(cnat_portmap_indices_by_vrf)); + return; + +found_portmaps: + nr_ports = mp->nr_ports; + nodd_ports = mp->nodd_ports; + neven_ports = mp->neven_ports; + + if ((nr_ports + nodd_ports + neven_ports ) > (PORTS_PER_ADDR)) { + printf("invalid port# nr_ports %d + odd %d + even %d " + "should be less than 200 \n", nr_ports, nodd_ports, neven_ports); + return; + } + + /* + * first port + */ + firstp = nr_ports ? (&nr_ports) : (nodd_ports ? (&nodd_ports) : (&neven_ports)); + if (!(*firstp)) { + printf("invalid port# nr_ports %d odd %d even %d ", + nr_ports, nodd_ports, neven_ports); + } + out_f = nr_ports ? out_r : (nodd_ports ? out_o : out_e); + +#ifdef LB_PORT + rv = cnat_port_alloc (pm, pm_inuse, my_instance, + PORT_ALLOC_ANY, PORT_S_ODD, + &pm_index, &ipv4_address, &aport); +#else + rv = cnat_port_alloc (pm, pm_inuse, + PORT_ALLOC_ANY, PORT_S_ODD, + &pm_index, &ipv4_address, &aport); +#endif + + if (!rv) { + printf("failed-o\n"); + return; + } + printf("%s %8d %10x %8d\n", out_f, + pm_index, ipv4_address, aport); + + (*firstp)--; + + for (i=0; i < nr_ports; i++) { +#ifdef LB_PORT + rv = cnat_port_alloc (pm, pm_inuse, my_instance, + PORT_ALLOC_DIRECTED, PORT_SINGLE, + &pm_index, &ipv4_address, &aport); +#else + rv = cnat_port_alloc (pm, pm_inuse, + PORT_ALLOC_DIRECTED, PORT_SINGLE, + &pm_index, &ipv4_address, &aport); +#endif + if (rv) { + printf("%s %8d %10x %8d\n", out_r, + pm_index, ipv4_address, aport); + } else { + printf("%s failed\n", out_r); + return; + } + } + + if (nodd_ports > neven_ports) { + k1 = nodd_ports; + k2 = neven_ports; + pt1 = PORT_S_ODD; + pt2 = PORT_S_EVEN; + out1 = out_o; + out2 = out_e; + } else { + k1= neven_ports; + pt1 = PORT_S_EVEN; + k2 = nodd_ports; + pt2 = PORT_S_ODD; + out1 = out_e; + out2 = out_o; + } + + j = 0; + for (i=0; i < k1; i++) { +#ifdef LB_PORT + rv = cnat_port_alloc (pm, pm_inuse, my_instance, + PORT_ALLOC_DIRECTED, pt1, + &pm_index, &ipv4_address, &aport); +#else + rv = cnat_port_alloc (pm, pm_inuse, + PORT_ALLOC_DIRECTED, pt1, + &pm_index, &ipv4_address, &aport); +#endif + if (rv) { + printf("%s %8d %10x %8d\n", out1, + pm_index, ipv4_address, aport); + } else { + printf("%s failed\n", out1); + return; + } + + if (j < k2) { +#ifdef LB_PORT + rv = cnat_port_alloc (pm, pm_inuse, my_instance, + PORT_ALLOC_DIRECTED, pt2, + &pm_index, &ipv4_address, &aport); +#else + rv = cnat_port_alloc (pm, pm_inuse, + PORT_ALLOC_DIRECTED, pt2, + &pm_index, &ipv4_address, &aport); +#endif + + if (rv) { + printf("%s %8d %10x %8d\n", out2, + pm_index, ipv4_address, aport); + j++; + } else { + printf("%s failed\n", __FUNCTION__); + return; + } + } + } +} + +void cnat_db_summary_stats (int argc, unsigned long *argv) +{ + spp_api_cnat_show_statistics_summary_req_t mp[50000]; + + spp_api_cnat_show_statistics_summary_req_t_handler(&(mp[0])); +} + +void cnat_debug_global_test (int argc, unsigned long *argv) +{ + spp_api_cnat_v4_debug_global_t *mp; + spp_api_cnat_v4_config_dummy_t mp1; + spp_api_cnat_v4_config_icmp_timeout_t mp2[10]; + + mp = spp_msg_api_alloc (sizeof (*mp)); + memset(mp, 0, sizeof (*mp)); + + + mp->_spp_msg_id = SPP_API_CNAT_V4_DEBUG_GLOBAL; + mp->debug_flag = argv[0]; + + platform_send_msg(mp); + + mp2[0].default_value = 3; + + spp_api_cnat_v4_config_dummy_t_handler(&mp1); + spp_api_cnat_v4_config_icmp_timeout_t_handler(&(mp2[0])); +} + +void cnat_debug_inside_test (int argc, unsigned long *argv) +{ + + spp_api_cnat_v4_debug_in2out_private_addr_t *mp; + + mp = spp_msg_api_alloc (sizeof (*mp)); + memset(mp, 0, sizeof (*mp)); + + + mp->_spp_msg_id = SPP_API_CNAT_V4_DEBUG_IN2OUT_PRIVATE_ADDR; + + mp->start_addr = spp_host_to_net_byte_order_32(argv[0]); + mp->end_addr = spp_host_to_net_byte_order_32(argv[1]); + mp->i_vrf = spp_host_to_net_byte_order_16(argv[2]); + mp->debug_flag = spp_host_to_net_byte_order_32(argv[3]); + + platform_send_msg(mp); +} + +void cnat_config_ports_user (int argc, unsigned long *argv) +{ + spp_api_cnat_v4_config_port_limit_t *mp; + + mp = spp_msg_api_alloc (sizeof (*mp)); + memset(mp, 0, sizeof (*mp)); + + + mp->_spp_msg_id = SPP_API_CNAT_V4_CONFIG_PORT_LIMIT; + + mp->port_limit = spp_host_to_net_byte_order_16(argv[0]); + + platform_send_msg(mp); + +} + +void cnat_debug_outside_test (int argc, unsigned long *argv) +{ + + spp_api_cnat_v4_debug_out2in_public_addr_t *mp; + + mp = spp_msg_api_alloc (sizeof (*mp)); + memset(mp, 0, sizeof (*mp)); + + + mp->_spp_msg_id = SPP_API_CNAT_V4_DEBUG_OUT2IN_PUBLIC_ADDR; + + mp->start_addr = spp_host_to_net_byte_order_32(argv[0]); + mp->end_addr = spp_host_to_net_byte_order_32(argv[1]); + mp->o_vrf = spp_host_to_net_byte_order_16(argv[2]); + mp->debug_flag = spp_host_to_net_byte_order_32(argv[3]); + + platform_send_msg(mp); +} + +void cnat_debug_udp_dump (int argc, unsigned long *argv) +{ + + spp_api_cnat_p2mp_debug_request_t *mp; + + mp = spp_msg_api_alloc (sizeof (*mp)); + memset(mp, 0, sizeof (*mp)); + + + mp->_spp_msg_id = SPP_API_CNAT_P2MP_DEBUG_REQUEST; + mp->dump_type = + spp_host_to_net_byte_order_16(CNAT_DEBUG_GENERIC_COMMAND_DEBUG_FLAGS); + + if (spp_host_to_net_byte_order_32(argv[0]) == 1) { + mp->param[0] = spp_host_to_net_byte_order_32( + CNAT_DEBUG_FLAG_UDP_INSIDE_PACKET_DUMP); + } else { + mp->param[0] = spp_host_to_net_byte_order_32( + CNAT_DEBUG_FLAG_UDP_OUTSIDE_PACKET_DUMP); + } + mp->param[1] = spp_host_to_net_byte_order_32(argv[1]); + + platform_send_msg(mp); + + + +} + +void cnat_debug_udp_crc (int argc, unsigned long *argv) +{ + spp_api_cnat_p2mp_debug_request_t *mp; + + mp = spp_msg_api_alloc (sizeof (*mp)); + memset(mp, 0, sizeof (*mp)); + + + mp->_spp_msg_id = SPP_API_CNAT_P2MP_DEBUG_REQUEST; + mp->dump_type = + spp_host_to_net_byte_order_16(CNAT_DEBUG_GENERIC_COMMAND_DEBUG_FLAGS); + + if (spp_host_to_net_byte_order_32(argv[0]) == 1) { + mp->param[0] = spp_host_to_net_byte_order_32( + CNAT_DEBUG_FLAG_UDP_INSIDE_CHECKSUM_MODIFY); + } else { + mp->param[0] = spp_host_to_net_byte_order_32( + CNAT_DEBUG_FLAG_UDP_OUTSIDE_CHECKSUM_MODIFY); + } + mp->param[1] = spp_host_to_net_byte_order_32(argv[1]); + + platform_send_msg(mp); + +} + +void cnat_db_allocate_port_cmd (int argc, unsigned long *argv) +{ + spp_api_cnat_port_allocate_t *mp; + + + if (!argc) { + printf("no port# defined\n"); + return; + } + + if ( argc < 3) { + printf("no port# defined\n"); + return; + } + + if ((argc == 3) && (argv[0] == 0) && (argv[1] == 0) && (argv[2] == 0)) { + printf("no port# defined\n"); + return; + } + + mp = spp_msg_api_alloc (sizeof (*mp)); + memset(mp, 0, sizeof (*mp)); + + + mp->_spp_msg_id = SPP_API_CNAT_PORT_ALLOCATE; + mp->nr_ports = argv[0]; + mp->nodd_ports = argv[1]; + mp->neven_ports = argv[2]; + mp->vrf = 1; + + platform_send_msg(mp); +} + + +void spp_api_cnat_port_clear_t_handler(spp_api_cnat_port_clear_t *mp) +{ + u32 i; + cnat_portmap_t *pm = 0; + u16 *pm_inuse = 0; +#ifdef LB_PORT + u32 my_instance = 1; +#endif + + + /* + * this command is run after db create port + * vrf is hardcode to 1 + */ + + /* Already have a portmap vector for this VRF? */ + for (i = 0; i < vec_len(cnat_portmap_indices_by_vrf); i++) { + if (cnat_portmap_indices_by_vrf[i] == mp->vrf) { + pm = cnat_portmaps[i]; + pm_inuse = cnat_portmaps_inuse[i]; + goto found_portmaps; + } + } + + printf("portmap is not created 0x%d\n", + vec_len(cnat_portmap_indices_by_vrf)); + return; + +found_portmaps: + if (mp->pm_index >= vec_len(pm)) { + printf("invalid port_index 0x%d >= 0x%d\n", + mp->pm_index, vec_len(pm)); + return; + } + +#ifdef LB_PORT + cnat_port_free(pm, pm_inuse, my_instance, + mp->pm_index, PORT_SINGLE, mp->port); +#else + cnat_port_free(pm, pm_inuse, + mp->pm_index, PORT_SINGLE, mp->port); +#endif + printf("\n pm_index %d port %d is deleted\n", mp->pm_index, mp->port); +} + + + +void cnat_db_clear_port_cmd (int argc, unsigned long *argv) +{ + spp_api_cnat_port_clear_t *mp; + + if (!argc) { + printf("no port# defined\n"); + return; + } + + if ( argc < 2 ) { + printf("no port# defined\n"); + return; + } + + if (argc > 2) { + printf("too many port# defined\n"); + return; + } + + mp = spp_msg_api_alloc (sizeof (*mp)); + memset(mp, 0, sizeof (*mp)); + + + mp->_spp_msg_id = SPP_API_CNAT_PORT_CLEAR; + mp->pm_index = argv[0]; + mp->port = argv[1]; + mp->vrf = 1; + + platform_send_msg(mp); +} + + +void spp_api_cnat_v4_add_vrf_map_t_handler +(spp_api_cnat_v4_add_vrf_map_t *mp); + +void spp_api_cnat_v4_del_vrf_map_t_handler +(spp_api_cnat_v4_del_vrf_map_t *mp); + +void spp_api_cnat_v4_add_static_port_t_handler +(spp_api_cnat_v4_add_static_port_t *mp); + +void spp_api_cnat_v4_del_static_port_t_handler +(spp_api_cnat_v4_del_static_port_t *mp); + + +void cnat_db_create_vrfmap_cmd (int argc, unsigned long *argv) +{ + spp_api_cnat_v4_add_vrf_map_t *mp; + + if ((argc != 4)) { + printf("need right input\n"); + return; + } + + mp = spp_msg_api_alloc (sizeof (*mp)); + memset(mp, 0, sizeof (*mp)); + mp->_spp_msg_id = SPP_API_CNAT_V4_ADD_VRF_MAP; + mp->i_vrf = spp_host_to_net_byte_order_16(argv[0]); + mp->o_vrf = spp_host_to_net_byte_order_16(argv[1]); + mp->start_addr[0] = spp_host_to_net_byte_order_32(argv[2]); + mp->end_addr[0] = spp_host_to_net_byte_order_32(argv[3]); + + /* + * Some hardcoded values for the vrf ids + */ + mp->i_vrf_id = spp_host_to_net_byte_order_32(0x00000100 | mp->i_vrf); + mp->o_vrf_id = spp_host_to_net_byte_order_32(0x00000200 | mp->o_vrf); + + platform_send_msg(mp); +} + + +void cnat_db_delete_vrfmap_cmd (int argc, unsigned long *argv) +{ + spp_api_cnat_v4_del_vrf_map_t *mp; + + if (argc != 4) { + printf("need right input\n"); + return; + } + + mp = spp_msg_api_alloc (sizeof (*mp)); + memset(mp, 0, sizeof (*mp)); + mp->_spp_msg_id = SPP_API_CNAT_V4_DEL_VRF_MAP; + mp->i_vrf = spp_host_to_net_byte_order_16(argv[0]); + mp->start_addr[0] = spp_host_to_net_byte_order_32(argv[2]); + mp->end_addr[0] = spp_host_to_net_byte_order_32(argv[3]); + + platform_send_msg(mp); +} + +void cnat_db_add_svi_cmd (int argc, unsigned long *argv) +{ + spp_api_cnat_config_svi_params_t *mp; + + if (argc != 3) { + printf("need right input\n"); + return; + } + + + mp = spp_msg_api_alloc (sizeof (*mp)); + memset(mp, 0, sizeof (*mp)); + mp->_spp_msg_id = SPP_API_CNAT_CONFIG_SVI_PARAMS; + mp->uidb_index = spp_host_to_net_byte_order_16(argv[1]); + mp->svi_ipv4_addr = spp_host_to_net_byte_order_32(argv[2]); + platform_send_msg(mp); + return; +} + + + +void spp_api_cnat_port_create_t_handler(spp_api_cnat_port_create_t *mp) +{ + int i, j, k1, k2; + int my_index; + u32 ipv4_address; + u16 aport; + u32 pm_len =0; + cnat_errno_t rv; + u16 i_vrf; + char *out1, *out2, *out_f; + port_alloc_t pt1, pt2; + cnat_vrfmap_t *my_vrfmap; + cnat_portmap_v2_t *pm = 0; + u32 *firstp =0; + u32 nr_ports =0; + u32 nodd_ports = 0; + u32 neven_ports = 0; +#ifdef LB_PORT + u32 my_instance = 1; +#endif + char out_r[12] = "allocated-r"; + char out_o[12] = "allocated-o"; + char out_e[12] = "allocated-e"; +#ifndef NO_BULK_LOGGING + int nfv9_log_req; +#endif + + nr_ports = mp->nr_ports; + nodd_ports = mp->nodd_ports; + neven_ports = mp->neven_ports; + i_vrf = mp->vrf; + + /* + * this command is run after db create vrfmap + * or using vrf id in init function + */ + /* Already have a portmap vector for this VRF? */ + pool_foreach (my_vrfmap, cnat_map_by_vrf, ({ + if ((my_vrfmap->status == S_RUN) && + (my_vrfmap->i_vrf == i_vrf)) { + pm = my_vrfmap->portmap_list; + pm_len = vec_len(pm); + if (pm_len) { + goto found_portmaps; + } + } + })); + + printf("need to run db create vrfmaps first for this vrf0x%d\n", pm_len); + return; + +found_portmaps: + + if ((nr_ports + nodd_ports + neven_ports ) > (PORTS_PER_ADDR)) { + printf("invalid port# nr_ports %d + odd %d + even %d " + "should be less than 200 \n", nr_ports, nodd_ports, neven_ports); + return; + } + + /* + * first port + */ + firstp = nr_ports ? (&nr_ports) : (nodd_ports ? (&nodd_ports) : (&neven_ports)); + if (!(*firstp)) { + printf("invalid port# nr_ports %d odd %d even %d ", + nr_ports, nodd_ports, neven_ports); + } + out_f = nr_ports ? out_r : (nodd_ports ? out_o : out_e); + + rv = cnat_dynamic_port_alloc_v2 (pm, PORT_ALLOC_ANY, PORT_S_ODD, + &my_index, &ipv4_address, &aport, + cnat_static_port_range +#ifndef NO_BULK_LOGGING + , BULKSIZE_FROM_VRFMAP(my_vrfmap), + &nfv9_log_req +#endif + , 0, + &(my_vrfmap->rseed_ip) + ); + + if (rv != CNAT_SUCCESS) { + printf("failed-o\n"); + return; + } + printf("%s %8d %10x %8d\n", out_f, + my_index, ipv4_address, aport); + + (*firstp)--; + + for (i=0; i < nr_ports; i++) { + rv = cnat_dynamic_port_alloc_v2 (pm, PORT_ALLOC_DIRECTED, PORT_SINGLE, + &my_index, &ipv4_address, &aport, + cnat_static_port_range +#ifndef NO_BULK_LOGGING + , BULKSIZE_FROM_VRFMAP(my_vrfmap), + &nfv9_log_req +#endif + , 0, + &(my_vrfmap->rseed_ip) + ); + + if (rv == CNAT_SUCCESS) { + printf("%s %8d %10x %8d\n", out_r, + my_index, ipv4_address, aport); + } else { + printf("%s failed\n", __FUNCTION__); + return; + } + } + + if (nodd_ports > neven_ports) { + k1 = nodd_ports; + k2 = neven_ports; + pt1 = PORT_S_ODD; + pt2 = PORT_S_EVEN; + out1 = out_o; + out2 = out_e; + } else { + k1= neven_ports; + pt1 = PORT_S_EVEN; + k2 = nodd_ports; + pt2 = PORT_S_ODD; + out1 = out_e; + out2 = out_o; + } + + j = 0; + for (i=0; i < k1; i++) { + rv = cnat_dynamic_port_alloc_v2 (pm, PORT_ALLOC_DIRECTED, pt1, + &my_index, &ipv4_address, &aport, + cnat_static_port_range +#ifndef NO_BULK_LOGGING + , BULKSIZE_FROM_VRFMAP(my_vrfmap), + &nfv9_log_req +#endif + , 0, + &(my_vrfmap->rseed_ip) + ); + + if (rv == CNAT_SUCCESS) { + printf("%s %8d %10x %8d\n", out1, + my_index, ipv4_address, aport); + } else { + printf("%s failed\n", __FUNCTION__); + return; + } + + if (j < k2) { + rv = cnat_dynamic_port_alloc_v2 (pm, PORT_ALLOC_DIRECTED, pt2, + &my_index, &ipv4_address, &aport, + cnat_static_port_range +#ifndef NO_BULK_LOGGING + , BULKSIZE_FROM_VRFMAP(my_vrfmap), + &nfv9_log_req +#endif + , 0, + &(my_vrfmap->rseed_ip) + ); + + if (rv == CNAT_SUCCESS) { + printf("%s %8d %10x %8d\n", out2, + my_index, ipv4_address, aport); + j++; + } else { + printf("%s failed\n", __FUNCTION__); + return; + return; + } + } + } +} + + +void cnat_db_create_port_cmd (int argc, unsigned long *argv) +{ + spp_api_cnat_port_create_t *mp; + + if (argc != 4) { + printf("no proper input defined\n"); + return; + } + + if ((argv[0] == 0) && (argv[1] == 0) && (argv[2] == 0)) { + printf("no port# defined\n"); + return; + } + + mp = spp_msg_api_alloc (sizeof (*mp)); + memset(mp, 0, sizeof (*mp)); + + + mp->_spp_msg_id = SPP_API_CNAT_PORT_CREATE; + mp->nr_ports = argv[0]; + mp->nodd_ports = argv[1]; + mp->neven_ports = argv[2]; + mp->vrf = argv[3]; + + platform_send_msg(mp); +} + +void spp_api_cnat_port_delete_t_handler(spp_api_cnat_port_delete_t *mp) +{ + u32 pm_len; + cnat_vrfmap_t *my_vrfmap; + cnat_portmap_v2_t *pm = 0; + + u32 my_index, my_port; + u16 i_vrf; +#ifdef LB_PORT + u32 my_instance = 1; +#endif + + my_index = mp->pm_index; + my_port = mp->port; + i_vrf = mp->vrf; + + /* + * this command is run after db create port + */ + pool_foreach (my_vrfmap, cnat_map_by_vrf, ({ + if (my_vrfmap->i_vrf == i_vrf) { + pm = my_vrfmap->portmap_list; + pm_len = vec_len(pm); + if (pm_len) { + goto found_portmaps; + } + } + })); + + printf("portmap is not created 0x%d\n", + vec_len(cnat_portmap_indices_by_vrf)); + return; + +found_portmaps: + if (my_index >= pm_len) { + printf("invalid port_index 0x%d >= 0x%d\n", + my_index, pm_len); + return; + } + +#ifdef LB_PORT + cnat_port_free_v2(pm, my_instance, + my_index, PORT_SINGLE, mp->port,cnat_static_port_range); +#else + cnat_port_free_v2(pm, my_index, PORT_SINGLE, mp->port,cnat_static_port_range); +#endif + printf("\n pm_index %d port %d is deleted\n", mp->pm_index, mp->port); +} + +void cnat_db_delete_port_cmd (int argc, unsigned long *argv) +{ + spp_api_cnat_port_clear_t *mp; + + if (argc != 3) { + printf("no proper input defined\n"); + return; + } + + mp = spp_msg_api_alloc (sizeof (*mp)); + memset(mp, 0, sizeof (*mp)); + + + mp->_spp_msg_id = SPP_API_CNAT_PORT_DELETE; + mp->pm_index = argv[0]; + mp->port = argv[1]; + mp->vrf = argv[2]; + platform_send_msg(mp); +} + +void cnat_db_create_static_fwd_cmd (int argc, unsigned long *argv) +{ + spp_api_cnat_v4_add_static_port_t *mp; + + if (argc != 4) { + printf("need right input\n"); + return; + } + + mp = spp_msg_api_alloc (sizeof (*mp)); + memset(mp, 0, sizeof (*mp)); + mp->_spp_msg_id = SPP_API_CNAT_V4_ADD_STATIC_PORT; + mp->i_vrf = spp_host_to_net_byte_order_16(argv[0]); + mp->i_ip = spp_host_to_net_byte_order_32(argv[1]); + mp->i_port = spp_host_to_net_byte_order_16(argv[2]); + mp->proto = argv[3]; + + platform_send_msg(mp); + return; +} + +void cnat_db_create_static_fwd_stby_cmd (int argc, unsigned long *argv) +{ + spp_api_cnat_v4_add_static_port_t *mp; + + if (argc != 7) { + printf("need right input\n"); + return; + } + + mp = spp_msg_api_alloc (sizeof (*mp)); + memset(mp, 0, sizeof (*mp)); + mp->_spp_msg_id = SPP_API_CNAT_V4_ADD_STATIC_PORT; + mp->i_vrf = spp_host_to_net_byte_order_16(argv[0]); + mp->i_ip = spp_host_to_net_byte_order_32(argv[1]); + mp->i_port = spp_host_to_net_byte_order_16(argv[2]); + mp->proto = argv[3]; + mp->o_vrf_id = spp_host_to_net_byte_order_32(argv[4]); + mp->o_ip = spp_host_to_net_byte_order_32(argv[5]); + mp->o_port = spp_host_to_net_byte_order_16(argv[6]); + +printf("\ni_vrf %d, ip 0x%x, port %d, o_ip, port %d", mp->i_vrf, mp->i_ip, mp->i_port, mp->o_ip, mp->o_port); + + platform_send_msg(mp); + return; +} + +void cnat_db_delete_static_fwd_cmd (int argc, unsigned long *argv) +{ + spp_api_cnat_v4_del_static_port_t *mp; + + if (argc != 3) { + printf("need right input\n"); + return; + } + + mp = spp_msg_api_alloc (sizeof (*mp)); + memset(mp, 0, sizeof (*mp)); + mp->_spp_msg_id = SPP_API_CNAT_V4_DEL_STATIC_PORT; + mp->i_vrf = spp_host_to_net_byte_order_16(argv[0]); + mp->i_ip = spp_host_to_net_byte_order_32(argv[1]); + mp->i_port = spp_host_to_net_byte_order_16(argv[2]); + + platform_send_msg(mp); + return; +} + +void cnat_nfv9_create_cmd (int argc, unsigned long *argv) +{ + spp_api_cnat_v4_config_nfv9_logging_t *mp; + + if (argc < 3) { + printf("nfv9 create i_vrf ip_addr port [refresh_rate] [timeout] [mtu]"); + return; + } + + mp = spp_msg_api_alloc (sizeof (*mp)); + memset(mp, 0, sizeof (*mp)); + mp->_spp_msg_id = SPP_API_CNAT_V4_CONFIG_NFV9_LOGGING; + mp->enable = 1; + mp->i_vrf = spp_host_to_net_byte_order_16(argv[0]); + + mp->ipv4_address = spp_host_to_net_byte_order_32(argv[1]); + mp->port = spp_host_to_net_byte_order_16(argv[2]); + + if (argc > 3) { + mp->refresh_rate = spp_host_to_net_byte_order_16(argv[3]); + mp->timeout_rate = spp_host_to_net_byte_order_16(argv[4]); + mp->path_mtu = spp_host_to_net_byte_order_16(argv[5]); + } else { + mp->refresh_rate = spp_host_to_net_byte_order_16(1000); + mp->timeout_rate = spp_host_to_net_byte_order_16(30); + mp->path_mtu = spp_host_to_net_byte_order_16(1500); + } + platform_send_msg(mp); +} + +void cnat_delete_cgn (int argc, unsigned long *argv) +{ + void *mp_send; + spp_api_cnat_del_cgn_t *mp; + u32 mp_size; + + mp_size = sizeof(spp_api_cnat_del_cgn_t); + + mp = spp_msg_api_alloc(mp_size); + memset(mp, 0, mp_size); + + mp->_spp_msg_id = SPP_API_CNAT_DEL_CGN; + + mp_send = mp; + + platform_send_msg(mp); +} + +void cnat_debug_global_all (int argc, unsigned long *argv) +{ + spp_api_cnat_v4_debug_global_t *mp; + + mp = spp_msg_api_alloc (sizeof (*mp)); + memset(mp, 0, sizeof (*mp)); + + mp->_spp_msg_id = SPP_API_CNAT_V4_DEBUG_GLOBAL; + mp->debug_flag = CNAT_DEBUG_GLOBAL_ALL; + + platform_send_msg(mp); +} + +void cnat_debug_global_none (int argc, unsigned long *argv) +{ + spp_api_cnat_v4_debug_global_t *mp; + + mp = spp_msg_api_alloc (sizeof (*mp)); + memset(mp, 0, sizeof (*mp)); + + mp->_spp_msg_id = SPP_API_CNAT_V4_DEBUG_GLOBAL; + mp->debug_flag = CNAT_DEBUG_NONE; + + platform_send_msg(mp); +} + + +void cnat_bulk_cmd (int argc, unsigned long *argv) +{ + void *mp_send; + + if (argc < 1) { + printf("\nargc = %d", argc); + printf("\n1. bulk cmd [0=static-port, 1=bulk_vrf, 2=policy_knob]"); + return; + } + + + switch (argv[0]) { + case 0: + { + spp_api_cnat_v4_bulk_add_delete_static_port_t *mp; + spp_api_cnat_v4_add_static_port_t *mp_sp; + u32 mp_size = + sizeof(spp_api_cnat_v4_bulk_add_delete_static_port_t) + + (sizeof(spp_api_cnat_v4_add_static_port_t))*2; + + mp = spp_msg_api_alloc(mp_size); + memset(mp, 0, mp_size); + + mp->_spp_msg_id = SPP_API_CNAT_V4_BULK_ADD_DELETE_STATIC_PORT; + + mp->num_static_port_entries = spp_host_to_net_byte_order_32(3); + + mp_sp = (spp_api_cnat_v4_add_static_port_t *) &(mp->pad2); + + mp_sp->_spp_msg_id = spp_host_to_net_byte_order_16( + SPP_API_CNAT_V4_ADD_STATIC_PORT); + mp_sp->proto = 2; + mp_sp->i_vrf = spp_host_to_net_byte_order_16(0x1); + mp_sp->i_ip = spp_host_to_net_byte_order_32(0x11111111); + mp_sp->i_port = spp_host_to_net_byte_order_16(0x7777); + + mp_sp++; + + + mp_sp->_spp_msg_id = spp_host_to_net_byte_order_16( + SPP_API_CNAT_V4_ADD_STATIC_PORT); + mp_sp->proto = 1; + mp_sp->i_vrf = spp_host_to_net_byte_order_16(0x1); + mp_sp->i_ip = spp_host_to_net_byte_order_32(0x22222222); + mp_sp->i_port = spp_host_to_net_byte_order_16(0x6666); + + mp_sp++; + + + mp_sp->_spp_msg_id = spp_host_to_net_byte_order_16( + SPP_API_CNAT_V4_ADD_STATIC_PORT); + mp_sp->proto = 1; + mp_sp->i_vrf = spp_host_to_net_byte_order_16(0x1); + mp_sp->i_ip = spp_host_to_net_byte_order_32(0x33333333); + mp_sp->i_port = spp_host_to_net_byte_order_16(0x5555); + + mp_send = mp; + + } + break; + + case 1: + { + spp_api_cnat_v4_bulk_vrf_map_t *mp; + spp_api_cnat_v4_single_vrf_map_req *mp_sp; + + u32 mp_size = sizeof(spp_api_cnat_v4_bulk_vrf_map_t) + + (sizeof(spp_api_cnat_v4_single_vrf_map_req))*2; + + mp = spp_msg_api_alloc(mp_size); + memset(mp, 0, mp_size); + + mp->_spp_msg_id = SPP_API_CNAT_V4_BULK_VRF_MAP; + + mp->num_vrfmap_entries = spp_host_to_net_byte_order_32(3); + + mp_sp = (spp_api_cnat_v4_single_vrf_map_req *) + &(mp->vrf_policy_enable); + + mp_sp->i_vrf_id = spp_host_to_net_byte_order_32(0xe0000001); + mp_sp->o_vrf_id = spp_host_to_net_byte_order_32(0xe0000000); + mp_sp->i_vrf = spp_host_to_net_byte_order_16(0x1); + mp_sp->o_vrf = spp_host_to_net_byte_order_16(0x0); + mp_sp->start_addr = spp_host_to_net_byte_order_32(0x11111100); + mp_sp->end_addr = spp_host_to_net_byte_order_32(0x111111ff); + mp_sp->vrf_policy_enable = spp_host_to_net_byte_order_16(0x3); + mp_sp->tcp_mss_value = spp_host_to_net_byte_order_16(0x111); + mp_sp->vrf_nfv9_logging_ipv4_address = spp_host_to_net_byte_order_32(0x11000001); + mp_sp->vrf_nfv9_logging_udp_port = spp_host_to_net_byte_order_16(0x1001); + mp_sp->vrf_nfv9_refresh_rate = spp_host_to_net_byte_order_16(0x100); + mp_sp->vrf_nfv9_timeout_rate = spp_host_to_net_byte_order_16(0x10); + mp_sp->vrf_nfv9_path_mtu = spp_host_to_net_byte_order_16(0x100); + + mp_sp++; + + mp_sp->i_vrf_id = spp_host_to_net_byte_order_32(0xe0000002); + mp_sp->o_vrf_id = spp_host_to_net_byte_order_32(0xe0000000); + mp_sp->i_vrf = spp_host_to_net_byte_order_16(0x2); + mp_sp->o_vrf = spp_host_to_net_byte_order_16(0x0); + mp_sp->start_addr = spp_host_to_net_byte_order_32(0x22220000); + mp_sp->end_addr = spp_host_to_net_byte_order_32(0x2222ffff); + mp_sp->vrf_policy_enable = spp_host_to_net_byte_order_16(0x1); + mp_sp->tcp_mss_value = spp_host_to_net_byte_order_16(0x222); + mp_sp->vrf_nfv9_logging_ipv4_address = spp_host_to_net_byte_order_32(0x22000002); + mp_sp->vrf_nfv9_logging_udp_port = spp_host_to_net_byte_order_16(0x2002); + mp_sp->vrf_nfv9_refresh_rate = spp_host_to_net_byte_order_16(0x200); + mp_sp->vrf_nfv9_timeout_rate = spp_host_to_net_byte_order_16(0x20); + mp_sp->vrf_nfv9_path_mtu = spp_host_to_net_byte_order_16(0x200); + + mp_sp++; + + mp_sp->i_vrf_id = spp_host_to_net_byte_order_32(0xe0000003); + mp_sp->o_vrf_id = spp_host_to_net_byte_order_32(0xe0000007); + mp_sp->i_vrf = spp_host_to_net_byte_order_16(0x3); + mp_sp->o_vrf = spp_host_to_net_byte_order_16(0x7); + mp_sp->start_addr = spp_host_to_net_byte_order_32(0x33333000); + mp_sp->end_addr = spp_host_to_net_byte_order_32(0x33333fff); + mp_sp->vrf_policy_enable = spp_host_to_net_byte_order_16(0x1); + mp_sp->tcp_mss_value = spp_host_to_net_byte_order_16(0x333); + mp_sp->vrf_nfv9_logging_ipv4_address = spp_host_to_net_byte_order_32(0x33000003); + mp_sp->vrf_nfv9_logging_udp_port = spp_host_to_net_byte_order_16(0x3003); + mp_sp->vrf_nfv9_refresh_rate = spp_host_to_net_byte_order_16(0x300); + mp_sp->vrf_nfv9_timeout_rate = spp_host_to_net_byte_order_16(0x30); + mp_sp->vrf_nfv9_path_mtu = spp_host_to_net_byte_order_16(0x300); + + mp_send = mp; + } + break; + + case 2: + { + spp_api_cnat_v4_bulk_policy_knob_t *mp; + + u32 mp_size = + sizeof(spp_api_cnat_v4_bulk_policy_knob_t) + + (sizeof(spp_api_cnat_v4_single_vrf_map_req))*2; + + mp = spp_msg_api_alloc(mp_size); + memset(mp, 0, mp_size); + + mp->_spp_msg_id = SPP_API_CNAT_V4_BULK_POLICY_KNOB; + + mp->port_limit = spp_host_to_net_byte_order_16(345); + mp->icmp_timeout = spp_host_to_net_byte_order_16(300); + mp->udp_init_timeout = spp_host_to_net_byte_order_16(175); + mp->udp_act_timeout = spp_host_to_net_byte_order_16(133); + mp->tcp_init_timeout = spp_host_to_net_byte_order_16(222); + mp->tcp_act_timeout = spp_host_to_net_byte_order_16(2345); + + mp->nat_policy_enable = spp_host_to_net_byte_order_32(0x7); + + mp->global_nfv9_logging_ipv4_address = spp_host_to_net_byte_order_32(0x77777777); + mp->global_nfv9_logging_udp_port = spp_host_to_net_byte_order_16(0x7007); + mp->global_nfv9_refresh_rate = spp_host_to_net_byte_order_16(0x700); + mp->global_nfv9_timeout_rate = spp_host_to_net_byte_order_16(0x70); + mp->global_nfv9_path_mtu = spp_host_to_net_byte_order_16(0x700); + + mp_send = mp; + } + break; + + + default: + printf("\nargv[2] = %d", argv[2]); + printf("\n2. bulk cmd [0=static-port, 1=bulk_vrf, 2=policy_knob+bulk_vrf]"); + return; + + } + platform_send_msg(mp_send); +} + +void cnat_nfv9_delete_cmd (int argc, unsigned long *argv) +{ + spp_api_cnat_v4_config_nfv9_logging_t *mp; + + if (argc != 1) { + printf("nfv9 delete i_vrf "); + return; + } + + mp = spp_msg_api_alloc (sizeof (*mp)); + memset(mp, 0, sizeof (*mp)); + mp->_spp_msg_id = SPP_API_CNAT_V4_CONFIG_NFV9_LOGGING; + mp->enable = 0; + mp->i_vrf = spp_host_to_net_byte_order_16(argv[0]); + platform_send_msg(mp); +} + +void cnat_generic_cmd (int argc, unsigned long *argv) +{ + spp_api_cnat_generic_command_request_t *mp; + + if (argc != 9) { + printf("generic command core type p1 p2 p3 p4 p5 p6 p7 "); + return; + } + + /* + * Allocate a large buffer for message req and resp structure + */ + mp = spp_msg_api_alloc (MAX_DEBUG_BUFFER_SIZE); + memset(mp, 0, MAX_DEBUG_BUFFER_SIZE); + mp->_spp_msg_id = SPP_API_CNAT_GENERIC_COMMAND_REQUEST; + mp->core_num = argv[0]; + mp->params[0] = spp_host_to_net_byte_order_32(argv[1]); + mp->params[1] = spp_host_to_net_byte_order_32(argv[2]); + mp->params[2] = spp_host_to_net_byte_order_32(argv[3]); + mp->params[3] = spp_host_to_net_byte_order_32(argv[4]); + mp->params[4] = spp_host_to_net_byte_order_32(argv[5]); + mp->params[5] = spp_host_to_net_byte_order_32(argv[6]); + mp->params[6] = spp_host_to_net_byte_order_32(argv[7]); + mp->params[7] = spp_host_to_net_byte_order_32(argv[8]); + platform_send_msg(mp); +} + +u32 icmp_sent_timestamps; /* 32 KB array per core */ +u8 v4_pkt_count = 0; + +cnat_icmp_msg_t icmp_msg_gen_allowed () +{ +#ifdef DISABLE_ICMP_THROTTLE_FOR_DEBUG_PURPOSE + return CNAT_ICMP_MSG; +#else + u32 current_timestamp; + spp_node_main_vector_t *nmv; + u32 updated_timestamp; + + v4_pkt_count ++; + + nmv = spp_get_node_main_vectorized_inline(); + + current_timestamp = nmv->ticks / nmv->ticks_per_second; + + PLATFORM_UPDATE_TIMESTAMP + if (PREDICT_FALSE(icmp_sent_timestamps != updated_timestamp)) { + v4_pkt_count = 1; + /* update timestamp */ + icmp_sent_timestamps = updated_timestamp; + } + if (PREDICT_TRUE(v4_pkt_count <= cnat_main_db_icmp_rate_limit_core)) { + return CNAT_ICMP_MSG; + } else { + return CNAT_NO_ICMP_MSG; + } +#endif +} + +u32 v6_icmp_sent_timestamps; /* 32 KB array per core */ +u8 v6_pkt_count = 0; + +cnat_icmp_msg_t v6_icmp_msg_gen_allowed () +{ +#ifdef DISABLE_ICMP_THROTTLE_FOR_DEBUG_PURPOSE + return CNAT_ICMP_MSG; +#else + u32 current_timestamp; + spp_node_main_vector_t *nmv; + u32 updated_timestamp; + + nmv = spp_get_node_main_vectorized_inline(); + + current_timestamp = nmv->ticks / nmv->ticks_per_second; + PLATFORM_UPDATE_TIMESTAMP + v6_pkt_count ++; + + if (PREDICT_FALSE(v6_icmp_sent_timestamps != updated_timestamp)) { + v6_pkt_count = 1; + /* update timestamp */ + v6_icmp_sent_timestamps = updated_timestamp; + } + if (PREDICT_TRUE(v6_pkt_count <= cnat_main_db_icmp_rate_limit_core)) { + return CNAT_ICMP_MSG; + } else { + return CNAT_NO_ICMP_MSG; + } +#endif +} + +u32 v4_udp_crc_zero_timestamps; +u32 v4_udp_crc_zero_pkt_count = 0; +int v4_crc_zero_udp_allowed () +{ + PLATFORM_V4_CRC_ZERO_UDP_ALLOWED + /* Currently not supported for Brahmos. we need to take care of this */ + spp_node_main_vector_t *nmv; + u32 hash_value, current_timestamp; + + nmv = spp_get_node_main_vectorized_inline(); + + current_timestamp = nmv->ticks / nmv->ticks_per_second; + v4_udp_crc_zero_pkt_count++; + if (PREDICT_FALSE(v4_udp_crc_zero_timestamps != current_timestamp)) { + v4_udp_crc_zero_pkt_count = 1; + v4_udp_crc_zero_timestamps = current_timestamp; + } + if (PREDICT_TRUE(v4_udp_crc_zero_pkt_count <= + crc_zero_udp_rate_limit_core)) { + return 1; + } else { + return 0; + } +} + +/* + * ipv4_decr_ttl_n_calc_csum() + * - It decrements the TTL and calculates the incremental IPv4 checksum + */ + +ALWAYS_INLINE( +void ipv4_decr_ttl_n_calc_csum(ipv4_header *ipv4)) +{ + u32 checksum; + u16 old; + + old = ntohs(*(u16 *)&ipv4->ttl); + + /* Decrement TTL */ + ipv4->ttl--; + + /* Calculate incremental checksum */ + checksum = old + (~ntohs(*(u16 *)&ipv4->ttl) & 0xFFFF); + checksum += ntohs(ipv4->checksum); + checksum = (checksum & 0xFFFF) + (checksum >> 16); + ipv4->checksum = htons(checksum + (checksum >> 16)); +} + +ALWAYS_INLINE( +void calc_ipv4_checksum (ipv4_header *ipv4)) +{ + u16 *data = (u16 *) ipv4; + u32 checksum = 0; + + checksum = crc_calc(ipv4); + + /* Now produce the 1's complement */ + ipv4->checksum = spp_host_to_net_byte_order_16(((u16) (~(u16)checksum))); +} + +ALWAYS_INLINE( +void calc_v4_icmp_checksum (icmp_v4_t *icmp, int ipv4_payload_size)) +{ + u16 *data = (u16 *) icmp; + int num_hwords = (ipv4_payload_size)/2; + u32 checksum = 0; + + icmp->checksum = 0; + if (PREDICT_FALSE((ipv4_payload_size%2) != 0)) { + num_hwords += 1; + /* Append 0's in the last octet */ + *((u8 *)data + ipv4_payload_size) = 0; + } + while (num_hwords) { + checksum += (u32)spp_net_to_host_byte_order_16(data++); + num_hwords--; + } + + /* Add in the carry of the original sum */ + checksum = (checksum & 0xFFFF) + (checksum >> 16); + /* Add in the carry of the final sum */ + checksum = (checksum & 0xFFFF) + (checksum >> 16); + /* Now produce the 1's complement */ + icmp->checksum = spp_host_to_net_byte_order_16(((u16) (~(u16)checksum))); +} + +ALWAYS_INLINE( +void calc_v6_icmp_checksum (ipv6_header_t *ipv6, u16 ip_payload_size)) +{ + u16 *data; + u16 *data1; + int i; + icmp_v6_t *icmp; + int num_hwords = (ip_payload_size)/2; + u32 checksum = 0; + pseudo_v6_header_t pseudo_header; + + icmp = (icmp_v6_t *) ((u8 *)ipv6 + IPV6_HDR_LEN); + data = (u16 *) icmp; + icmp->checksum = 0; + +#if 1 + if (PREDICT_FALSE((ip_payload_size%2) != 0)) { + num_hwords += 1; + /* Append 0's in the last octet */ + *((u8 *)data + ip_payload_size) = 0; + } +#endif + + /* construct the pseudo header */ + + pseudo_header.src_addr[0] = ipv6->src_addr[0]; + pseudo_header.src_addr[1] = ipv6->src_addr[1]; + pseudo_header.src_addr[2] = ipv6->src_addr[2]; + pseudo_header.src_addr[3] = ipv6->src_addr[3]; + pseudo_header.dst_addr[0] = ipv6->dst_addr[0]; + pseudo_header.dst_addr[1] = ipv6->dst_addr[1]; + pseudo_header.dst_addr[2] = ipv6->dst_addr[2]; + pseudo_header.dst_addr[3] = ipv6->dst_addr[3]; + pseudo_header.payload_length = spp_host_to_net_byte_order_16(ip_payload_size); + pseudo_header.next_header = spp_host_to_net_byte_order_16(ipv6->next_header); + + data1 = (u16 *) &pseudo_header; + + /* sizeof(pseudo_v6_header_t) = 36 */ + for (i = 0; i < 18; i++) { + checksum += (u32)spp_net_to_host_byte_order_16(data1++); + } + +checksum_calc: + + if (PREDICT_TRUE(num_hwords)) { + checksum += (u32)spp_net_to_host_byte_order_16(data); + num_hwords--; + data++; + goto checksum_calc; + } + + /* Add in the carry of the original sum */ + checksum = (checksum & 0xFFFF) + (checksum >> 16); + /* Add in the carry of the final sum */ + checksum = (checksum & 0xFFFF) + (checksum >> 16); + /* Now produce the 1's complement */ + icmp->checksum = spp_host_to_net_byte_order_16(((u16) (~(u16)checksum))); +} + +void icmp_error_generate_v6 (spp_ctx_t *ctx, u8 icmp_type, + u8 icmp_code, u16 uidb_index) { + + u16 ip_hdr_len, ip_payload_size; + u32 *src_p, * dst_p; + icmp_v6_t *icmp; + int i; + ipv6_header_t *ip_old, *ip_new; + u16 icmp_payload_len; + + /* + * As per RFC 2463, we limit the maximum size of generated ICMPv6 message to * 1280. And hence if the packet is bigger than 1280, then it needs to be + * truncated. Also, if the packet had multiple chained buffers, we need to + * free all chained buffers, except the first one. + */ + free_all_but_first_chained_buffers(ctx); + + ip_hdr_len = IPV6_HDR_LEN; + /* offset to ip payload */ + + ip_old = (ipv6_header_t *)PLATFORM_CTX_CURRENT_HDR; + ip_new = (ipv6_header_t *) ((u8 *) PLATFORM_CTX_CURRENT_HDR - ICMPV6_ERR_SIZE); + icmp = (icmp_v6_t*) ( (u8*)ip_new + ip_hdr_len); + + icmp_payload_len = ip_hdr_len + + spp_net_to_host_byte_order_16(&(ip_old->payload_length)) ; + + ip_payload_size = ICMPV6_HDR_SIZE + icmp_payload_len; + /* + * There is no easy way to predict this case as the probablity that the IPv6 + * pkt is big depends on the type of traffic. Let us optimize the big + * pkt case as it involves more processing + * + * If the pkt size exceeds IPV6_MIN_PATH_MTU truncate it to IPV6_MIN_PATH_MTU + */ + if (PREDICT_TRUE((ip_payload_size + ip_hdr_len) > IPV6_MIN_PATH_MTU)) { + ip_payload_size = IPV6_MIN_PATH_MTU - ip_hdr_len; + } + + /* Following ICMP op has to be after ip header being copied */ + icmp->type = icmp_type; + icmp->code = icmp_code; + + ip_new->version_trafficclass_flowlabel = spp_host_to_net_byte_order_32( + VERSION_TRAFFICCLASS_FLOWLABEL); + ip_new->payload_length = spp_host_to_net_byte_order_16(ip_payload_size); + ip_new->next_header = IPV6_PROTO_ICMPV6; + ip_new->hop_limit = 64; + ip_new->dst_addr[0] = ip_old->src_addr[0]; + ip_new->dst_addr[1] = ip_old->src_addr[1]; + ip_new->dst_addr[2] = ip_old->src_addr[2]; + ip_new->dst_addr[3] = ip_old->src_addr[3]; + + ip_new->src_addr[0] = + spp_host_to_net_byte_order_32(svi_params_array[uidb_index].ipv6_addr[0]); + ip_new->src_addr[1] = + spp_host_to_net_byte_order_32(svi_params_array[uidb_index].ipv6_addr[1]); + ip_new->src_addr[2] = + spp_host_to_net_byte_order_32(svi_params_array[uidb_index].ipv6_addr[2]); + ip_new->src_addr[3] = + spp_host_to_net_byte_order_32(svi_params_array[uidb_index].ipv6_addr[3]); + /* calc checksum for icmp */ + + calc_v6_icmp_checksum(ip_new, ip_payload_size); +#if 0 + printf("Flow = 0x%x\n", ip_new->version_trafficclass_flowlabel); + printf("Hoplimit = 0x%x\n", ip_new->hop_limit); + printf("Length= 0x%x\n", ip_new->payload_length); + printf("Next header = 0x%x\n", ip_new->next_header); + printf("Src add0 = 0x%x\n", ip_new->src_addr[0]); + printf("Src add1 = 0x%x\n", ip_new->src_addr[1]); + printf("Src add2 = 0x%x\n", ip_new->src_addr[2]); + printf("Src add3 = 0x%x\n", ip_new->src_addr[3]); + printf("Dst add0 = 0x%x\n", ip_new->dst_addr[0]); + printf("Dst add1 = 0x%x\n", ip_new->dst_addr[1]); + printf("Dst add2 = 0x%x\n", ip_new->dst_addr[2]); + printf("Dst add3 = 0x%x\n", ip_new->dst_addr[3]); + printf("Icmp type = 0x%x\n", icmp->type); + printf("Icmp code = 0x%x\n", icmp->code); + + printf("\n\nICMP packet:\n"); + for (i = 0; i < 10; i ++) { + printf("0x%x " , *((u8 *)icmp + i)); + if ((i%16) == 15) { + printf("\n"); + } + } +#endif + + ctx->current_header -= ICMPV6_ERR_SIZE; + ctx->current_length = ip_payload_size + ip_hdr_len; + PLATFORM_CNAT_SET_TX_VRF(ctx,uidb_index); +} + +void icmp_error_generate_v2 (ipv4_header *ip, u8 icmp_type, + u8 icmp_code, u16 mtu, u32 src_ip) +{ + + u16 ip_hdr_len, ip_payload_size; + u32 *src_p, * dst_p; + icmp_v4_t *icmp; + + ip_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; /* offset to ip payload */ + icmp = (icmp_v4_t*) ( (u8*)ip + ip_hdr_len); + ip_payload_size = sizeof(icmp_v4_t) + ip_hdr_len + + ICMP_UNREACHABLE_IP_PAYLOAD_SIZE; + + src_p = (u32*) + ((u8*)ip + ip_hdr_len + ICMP_UNREACHABLE_IP_PAYLOAD_SIZE - 4); + dst_p = (u32*) ((u8*)src_p + sizeof(ipv4_header) + + sizeof(icmp_v4_t)); + + while(src_p >= (u32*)ip) *dst_p-- = *src_p--; + + /* Following ICMP op has to be after ip header being copied */ + icmp->type = icmp_type; + icmp->code = icmp_code; + icmp->identifier = 0; + icmp->sequence = 0; + if(PREDICT_FALSE(mtu != 0)) { + icmp->sequence = spp_host_to_net_byte_order_16(mtu); + } + + + /* build icmp header, keep original tos, identification values */ + ip->version_hdr_len_words = 0x45; + ip->total_len_bytes = sizeof(ipv4_header) + ip_payload_size; + ip->total_len_bytes = spp_host_to_net_byte_order_16(ip->total_len_bytes); + ip->frag_flags_offset = 0; + ip->ttl = 64; + ip->protocol = ICMP_PROT; + ip->checksum = 0; + ip->dest_addr = ip->src_addr; + ip->src_addr = spp_host_to_net_byte_order_32(src_ip); + + /* calc checksum for ip and icmp */ + + calc_ipv4_checksum(ip); + calc_v4_icmp_checksum( (icmp_v4_t *) ((u8*) ip + sizeof(ipv4_header)), + ip_payload_size); +} + +void icmp_error_generate (ipv4_header *ip, u8 icmp_type, + u8 icmp_code, u16 uidb_index) { + + u16 ip_hdr_len, ip_payload_size; + u32 *src_p, * dst_p; + icmp_v4_t *icmp; + + ip_hdr_len = (ip->version_hdr_len_words & 0xf) << 2; /* offset to ip payload */ + icmp = (icmp_v4_t*) ( (u8*)ip + ip_hdr_len); + ip_payload_size = sizeof(icmp_v4_t) + ip_hdr_len + + ICMP_UNREACHABLE_IP_PAYLOAD_SIZE; + + src_p = (u32*) + ((u8*)ip + ip_hdr_len + ICMP_UNREACHABLE_IP_PAYLOAD_SIZE - 4); + dst_p = (u32*) ((u8*)src_p + sizeof(ipv4_header) + + sizeof(icmp_v4_t)); + + while(src_p >= (u32*)ip) *dst_p-- = *src_p--; + + /* Following ICMP op has to be after ip header being copied */ + icmp->type = icmp_type; + icmp->code = icmp_code; + icmp->identifier = 0; + icmp->sequence = 0; + + + /* build icmp header, keep original tos, identification values */ + ip->version_hdr_len_words = 0x45; + ip->total_len_bytes = sizeof(ipv4_header) + ip_payload_size; + ip->total_len_bytes = spp_host_to_net_byte_order_16(ip->total_len_bytes); + ip->frag_flags_offset = 0; + ip->ttl = 64; + ip->protocol = ICMP_PROT; + ip->checksum = 0; + ip->dest_addr = ip->src_addr; + + ip->src_addr = spp_host_to_net_byte_order_32(svi_params_array[uidb_index].ipv4_addr); + + /* calc checksum for ip and icmp */ + + calc_ipv4_checksum(ip); + calc_v4_icmp_checksum( (icmp_v4_t *) ((u8*) ip + sizeof(ipv4_header)), + ip_payload_size); +#if 0 + printf("version_hdr_len_words = 0x%x\n", ip->version_hdr_len_words); + printf("total_len_bytes = 0x%x\n", ip->total_len_bytes); + printf("Frag = 0x%x\n", ip->frag_flags_offset); + printf("ttl = 0x%x\n", ip->ttl); + printf("Protocol = 0x%x\n", ip->protocol); + printf("checksum = 0x%x\n", ip->checksum); + printf("Dest addr = 0x%x\n", ip->dest_addr); + printf("Src addr = 0x%x\n", ip->src_addr); + printf("Icmp type = 0x%x\n", icmp->type); + printf("Icmp code = 0x%x\n", icmp->code); +#endif + +} + +int icmpv4_generate_with_throttling_v2 (spp_ctx_t *ctx, ipv4_header *ipv4, + int icmp_type, int icmp_code, + u16 mtu, u32 src_ip) +{ + u16 ip_hdr_len; + icmp_v4_t *icmp; + u16 rx_uidb_index = ctx->ru.rx.uidb_index; + if (icmp_msg_gen_allowed()) { + free_all_but_first_chained_buffers(ctx); + icmp_error_generate_v2(ipv4, icmp_type, icmp_code, mtu, src_ip); + ctx->current_length = (u16) + ((u8*)ctx->current_header - ctx->packet_data) + + spp_net_to_host_byte_order_16(&ipv4->total_len_bytes); + PLATFORM_CNAT_SET_TX_VRF(ctx,rx_uidb_index); + return 1; + } else { + return 0; + } +} + +int icmpv4_generate_with_throttling (spp_ctx_t *ctx, ipv4_header *ipv4, + u16 rx_uidb_index) +{ + int icmp_type; + int icmp_code; + + if (icmp_msg_gen_allowed()) { + /* ICMP error would be small, so one buffer is enough. Clear the other */ + free_all_but_first_chained_buffers(ctx); + + icmp_type = ICMPV4_TIMEEXCEEDED; + icmp_code = ICMPV4_TIMTTL; + icmp_error_generate(ipv4, icmp_type, icmp_code, rx_uidb_index); + ctx->current_length = (u16) + ((u8*)ctx->current_header - ctx->packet_data) + + spp_net_to_host_byte_order_16(&ipv4->total_len_bytes); + PLATFORM_CNAT_SET_TX_VRF(ctx,rx_uidb_index); + return 1; + } else { + return 0; + } +} + +int icmpv4_generate_with_throttling_v1 (spp_ctx_t *ctx, ipv4_header *ipv4, + u16 rx_uidb_index, u32 type, u32 code) +{ + if (icmp_msg_gen_allowed()) { + /* ICMP error would be small, so one buffer is enough. Clear the other */ + free_all_but_first_chained_buffers(ctx); + + icmp_error_generate(ipv4, type, code, rx_uidb_index); + ctx->current_length = (u16) + ((u8*)ctx->current_header - ctx->packet_data) + + spp_net_to_host_byte_order_16(&ipv4->total_len_bytes); + PLATFORM_CNAT_SET_TX_VRF(ctx,rx_uidb_index); + return 1; + } else { + return 0; + } +} + + +int icmpv6_generate_with_throttling (spp_ctx_t *ctx, ipv6_header_t *ipv6, + u16 rx_uidb_index) +{ + int icmp_type; + int icmp_code; + + if (v6_icmp_msg_gen_allowed()) { + icmp_type = ICMPV6_TIMEEXCEEDED; + icmp_code = ICMPV6_TIMTTL; + icmp_error_generate_v6(ctx, icmp_type, icmp_code, rx_uidb_index); + return 1; + } else { + return 0; + } +} + +int icmpv6_generate_with_throttling_v1 (spp_ctx_t *ctx, ipv6_header_t *ipv6, + u16 rx_uidb_index, u32 type, u32 code) +{ + + if (v6_icmp_msg_gen_allowed()) { + icmp_error_generate_v6(ctx, type, code, rx_uidb_index); + return 1; + } else { + return 0; + } +} +#endif + +void calculate_window_scale(tcp_hdr_type *tcp_header, u8 *scale) { + + u8 check_options = 0; + + *scale = 0; + check_options = ((tcp_header->flags & TCP_FLAG_SYN) && + (((tcp_header->hdr_len>>4) << 2) > sizeof(tcp_hdr_type))); + + if (PREDICT_FALSE(check_options)) { + u8 *options_ptr = tcp_findoption(tcp_header, TCP_OPTION_WINDOW_SCALE); + + /* + * TCP option field: | kind 1B | len 1B | value 2B| + * where kind != [0, 1] + */ + if (PREDICT_TRUE(options_ptr && + (options_ptr[1] == TCP_OPTION_WINDOW_SCALE))) { + u8 *ptr = (u8*)(options_ptr + 2); + *scale = *ptr; + + if(PREDICT_FALSE(*scale >= 14)) { + *scale = 14; + } + + return; + } + } +} + +#if 0 +ALWAYS_INLINE( +void cnat_log_nat44_tcp_seq_mismatch( + cnat_main_db_entry_t *db, + cnat_vrfmap_t *vrfmap)) +{ + /* As of now, Netflow does not require this to be logged + * So only syslog + */ + if(PREDICT_TRUE(db->flags & CNAT_TAC_SEQ_MISMATCH)) { + /* Already logged ..*/ + return; + } + /* else, set the flag and call the log API */ + + db->flags = db->flags | CNAT_TAC_SEQ_MISMATCH; + + cnat_syslog_nat44_tcp_seq_mismatch(db, vrfmap); +} + + +static int cnat_util_init (void *notused) +{ + /* run SPP_API_CNAT_PORTMAP_CREATE first*/ + spp_msg_api_set_handler(SPP_API_CNAT_PORT_ALLOCATE, + spp_api_cnat_port_allocate_t_handler); + + + spp_msg_api_set_handler(SPP_API_CNAT_PORT_CLEAR, + spp_api_cnat_port_clear_t_handler); + + /* run vrfmap config first */ + spp_msg_api_set_handler(SPP_API_CNAT_PORT_CREATE, + spp_api_cnat_port_create_t_handler); + + spp_msg_api_set_handler(SPP_API_CNAT_PORT_DELETE, + spp_api_cnat_port_delete_t_handler); + return 0; +} + +void +print_ipv6_pkt (ipv6_header_t *ip) +{ + u32 i, total_len, l4_len=0; + + u8 *pkt = (u8 *) ip; + + total_len = spp_net_to_host_byte_order_16(&ip->payload_length); + + /* we rarely need to debug > 200 bytes of packet */ + if(total_len > 200) { + total_len = 200; + } + + printf("\n======== PRINTING PKT START======\n"); + printf("======== IPv6 PAYLOAD LEN %d ===========\n", total_len); + for (i=0; i < 40; i++) { + printf(" %02X ", *(pkt + i)); + if(i%16==15) + printf("\n"); + } + + if (ip->next_header == IPV6_PROTO_TCP) { + printf("\n======== TCP HEADER =================\n"); + l4_len = 20; + } + else if (ip->next_header == IPV6_PROTO_UDP) { + printf("\n======== UDP HEADER =================\n"); + l4_len = 8; + } + else if (ip->next_header == IPV6_PROTO_ICMPV6) { + printf("\n======== ICMP HEADER =================\n"); + l4_len = 8; + } + + for (i=40; i < (l4_len + 40); i++) { + printf(" %02X ", *(pkt + i)); + } + + printf("\n======== LAYER4 PAYLOAD ===================\n"); + for (i=(l4_len + 40); i < total_len; i++) { + printf(" %02X ", *(pkt + i)); + if(i%16==15) + printf("\n"); + } + + printf("\n======== PRINTING PKT END =======\n"); +} + + + +PLATFORM_SPP_INIT_FUNCTION(cnat_util_init); +#endif diff --git a/plugins/vcgn-plugin/vcgn/cnat_v4_ftp_alg.h b/plugins/vcgn-plugin/vcgn/cnat_v4_ftp_alg.h new file mode 100644 index 00000000..df3dfcb0 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_v4_ftp_alg.h @@ -0,0 +1,133 @@ +/* + *------------------------------------------------------------------ + * cnat_v4_ftp_alg.h + * + * Copyright (c) 2012-2013 Cisco and/or its affiliates. + * 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 __CNAT_V4_FTP_ALG_H__ +#define __CNAT_V4_FTP_ALG_H__ + + +#include +#include + +#include "tcp_header_definitions.h" +#include "dslite_defs.h" +#include "dslite_db.h" + +/* shorter form of byte order functions */ + +#define net2host16(x) clib_net_to_host_u16( x) +#define net2host32(x) clib_net_to_host_u32( x) +#define net2host64(x) clib_net_to_host_u64( x) +#define host2net16(x) clib_host_to_net_u16(x) +#define host2net32(x) clib_host_to_net_u32(x) +#define host2net64(x) clib_host_to_net_u64(x) + +//#define BIGENDIAN + +typedef struct iphdrtype_ { + u8 v_ihl; /* version and IP header length */ + u8 tos; /* type of service */ + u16 tl; /* total length */ + u16 id; /* identifier */ + u16 ipreserved: 1; + u16 dontfragment: 1; + u16 morefragments: 1; + u16 fo: 13; /* fragment offset */ + u8 ttl; /* time to live */ + u8 prot; /* protocol type */ + u16 checksum; /* checksum */ + u32 srcadr; /* IP source address */ + u32 dstadr; /* IP destination address */ +} iphdrtype; + + +typedef struct tcptype_ { + u16 sourceport; + u16 destinationport; + u32 sequencenumber; + u32 acknowledgementnumber; + u8 dataoffset; + u8 flags; +#if 0 +/* bypass the ENDIAN part */ +#ifdef BIGENDIAN + u8 reserved: 2; + u8 urg: 1; + u8 ack: 1; + u8 psh: 1; + u8 rst: 1; + u8 syn: 1; + u8 fin: 1; +#else + u8 fin: 1; + u8 syn: 1; + u8 rst: 1; + u8 psh: 1; + u8 ack: 1; + u8 urg: 1; + u8 reserved2: 2; +#endif +#endif + + u16 window; + u16 checksum; + u16 urgentpointer; + u8 data[0]; +} tcptype ; + + +int watch_ftp_port_cmd (iphdrtype *ip, + tcptype *tcp, + u32 * ip_addr, + u16 * port); + + +u8 * ftp_test_pkt_gen (u32 ip_addr, u16 port); + +int update_ftp_port(u8 * pkt, u32 new_ip, u16 new_port, i8 * delta, + cnat_main_db_entry_t *db_tcp_control, + dslite_table_entry_t *dslite_entry_ptr, + ipv6_header_t *ipv6_hdr); +/* + * caller needs to check if it's a ftp packet + * this function returns 1 + * if packet being updated for PORT + * otherwise return 0. + * Assume IP header DOES NOT have option fields + */ + +int cnat_ftp_alg ( u8* pkt, i8 * delta, cnat_main_db_entry_t *db, + dslite_table_entry_t *dslite_entry_ptr, + ipv6_header_t *ipv6_hdr); + +#define FTP_ALG_DEBUG_PRINTF_ENABLED 1 + +#ifdef FTP_ALG_DEBUG_PRINTF_ENABLED + +#define FTP_ALG_DEBUG_PRINTF(...) { \ + if (global_debug_flag & CNAT_DEBUG_FTP_ALG) { \ + printf(__VA_ARGS__); \ + } } + +#else + +#define FTP_ALG_DEBUG_PRINTF(...) + +#endif + +#endif /* __CNAT_V4_FTP_ALG_H__ */ diff --git a/plugins/vcgn-plugin/vcgn/cnat_v4_functions.c b/plugins/vcgn-plugin/vcgn/cnat_v4_functions.c new file mode 100644 index 00000000..d3051fba --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_v4_functions.c @@ -0,0 +1,364 @@ +/* + *--------------------------------------------------------------------------- + * cnat_v4_funtions.c + * + * Copyright (c) 2008-2013 Cisco and/or its affiliates. + * 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 +#include +#include +#include + + +#include "tcp_header_definitions.h" +#include "cnat_db.h" +#include "cnat_config.h" +#include "cnat_v4_functions.h" +#include "dslite_defs.h" +#include "dslite_db.h" + +static u32 tcp_logging_count; +static u32 tcp_logging_overflow; + +static tcp_logging_struct_t tcp_logging_array[MAX_TCP_LOGGING_COUNT]; + +/* + * Function to log TCP pkts checksum changes.. + */ +void +tcp_debug_logging ( + u32 seq_num, + u32 ack_num, + u32 old_ip, + u32 new_ip, + u16 old_port, + u16 new_port, + u16 old_ip_crc, + u16 new_ip_crc, + u16 old_tcp_crc, + u16 new_tcp_crc) +{ + tcp_logging_array[tcp_logging_count].seq_num = seq_num; + tcp_logging_array[tcp_logging_count].ack_num = ack_num; + tcp_logging_array[tcp_logging_count].old_ip = old_ip; + tcp_logging_array[tcp_logging_count].new_ip = new_ip; + tcp_logging_array[tcp_logging_count].old_port = old_port; + tcp_logging_array[tcp_logging_count].new_port = new_port; + tcp_logging_array[tcp_logging_count].old_ip_crc = old_ip_crc; + tcp_logging_array[tcp_logging_count].new_ip_crc = new_ip_crc; + tcp_logging_array[tcp_logging_count].old_tcp_crc = old_tcp_crc; + tcp_logging_array[tcp_logging_count].new_tcp_crc = new_tcp_crc; + + tcp_logging_count++; + + if (tcp_logging_count >= MAX_TCP_LOGGING_COUNT) { + tcp_logging_overflow = 1; + tcp_logging_count = 0; + } +} + +/* + * Function to dmp TCP pkts logged.. + */ +void +tcp_debug_logging_dump (void) +{ + u32 i, total_count, start_entry; + + if (tcp_logging_overflow) { + total_count = MAX_TCP_LOGGING_COUNT; + start_entry = tcp_logging_count; + printf("Logging Entries Wrapped Around, displaying %d entries\n", + total_count); + } else { + total_count = tcp_logging_count; + start_entry = 0; + printf("Displaying %d entries\n", total_count); + } + + printf("SEQ ACK IP_O IP_N PORT_O PORT_N L3_CRC_O L3_CRC_N L4_CRC_O L4_CRC_N\n"); + + for (i = 0; i < total_count; i++) { + u32 entry = (i + start_entry) % MAX_TCP_LOGGING_COUNT; + + printf("%04d: 0x%08x 0x%08x 0x%08x 0x%08x 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x\n", + entry, + tcp_logging_array[entry].seq_num, + tcp_logging_array[entry].ack_num, + tcp_logging_array[entry].old_ip, + tcp_logging_array[entry].new_ip, + tcp_logging_array[entry].old_port, + tcp_logging_array[entry].new_port, + tcp_logging_array[entry].old_ip_crc, + tcp_logging_array[entry].new_ip_crc, + tcp_logging_array[entry].old_tcp_crc, + tcp_logging_array[entry].new_tcp_crc); + } +} + +/* + * Function to enable TCP logging + */ +void +tcp_debug_logging_enable_disable (u32 enable_flag) +{ + switch (enable_flag) { + + case TCP_LOGGING_DISABLE: + if (tcp_logging_enable_flag == TCP_LOGGING_DISABLE) { + printf("\nTCP Logging ALREADY DISABLED\n"); + } else { + printf("\nTCP Logging DISABLED\n"); + } + tcp_logging_enable_flag = 0; + break; + + case TCP_LOGGING_ENABLE: + if (tcp_logging_enable_flag == TCP_LOGGING_ENABLE) { + printf("\nTCP Logging ALREADY ENABLED\n"); + } else { + tcp_logging_enable_flag = 1; + tcp_logging_count = 0; + tcp_logging_overflow = 0; + + printf("\nTCP Logging ENABLED\n"); + } + break; + + case TCP_LOGGING_PACKET_DUMP: + tcp_debug_logging_dump(); + break; + + case TCP_LOGGING_SUMMARY_DUMP: + default: + printf("\ntcp_logging_enable_flag %d, tcp_log_count %d\n", + tcp_logging_enable_flag, tcp_logging_count); + printf("To Enable TCP LOGGING provide a flag value of %d\n", + TCP_LOGGING_ENABLE); + break; + } +} + +void hex_dump (u8 * p, int len) { + int i; + for (i=0;itotal_len_bytes); + + printf("\n======== PRINTING PKT START======\n"); + printf("======== IP PACKET LEN %d ===========\n", total_len); + for (i=0; i < 20; i++) { + printf(" %02X ", *(pkt + i)); + } + + printf("\n======== ICMP HEADER =================\n"); + for (i=20; i < 28; i++) { + printf(" %02X ", *(pkt + i)); + } + + printf("\n======== ICMP BODY ===================\n"); + for (i=28; i < total_len; i++) { + printf(" %02X ", *(pkt + i)); + } + + printf("\n======== PRINTING PKT END =======\n"); +} + +void +print_udp_pkt (ipv4_header *ip) +{ + u32 i, total_len, udp_len; + + u8 *pkt = (u8 *) ip; + + total_len = clib_net_to_host_u16(ip->total_len_bytes); + udp_len = total_len - 20; + + printf("\n======== PRINTING PKT START======\n"); + printf("======== IP PACKET LEN %d ===========\n", total_len); + for (i=0; i < 20; i++) { + printf(" %02X ", *(pkt + i)); + } + printf("\n======== UDP PSEUDO HEADER ==========\n"); + for (i=12; i < 20; i++) { + printf(" %02X ", *(pkt + i)); + } + printf(" 00 11 %02X %02X ", udp_len >> 8, udp_len & 0xff); + + printf("\n======== UDP HEADER =================\n"); + for (i=20; i < 28; i++) { + printf(" %02X ", *(pkt + i)); + } + printf("\n======== UDP BODY ===================\n"); + for (i=28; i < total_len; i++) { + printf(" %02X ", *(pkt + i)); + } + + printf("\n======== PRINTING PKT END =======\n"); +} + +void +print_tcp_pkt (ipv4_header *ip) +{ + u32 i, total_len, tcp_len; + + u8 *pkt = (u8 *) ip; + + total_len = clib_net_to_host_u16(ip->total_len_bytes); + tcp_len = total_len - 20; + + printf("\n======== PRINTING PKT START======\n"); + printf("======== IP PACKET LEN %d ===========\n", total_len); + for (i=0; i < 20; i++) { + printf(" %02X ", *(pkt + i)); + } + printf("\n======== TCP PSEUDO HEADER ==========\n"); + for (i=12; i < 20; i++) { + printf(" %02X ", *(pkt + i)); + } + printf(" 00 06 %02X %02X ", tcp_len >> 8, tcp_len & 0xff); + + printf("\n======== TCP HEADER =================\n"); + for (i=20; i < 40; i++) { + printf(" %02X ", *(pkt + i)); + } + printf("\n======== TCP BODY ===================\n"); + for (i=40; i < total_len; i++) { + printf(" %02X ", *(pkt + i)); + } + + printf("\n======== PRINTING PKT END =======\n"); +} + +/* IN: ipv4 and tcp header pointer, + * new ipv4 addr and port value + * main db index for accessing per vrf mss value + * DO: + * NAT + * mss adjust if needed + * ip & tcp checksum update (incremental) + */ + +inline void tcp_in2out_nat_mss_n_checksum (ipv4_header * ip, + tcp_hdr_type * tcp, + u32 ipv4_addr, + u16 port, + cnat_main_db_entry_t * db) +{ + u8 *mss_ptr; + u8 check_mss = 0; + u16 mss_old, mss_new; + cnat_vrfmap_t * vrf_map_p; + + cnat_v4_recalculate_tcp_checksum(ip, + tcp, + &(ip->src_addr), + &(tcp->src_port), + ipv4_addr, + port); + u16 frag_offset = + clib_net_to_host_u16(ip->frag_flags_offset); + + if(PREDICT_FALSE(frag_offset & IP_FRAG_OFFSET_MASK)) { + return; /* No TCP Header at all */ + } + + /* + * check SYN bit and if options field is present + * If yes, proceed to extract the options and get TCP MSS value + */ + check_mss = ((tcp->flags & TCP_FLAG_SYN) && + (((tcp->hdr_len>>4) << 2) > sizeof(tcp_hdr_type))); + + if (PREDICT_FALSE(check_mss)) { + + /* get per VRF mss config */ + if(PREDICT_FALSE(db->flags & (CNAT_DB_DSLITE_FLAG))) { + mss_new = dslite_table_db_ptr[db->dslite_nat44_inst_id].tcp_mss; + } else { + vrf_map_p = cnat_map_by_vrf + db->vrfmap_index; + mss_new = vrf_map_p->tcp_mss; + } + DSLITE_PRINTF(1, "Check MSS true..%u\n", mss_new); + /* + * If TCP MSS is not configured, skip the MSS checks + */ + if (PREDICT_FALSE(mss_new != V4_TCP_MSS_NOT_CONFIGURED_VALUE)) { + + /* if mss_ptr != NULL, then it points to MSS option */ + mss_ptr = tcp_findoption(tcp, TCP_OPTION_MSS); + + /* + * TCP option field: | kind 1B | len 1B | value 2B| + * where kind != [0,1] + */ + if (PREDICT_TRUE(mss_ptr && (mss_ptr[1] == 4))) { + + u16 *ptr = (u16*)(mss_ptr + 2); + + mss_old = clib_net_to_host_u16(*ptr); + + if (PREDICT_FALSE(mss_old > mss_new)) { + u32 sum32; + u16 mss_old_r, old_tcp_checksum_r; + + *ptr = clib_host_to_net_u16(mss_new); + + mss_old_r = ~mss_old; + + old_tcp_checksum_r = + ~clib_net_to_host_u16(tcp->tcp_checksum); + + /* + * Revise the TCP checksum + */ + sum32 = old_tcp_checksum_r + mss_old_r + mss_new; + FILL_CHECKSUM(tcp->tcp_checksum, sum32) + + if (PREDICT_FALSE(tcp_logging_enable_flag)) { + tcp_debug_logging( + clib_net_to_host_u32(tcp->seq_num), + clib_net_to_host_u32(tcp->ack_num), + 0, + 0, + mss_old, + mss_new, + 0, + 0, + ~old_tcp_checksum_r, + clib_net_to_host_u16(tcp->tcp_checksum)); + } + } + } + } + } +} + +u32 get_my_svi_intf_ip_addr() { + return 0x01010101; +} diff --git a/plugins/vcgn-plugin/vcgn/cnat_v4_functions.h b/plugins/vcgn-plugin/vcgn/cnat_v4_functions.h new file mode 100644 index 00000000..2429e5e1 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_v4_functions.h @@ -0,0 +1,342 @@ +/* + *------------------------------------------------------------------ + * cnat_v4_functions.h + * + * Copyright (c) 2007-2013 Cisco and/or its affiliates. + * 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 __CNAT_V4_FUNCTOINS__ +#define __CNAT_V4_FUNCTOINS__ + +#include "tcp_header_definitions.h" +#include "cnat_db.h" +#include "spp_ctx.h" + +#include "platform_common.h" + +/* + * Defines and structures to enable TCP packet logging + */ +#define TCP_LOGGING_DISABLE 0 +#define TCP_LOGGING_ENABLE 1 +#define TCP_LOGGING_PACKET_DUMP 2 +#define TCP_LOGGING_SUMMARY_DUMP 3 + +#define MAX_TCP_LOGGING_COUNT 1024 + +typedef struct tcp_logging_struct { + u32 seq_num; + u32 ack_num; + u32 old_ip; + u32 new_ip; + u16 old_port; + u16 new_port; + u16 old_ip_crc; + u16 new_ip_crc; + u16 old_tcp_crc; + u16 new_tcp_crc; +} tcp_logging_struct_t; + +void tcp_debug_logging_dump (void); +void tcp_debug_logging_enable_disable (u32 enable_flag); + +void +tcp_debug_logging ( + u32 seq_num, + u32 ack_num, + u32 old_ip, + u32 new_ip, + u16 old_port, + u16 new_port, + u16 old_ip_crc, + u16 new_ip_crc, + u16 old_tcp_crc, + u16 new_tcp_crc); + +#define JLI printf("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__); fflush(stdout); + +#define CNAT_ICMP_DEST_UNREACHABLE 100 +#define INCREMENT_NODE_COUNTER(c) \ + em->counters[node_counter_base_index + c] += 1; + +#define V4_TCP_UPDATE_SESSION_FLAG(db, tcp) \ +if ((tcp->flags & TCP_FLAG_ACK) && (tcp->flags & TCP_FLAG_SYN)) { \ + db->flags |= CNAT_DB_FLAG_TCP_ACTIVE; \ +} \ +if ((tcp->flags & TCP_FLAG_RST) || (tcp->flags & TCP_FLAG_FIN)) { \ + db->flags &= ~CNAT_DB_FLAG_TCP_ACTIVE; \ + db->flags |= CNAT_DB_FLAG_TCP_CLOSING; \ +} + +#define V4_TCP_UPDATE_SESSION_DB_FLAG(sdb, tcp) \ +if ((tcp->flags & TCP_FLAG_ACK) && (tcp->flags & TCP_FLAG_SYN)) { \ + sdb->flags |= CNAT_DB_FLAG_TCP_ACTIVE; \ +} \ +if ((tcp->flags & TCP_FLAG_RST) || (tcp->flags & TCP_FLAG_FIN)) { \ + sdb->flags &= ~CNAT_DB_FLAG_TCP_ACTIVE; \ + sdb->flags |= CNAT_DB_FLAG_TCP_CLOSING; \ +} + +/* + * Code to recalculate checksum after ACK/SEQ number changes + * This macro assumes, we have pointer to tcp structure + * referenced by the name "tcp" + */ +#define CNAT_UPDATE_TCP_SEQ_ACK_CHECKSUM(old_val32, new_val32) \ +{ \ + u16 old_val_lower, old_val_upper, old_tcp_cr; \ + u16 new_val_lower, new_val_upper, new_tcp_cr; \ + u32 sum32; \ + \ + old_val_lower = ~((u16) old_val32); \ + old_val_upper = ~((u16) (old_val32 >> 16)); \ + old_tcp_cr = ~net2host16(&tcp->tcp_checksum); \ + new_val_lower = (u16) new_val32; \ + new_val_upper = (u16) (new_val32 >> 16); \ + \ + sum32 = old_val_lower + old_val_upper + old_tcp_cr + \ + new_val_lower + new_val_upper; \ + \ + sum32 = (sum32 & 0xffff) + ((sum32 >> 16) & 0xffff); \ + sum32 = (sum32 & 0xffff) + ((sum32 >> 16) & 0xffff); \ + new_tcp_cr = ~((u16)sum32); \ + \ + tcp->tcp_checksum = host2net16(new_tcp_cr); \ +} + +/* + * newchecksum = ~(~oldchecksum + ~old + new) + * old/new for l3 checksum: ip address + */ +#define CNAT_UPDATE_L3_CHECKSUM_DECLARE \ +u16 old_l3_1r, old_l3_2r; \ +u16 old_l3_cr, new_l3_c; \ +u32 new32; + +#define CNAT_UPDATE_L3_CHECKSUM(old_l3_1, old_l3_2, old_l3_c, \ + new_l3_1, new_l3_2) \ +old_l3_1r = ~(old_l3_1); \ +old_l3_2r = ~(old_l3_2); \ +old_l3_cr = ~(old_l3_c); \ +new32 = old_l3_cr + old_l3_1r + old_l3_2r + new_l3_1 + new_l3_2; \ +new32 = (new32 & 0xffff) + ((new32 >> 16) & 0xffff); \ +new32 = (new32 & 0xffff) + ((new32 >> 16) & 0xffff); \ +new_l3_c = ~((u16)new32); + + +/* + * newchecksum = ~(~oldchecksum + ~old + new) + * old/new for l3 checksum: ip address + * old/new for l4 checksum: ip address and port + */ +#define CNAT_UPDATE_L3_L4_CHECKSUM_DECLARE \ +u16 old_l3_1r, old_l3_2r, old_l4r; \ +u16 old_l3_cr, old_l4_cr; \ +u16 new_l3_c, new_l4_c; \ +u32 sum32, new32; + +#define CNAT_UPDATE_L3_L4_CHECKSUM(old_l3_1, old_l3_2, old_l4, \ + old_l3_c, old_l4_c, \ + new_l3_1, new_l3_2, new_l4) \ +old_l3_1r = ~(old_l3_1); \ +old_l3_2r = ~(old_l3_2); \ +old_l3_cr = ~(old_l3_c); \ +sum32 = old_l3_1r + old_l3_2r + new_l3_1 + new_l3_2; \ +new32 = old_l3_cr + sum32; \ +new32 = (new32 & 0xffff) + ((new32 >> 16) & 0xffff); \ +new32 = (new32 & 0xffff) + ((new32 >> 16) & 0xffff); \ +new_l3_c = ~((u16)new32); \ +old_l4r = ~(old_l4); \ +old_l4_cr = ~(old_l4_c); \ +sum32 += old_l4r + new_l4; \ +new32 = old_l4_cr + sum32; \ +new32 = (new32 & 0xffff) + ((new32 >> 16) & 0xffff); \ +new32 = (new32 & 0xffff) + ((new32 >> 16) & 0xffff); \ +new_l4_c = ~((u16)new32); + +/* + * For ICMP checksums, we don't use the top IP header for checksum calculation + */ +#define CNAT_UPDATE_L3_ICMP_CHECKSUM(old_l3_1, old_l3_2, old_l4, \ + old_l3_c, old_l4_c, \ + new_l3_1, new_l3_2, new_l4) \ +old_l3_1r = ~(old_l3_1); \ +old_l3_2r = ~(old_l3_2); \ +old_l3_cr = ~(old_l3_c); \ +sum32 = old_l3_1r + old_l3_2r + new_l3_1 + new_l3_2; \ +new32 = old_l3_cr + sum32; \ +new32 = (new32 & 0xffff) + ((new32 >> 16) & 0xffff); \ +new32 = (new32 & 0xffff) + ((new32 >> 16) & 0xffff); \ +new_l3_c = ~((u16)new32); \ +old_l4r = ~(old_l4); \ +old_l4_cr = ~(old_l4_c); \ +sum32 = old_l4r + new_l4; \ +new32 = old_l4_cr + sum32; \ +new32 = (new32 & 0xffff) + ((new32 >> 16) & 0xffff); \ +new32 = (new32 & 0xffff) + ((new32 >> 16) & 0xffff); \ +new_l4_c = ~((u16)new32); + + +/* + * icmp error type message: + * newchecksum = ~(~oldchecksum + ~old + new) + * old/new for outlayer ip checksum: ip address + * old/new for outlayer icmp checksum: + * out-layer: ip address + * inner-layer: ip addr, port, l3 checksum, l4 checksum + */ +#define CNAT_UPDATE_ICMP_ERR_CHECKSUM_DECLARE \ +u16 old_ip_1r, old_ip_2r, old_ip_port_r, old_ip_cr, old_icmp_cr; \ +u16 new_icmp_c; \ +u32 sum32; + + +#define CNAT_UPDATE_ICMP_ERR_CHECKSUM(old_ip_1, old_ip_2, old_ip_port, old_ip_c, old_icmp_c, \ + new_ip_1, new_ip_2, new_ip_port, new_ip_c) \ +old_ip_1r = ~(old_ip_1); \ +old_ip_2r = ~(old_ip_2); \ +old_ip_port_r = ~(old_ip_port); \ +old_ip_cr = ~(old_ip_c); \ +old_icmp_cr = ~(old_icmp_c); \ +sum32 = old_ip_1r + old_ip_2r + new_ip_1 + new_ip_2 + \ + old_ip_port_r + new_ip_port + old_ip_cr + new_ip_c; \ +new32 = old_icmp_cr + sum32; \ +new32 = (new32 & 0xffff) + ((new32 >> 16) & 0xffff); \ +new32 = (new32 & 0xffff) + ((new32 >> 16) & 0xffff); \ +new_icmp_c = ~((u16)new32); \ + +/* + * Add the two 16 bit parts of the 32 bit field + * Repeat it one more time to take care of any overflow + * Complement the u16 value and store it in network format + */ +#define FILL_CHECKSUM(checksum_field, sum32) { \ + sum32 = (sum32 & 0xffff) + ((sum32>>16) & 0xffff); \ + sum32 = (sum32 & 0xffff) + ((sum32>>16) & 0xffff); \ + checksum_field = clib_host_to_net_u16(~((u16) sum32)); \ +} + +static inline void +cnat_v4_recalculate_tcp_checksum (ipv4_header *ip, + tcp_hdr_type *tcp, + u32 *ip_addr_ptr, + u16 *tcp_port_addr_ptr, + u32 new_ip, + u16 new_port) +{ + u32 old_ip_addr, old_ip32_r, new_ip32, sum32; + u16 old_port_r, old_ip_checksum_r, old_tcp_checksum_r; + + u16 *p16; + + p16 = (u16*) ip_addr_ptr; + + old_ip_addr = *ip_addr_ptr; + old_ip32_r = (((u16) ~clib_net_to_host_u16(*p16)) + + ((u16) ~clib_net_to_host_u16(*(p16+1)))); + + old_port_r = ~clib_net_to_host_u16(*tcp_port_addr_ptr); + + *ip_addr_ptr = clib_host_to_net_u32(new_ip); + + new_ip32 = (new_ip & 0xffff) + ((new_ip >> 16) & 0xffff); + + old_ip_checksum_r = ~clib_net_to_host_u16(ip->checksum); + + /* + * Recalculate the new IP checksum + */ + sum32 = old_ip32_r + new_ip32 + old_ip_checksum_r; + + FILL_CHECKSUM(ip->checksum, sum32); + + u16 frag_offset = + clib_net_to_host_u16((ip->frag_flags_offset)); + + if(PREDICT_FALSE(frag_offset & IP_FRAG_OFFSET_MASK)) { + return; /* No need to update TCP fields */ + } + + *tcp_port_addr_ptr = clib_host_to_net_u16(new_port); + old_tcp_checksum_r = ~clib_net_to_host_u16(tcp->tcp_checksum); + + /* + * Recalculate the new TCP checksum + */ + sum32 = old_ip32_r + new_ip32 + + old_port_r + new_port + old_tcp_checksum_r; + + FILL_CHECKSUM(tcp->tcp_checksum, sum32); + + if (PREDICT_FALSE(tcp_logging_enable_flag)) { + tcp_debug_logging( + clib_net_to_host_u32(tcp->seq_num), + clib_net_to_host_u32(tcp->ack_num), + clib_net_to_host_u32(old_ip_addr), + clib_net_to_host_u32(*ip_addr_ptr), + ~old_port_r, + clib_net_to_host_u16(*tcp_port_addr_ptr), + ~old_ip_checksum_r, + clib_net_to_host_u16(ip->checksum), + ~old_tcp_checksum_r, + clib_net_to_host_u16(tcp->tcp_checksum)); + } +} + + +extern void tcp_in2out_nat_mss_n_checksum (ipv4_header *ip, + tcp_hdr_type *tcp, + u32 ipv4_addr, + u16 port, + cnat_main_db_entry_t * db); + +void hex_dump(u8 * p, int len); + +u32 get_my_svi_intf_ip_addr(); + +/* + * in cnat_v4_icmp_gen.c, + * return 1 if icmp msg allow to generate + * for this user + */ + +u32 icmp_msg_gen_allowed (); + +cnat_icmp_msg_t v6_icmp_msg_gen_allowed(); + +int v4_crc_zero_udp_allowed(); +void ipv4_decr_ttl_n_calc_csum(ipv4_header *ipv4); +int icmpv4_generate_with_throttling (spp_ctx_t *ctx, ipv4_header *ipv4, + u16 rx_uidb_index); + +int icmpv6_generate_with_throttling (spp_ctx_t *ctx, ipv6_header_t *ipv4, + u16 rx_uidb_index); + +void icmp_error_generate_v6(spp_ctx_t *ctx, u8 icmp_type, + u8 icmp_code, u16 uidb_index); + +void calculate_window_scale(tcp_hdr_type *tcp_header, u8 *scale); + +void cnat_log_nat44_tcp_seq_mismatch( + cnat_main_db_entry_t *db, + cnat_vrfmap_t *vrfmap); +void print_icmp_pkt (ipv4_header *ip); +void print_udp_pkt (ipv4_header *ip); +void print_tcp_pkt (ipv4_header *ip); +void print_ipv6_pkt (ipv6_header_t *ip); + + +#endif + diff --git a/plugins/vcgn-plugin/vcgn/cnat_v4_pptp_alg.h b/plugins/vcgn-plugin/vcgn/cnat_v4_pptp_alg.h new file mode 100644 index 00000000..5a6d4243 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_v4_pptp_alg.h @@ -0,0 +1,150 @@ +/* + *------------------------------------------------------------------ + * cnat_v4_pptp_alg.h + * + * Copyright (c) 2009-2013 Cisco and/or its affiliates. + * 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 __CNAT_V4_PPTP_ALG_H__ +#define __CNAT_V4_PPTP_ALG_H__ + +/* Debug utils of PPTP */ +#define PPTP_DBG(debug, ...) \ + if(PREDICT_FALSE(cnat_pptp_debug_flag >= debug)) { \ + PLATFORM_DEBUG_PRINT("%s:%s:%d - ", \ + __FILE__, __FUNCTION__, __LINE__);\ + PLATFORM_DEBUG_PRINT(__VA_ARGS__);\ + PLATFORM_DEBUG_PRINT("\n"); \ + } + +#define PPTP_DUMP_PACKET(ip, len) pptp_hex_dump(ip, len) + + +#define PPTP_DISABLED 0 +#define PPTP_ENABLED 1 + +#define PPTP_GRE_TIMEOUT 60 /*sec */ + +#define TCP_PPTP_PORT 1723 + +#define PPTP_PAC 0 +#define PPTP_PNS 1 + +/* PPTP MSG TYPE */ + +#define PPTP_MSG_TYPE_CONTROL 1 +#define PPTP_MSG_TYPE_MGMT 2 + +/* PPTP control messages */ + +/* control connection mgmt */ +#define PPTP_START_CC_RQ 1 +#define PPTP_START_CC_RP 2 +#define PPTP_STOP_CC_RQ 3 +#define PPTP_STOP_CC_RP 4 +#define PPTP_ECHO_RQ 5 +#define PPTP_ECHO_RP 6 + +/* call mgmt */ +#define PPTP_OBOUND_CALL_RQ 7 +#define PPTP_OBOUND_CALL_RP 8 +#define PPTP_IBOUND_CALL_RQ 9 +#define PPTP_IBOUND_CALL_RP 10 +#define PPTP_IBOUND_CALL_CN 11 +#define PPTP_CALL_CLEAR_RQ 12 +#define PPTP_CALL_DISCON_NT 13 + +/* other */ + +#define PPTP_WAN_ERR_NT 14 +#define PPTP_SET_LINK_INF 15 + +#define PPTP_MIN_HDR_LEN 8 + +/* Byte offsets from start of TCP Data(PPTP header) */ + +#define PPTP_CTRL_MGMT_TYPE_OFFSET 0x02 +#define PPTP_CC_TYPE_OFFSET 0x08 +#define PPTP_HDR_CALL_ID_OFFSET 0x0c +#define PPTP_HDR_PEER_CALL_ID_OFFSET 0x0e + +#define PPTP_HDR_RESULT_CODE_OFFSET_STCCRP 0x0e +#define PPTP_HDR_RESULT_CODE_OFFSET 0x10 + + +/* Offset of control/mgmt msg types + from start of TCP header */ + +#define TCP_HEADER_SIZE(tcp) \ + ((tcp->hdr_len>>4) << 2) + + +#define PPTP_MSG_START_OFFSET(tcp) \ + ((u8*)tcp + TCP_HEADER_SIZE(tcp)) + + +#define PPTP_CC_MSG_TYPE_OFFSET(tcp) \ + (PPTP_MSG_START_OFFSET(tcp) + \ + PPTP_CC_TYPE_OFFSET ) + +#define PPTP_MGMT_MSG_TYPE_OFFSET(tcp) \ + ( PPTP_MSG_START_OFFSET(tcp) + \ + PPTP_CTRL_MGMT_TYPE_OFFSET ) + +#define PPTP_CALL_ID_OFFSET(tcp) \ + ( PPTP_MSG_START_OFFSET(tcp) + \ + PPTP_HDR_CALL_ID_OFFSET ) + +#define PPTP_PEER_CALL_ID_OFFSET(tcp) \ + ( PPTP_MSG_START_OFFSET(tcp) + \ + PPTP_HDR_PEER_CALL_ID_OFFSET ) + +#define PPTP_RESULT_CODE_OFFSET(tcp) \ + ( PPTP_MSG_START_OFFSET(tcp) + \ + PPTP_HDR_RESULT_CODE_OFFSET ) + +#define PPTP_RESULT_CODE_OFFSET_STCCRP(tcp) \ + ( PPTP_MSG_START_OFFSET(tcp) + \ + PPTP_HDR_RESULT_CODE_OFFSET_STCCRP) + +/* values */ +#define PPTP_CC_MSG_TYPE(tcp) \ + (u16*)PPTP_CC_MSG_TYPE_OFFSET(tcp) + +#define PPTP_MGMT_MSG_TYPE(tcp) \ + (u16*)PPTP_MGMT_MSG_TYPE_OFFSET(tcp) + +#define PPTP_CALL_ID(tcp) \ + (u16*)PPTP_CALL_ID_OFFSET(tcp) + +#define PPTP_PEER_CALL_ID(tcp) \ + (u16*)PPTP_PEER_CALL_ID_OFFSET(tcp) + +#define PPTP_RESULT_CODE(tcp) \ + *(u8*)PPTP_RESULT_CODE_OFFSET(tcp); + +#define PPTP_RESULT_CODE_STCCRP(tcp) \ + *(u8*)PPTP_RESULT_CODE_OFFSET_STCCRP(tcp); + + +/* other code */ +#define PPTP_CHAN_SUCCESS 1 + + +/* Data structures */ + +extern u32 cnat_pptp_debug_flag; + +#endif /* __CNAT_V4_PPTP_ALG_H__ */ diff --git a/plugins/vcgn-plugin/vcgn/cnat_v4_tcp_in2out_stages.c b/plugins/vcgn-plugin/vcgn/cnat_v4_tcp_in2out_stages.c new file mode 100644 index 00000000..220ced46 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_v4_tcp_in2out_stages.c @@ -0,0 +1,679 @@ +/* + *--------------------------------------------------------------------------- + * cnat_v4_tcp_in2out_stages.c - cnat_v4_tcp_in2out node pipeline stage functions + * + * + * Copyright (c) 2008-2014 Cisco and/or its affiliates. + * 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 +#include +#include +#include + +#include "cnat_db.h" +/* #include */ +#include "ipv4_packet.h" +#include "tcp_header_definitions.h" +#include "cnat_config.h" +#include "cnat_global.h" +#include "cnat_v4_functions.h" +#include "cnat_v4_ftp_alg.h" +#include "cnat_v4_pptp_alg.h" + +#define foreach_cnat_ipv4_tcp_inside_input_error \ +_(TCP_NAT_IN, "packets received") \ +_(TCP_NAT, "packets NATed") \ +_(TCP_EXCEPTION, "packets to exception") \ +_(TCP_TTL_GEN, "Generated TTL Expiry ICMP packet") \ +_(TCP_TTL_DROP, "Could not generate TTL Expiry ICMP packet") \ +_(TCP_SESSION_DROP, "Could not generate session") \ +_(TCP_FRAG_DROP, "Non-first Fragment received") + +typedef enum { +#define _(sym,str) sym, + foreach_cnat_ipv4_tcp_inside_input_error +#undef _ + CNAT_IPV4_TCP_INSIDE_INPUT_N_ERROR, +} cnat_ipv4_tcp_inside_input_t; + +static char * cnat_ipv4_tcp_inside_input_error_strings[] = { +#define _(sym,string) string, + foreach_cnat_ipv4_tcp_inside_input_error +#undef _ + + + +typedef struct cnat_v4_tcp_in2out_pipeline_data_ { + spp_node_main_vector_t *nmv; + /* Add additional pipeline stage data here... */ + u32 bucket; + u16 src_port; /* Added for handling fragments */ + u16 dst_port; /* Added for handling fragments */ +} cnat_v4_tcp_in2out_pipeline_data_t; + +static cnat_v4_tcp_in2out_pipeline_data_t pctx_data[SPP_MAXDISPATCH]; + +#define EXTRA_PIPELINE_ARGS_PROTO , cnat_v4_tcp_in2out_pipeline_data_t *pctx +#define EXTRA_PIPELINE_ARGS , pctx + +ALWAYS_INLINE( +static inline void +stage0(spp_ctx_t **ctxs, int index, spp_node_t *np, + u8 *disp_used EXTRA_PIPELINE_ARGS_PROTO)) +{ + spp_ctx_t *ctx = ctxs[index]; + /* + * Prefetch the context header. This is almost always + * the right thing to do + */ + SPP_PREFETCH_CTX(ctx); +} + +ALWAYS_INLINE( +static inline void +stage1(spp_ctx_t **ctxs, int index, spp_node_t *np, + u8 *disp_used EXTRA_PIPELINE_ARGS_PROTO)) +{ + spp_ctx_t *ctx = ctxs[index]; + /* got ctx, prefetch packet data separately */ + SPP_PREFETCH_CTX_DATA(ctx, 1*CACHE_DATA_QUANTUM); +} + +ALWAYS_INLINE( +static inline void +stage2(spp_ctx_t **ctxs, int index, spp_node_t *np, + u8 *disp_used EXTRA_PIPELINE_ARGS_PROTO)) +{ + spp_ctx_t *ctx = ctxs[index]; + u64 a, b, c; + u32 bucket; + cnat_feature_data_t *fd = (cnat_feature_data_t *)ctx->feature_data; + ipv4_header *ip; + tcp_hdr_type * tcp; + u8 *prefetch_target; + + INCREMENT_NODE_COUNTER(np, TCP_NAT_IN); + + /* extract the key from ctx and save it to feature_data */ + + ip = (ipv4_header *)(ctx->current_header); + ctx->application_start = (ip->version_hdr_len_words & 0xf) << 2; + tcp = (tcp_hdr_type*) ((u8 *)ip + ctx->application_start); + + PLATFORM_CNAT_SET_RX_VRF(ctx,fd->dbl.k.k.vrf, CNAT_TCP, 1); + fd->dbl.k.k.ipv4 = spp_net_to_host_byte_order_32(&ip->src_addr); + + if(PREDICT_FALSE(ctx->ru.rx.frag)) { + /* Must have routed through cnat_v4_frag_in2out node + * Since feature data of the ctx is being used for other + * purposes here, copy them to extra stage argument + */ + u16 *feature_data_ports = (u16 *)&ctx->feature_data[2]; + pctx[index].src_port = fd->dbl.k.k.port = *feature_data_ports; + feature_data_ports++; + pctx[index].dst_port = *feature_data_ports; + } else { + fd->dbl.k.k.port = spp_net_to_host_byte_order_16(&tcp->src_port); + pctx[index].dst_port = + spp_net_to_host_byte_order_16(&tcp->dest_port); + } + +#if 0 + /* extra info for evil mode, or default value for dst_ipv4 field in good mode */ + fd->dbl.dst_ipv4 = address_dependent_filtering ? + spp_net_to_host_byte_order_32(&ip->dest_addr) : 0; +#endif + + CNAT_V4_GET_HASH(fd->dbl.k.key64, + bucket, CNAT_MAIN_HASH_MASK) + + prefetch_target = (u8 *)(&cnat_in2out_hash[bucket]); + pctx[index].bucket = bucket; + + /* Prefetch the hash bucket */ + SPP_PREFETCH(prefetch_target, 0, LOAD); + +} + +ALWAYS_INLINE( +static inline void +stage3(spp_ctx_t **ctxs, int index, spp_node_t *np, + u8 *disp_used EXTRA_PIPELINE_ARGS_PROTO)) +{ + u32 db_index; + u32 bucket; + uword prefetch_target0, prefetch_target1; + + bucket = pctx[index].bucket; + + /* read the hash bucket */ + db_index = pctx[index].bucket = cnat_in2out_hash[bucket].next; + if (PREDICT_TRUE(db_index != EMPTY)) { + + /* + * Prefetch database keys. We save space by not cache-line + * aligning the DB entries. We don't want to waste LSU + * bandwidth prefetching stuff we won't need. + */ + + prefetch_target0 = (uword)(cnat_main_db + db_index); + + SPP_PREFETCH(prefetch_target0, 0, LOAD); + + /* Just beyond DB key #2 */ + + prefetch_target1 = prefetch_target0 + + STRUCT_OFFSET_OF(cnat_main_db_entry_t, user_ports); + + /* If the targets are in different lines, do the second prefetch */ + + if (PREDICT_FALSE((prefetch_target0 & ~(SPP_CACHE_LINE_BYTES-1)) != + (prefetch_target1 & ~(SPP_CACHE_LINE_BYTES-1)))) { + + SPP_PREFETCH(prefetch_target1, 0, LOAD); + + } + } +} + +static inline void +stage4(spp_ctx_t **ctxs, int index, spp_node_t *np, + u8 *disp_used EXTRA_PIPELINE_ARGS_PROTO) +{ + spp_ctx_t *ctx = ctxs[index]; + u32 db_index = pctx[index].bucket; + cnat_main_db_entry_t *db; + cnat_feature_data_t *fd; + + /* + * Note: if the search already failed (empty bucket), + * the answer is already in the pipeline context structure + */ + if (PREDICT_FALSE(db_index == EMPTY)) { + return; + } + + fd = (cnat_feature_data_t *)ctx->feature_data; + + /* + * Note: hash collisions suck. We can't easily prefetch around them. + * The first trip around the track will be fast. After that, maybe + * not so much... + */ + do { + + db = cnat_main_db + db_index; + if (PREDICT_TRUE(db->in2out_key.key64 == fd->dbl.k.key64)) + break; + db_index = db->in2out_hash.next; + + } while (db_index != EMPTY); + + /* even in evil mode, for in2out, we nat all packets regardless mode and dst_ip */ + + /* Stick the answer back into the pipeline context structure */ + pctx[index].bucket = db_index; +} + +ALWAYS_INLINE( +static inline void +stage5(spp_ctx_t **ctxs, int index, spp_node_t *np, + u8 *disp_used EXTRA_PIPELINE_ARGS_PROTO)) +{ + spp_ctx_t *ctx = ctxs[index]; + u32 db_index = pctx[index].bucket; + cnat_feature_data_t *fd = (cnat_feature_data_t *)ctx->feature_data; + int disposition; + cnat_main_db_entry_t *db; + /* Below two pointers are just to keep the cnat_ftp_alg call happy*/ + dslite_table_entry_t *dslite_entry_ptr = NULL; + ipv6_header_t *ipv6_hdr = NULL; + tcp_hdr_type *tcp; + ipv4_header *ip; + i8 delta; + u32 seq, seq1; + u32 window; + u8 scale; + int rc; + + ip = (ipv4_header *) ctx->current_header; + + if (PLATFORM_HANDLE_TTL_DECREMENT) { + if (PREDICT_FALSE(ip->ttl <= 1)) { + /* Try to generate ICMP error msg, as TTL is <= 1 */ + + if (icmpv4_generate_with_throttling + (ctx, ip, ctx->ru.rx.uidb_index)) { + /* Generated ICMP */ + disposition = CNAT_REWRITE_OUTPUT; + INCREMENT_NODE_COUNTER(np, TCP_TTL_GEN); + } else { + /* Could not generated ICMP - drop the packet */ + disposition = CNAT_DROP; + INCREMENT_NODE_COUNTER(np, TCP_TTL_DROP); + } + goto drop_pkt; + } + } + + if (PREDICT_FALSE(db_index == EMPTY)) { + if(PREDICT_FALSE(ctx->ru.rx.frag)) { + /* Must have routed through cnat_v4_frag_in2out node */ + u16 frag_offset = + spp_net_to_host_byte_order_16(&(ip->frag_flags_offset)); + if(PREDICT_FALSE(frag_offset & IP_FRAG_OFFSET_MASK)) { + INCREMENT_NODE_COUNTER(np, TCP_FRAG_DROP); + disposition = CNAT_DROP; + goto drop_pkt; + } else { + INCREMENT_NODE_COUNTER(np, TCP_EXCEPTION); + disposition = CNAT_V4_TCP_IE; + } + } else { + INCREMENT_NODE_COUNTER(np, TCP_EXCEPTION); + disposition = CNAT_V4_TCP_IE; + } + } else { + cnat_key_t dest_info; + cnat_session_entry_t *session_db = NULL; + db = cnat_main_db + db_index; + /* Handle destination sessions */ + tcp = (tcp_hdr_type*) ((u8*)ip + ctx->application_start); + dest_info.k.port = pctx[index].dst_port; + dest_info.k.ipv4 = spp_net_to_host_byte_order_32(&(ip->dest_addr)); + + if(PREDICT_TRUE(!PLATFORM_DBL_SUPPORT)) { + + /* No DBL support, so just update the destn and proceed */ + db->dst_ipv4 = dest_info.k.ipv4; + db->dst_port = dest_info.k.port; + goto update_pkt; + } + + if(PREDICT_FALSE(db->dst_ipv4 != dest_info.k.ipv4 || + db->dst_port != dest_info.k.port)) { + if(PREDICT_TRUE(db->nsessions == 0)) { + /* Should be a static entry + * Note this session as the first session and log + */ + cnat_add_dest_n_log(db, &dest_info); + } else if(PREDICT_FALSE(db->nsessions == 1)) { + /* Destn is not same as in main db. Multiple session + * scenario + */ + dest_info.k.vrf = db->in2out_key.k.vrf; + session_db = cnat_handle_1to2_session(db, &dest_info); + if(PREDICT_FALSE(session_db == NULL)) { + disposition = CNAT_DROP; + INCREMENT_NODE_COUNTER(np, TCP_SESSION_DROP); + goto drop_pkt; + } + } else { /* There are already multiple destinations */ + dest_info.k.vrf = db->in2out_key.k.vrf; + /* If session already exists, + * cnat_create_session_db_entry will return the existing db + * else create a new db + * If could not create, return NULL + */ + session_db = cnat_create_session_db_entry(&dest_info, + db, TRUE); + if(PREDICT_FALSE(session_db == NULL)) { + disposition = CNAT_DROP; + INCREMENT_NODE_COUNTER(np, TCP_SESSION_DROP); + goto drop_pkt; + } + } + if(PREDICT_TRUE(session_db)) { + /* Have to repeat the window size check for new destinations */ + window = (u32)spp_net_to_host_byte_order_16( + &tcp->window_size); + window = window << session_db->scale; + if(PREDICT_TRUE(!session_db->window)) { + calculate_window_scale(tcp, &scale); + session_db->scale = scale; + session_db->window = window; + } else if (PREDICT_FALSE(session_db->window < + window)) { + /* Update the db entry with window option from packet */ + session_db->window = window; + } else { + /* Do nothing */ + } + session_db->tcp_seq_num = spp_net_to_host_byte_order_32( + &tcp->seq_num); + session_db->ack_no = spp_net_to_host_byte_order_32( + &tcp->ack_num); + if (PREDICT_FALSE(global_debug_flag && CNAT_DEBUG_GLOBAL_ALL)) { + PLATFORM_DEBUG_PRINT("\n In2out SDB stages seq no = %u," + " ack no = %u, window = %u\n", + session_db->tcp_seq_num, + session_db->ack_no, + session_db->window); + } + } + } else { + //Update the seq no and ack no for subsequent communication + //after connection establishment + //No need to update window here. Window is already updated + //during connection establishment + window = (u32)spp_net_to_host_byte_order_16( + &tcp->window_size); + window = window << db->scale; + if(PREDICT_FALSE(!ALG_ENABLED_DB(db))) { + //This check is done since proto_data is part of union in main + //db entry + db->proto_data.tcp_seq_chk.seq_no = + spp_net_to_host_byte_order_32( + &tcp->seq_num); + db->proto_data.tcp_seq_chk.ack_no = + spp_net_to_host_byte_order_32( + &tcp->ack_num); + } + if (PREDICT_FALSE(db->diff_window < window)) { + /* Update the db entry with window option from packet */ + db->diff_window = window; + } + if (PREDICT_FALSE(global_debug_flag && CNAT_DEBUG_GLOBAL_ALL)) { + PLATFORM_DEBUG_PRINT("\n In2out MainDB seq no = %u," + "\n ack no = %u\n", + db->proto_data.tcp_seq_chk.seq_no, + db->proto_data.tcp_seq_chk.ack_no); + PLATFORM_DEBUG_PRINT("\n In2out MAINDB window = %u\n", + db->diff_window); + } + } +update_pkt: + + INCREMENT_NODE_COUNTER(np, TCP_NAT); + + disposition = CNAT_REWRITE_OUTPUT; + + /* NAT the packet and update checksum (increamental) */ + + /* If it is a non-first fragment, we need not worry about + * ALGs as the packet does not have TCP header.. + * However, under a very race scenario when this non-first + * fragment is containing an FTP PORT command OR RTSP command + * we cannot handle that case.. in that case the ALG will fail + * Do not want to add a lot of complexity to handle one in million + * of such ALG case + */ + u16 frag_offset = + spp_net_to_host_byte_order_16(&(ip->frag_flags_offset)); + + if(PREDICT_FALSE(frag_offset & IP_FRAG_OFFSET_MASK)) { + /* Non first fragment.. no TCP header */ + FTP_ALG_DEBUG_PRINTF("Non first frag.. cannot handle ALG"); + goto handle_ttl_n_checksum; + } + + FTP_ALG_DEBUG_PRINTF("src port 0x%x, dst_port 0x%x", + spp_net_to_host_byte_order_16(&tcp->src_port), + spp_net_to_host_byte_order_16(&tcp->dest_port)) + + /* handle FTP ALG */ + if (PREDICT_FALSE(ftp_alg_enabled && + (spp_net_to_host_byte_order_16(&tcp->src_port) == 21 || + spp_net_to_host_byte_order_16(&tcp->dest_port) == 21))) { + + if(PREDICT_FALSE((db->flags & CNAT_DB_FLAG_PPTP_TUNNEL_ACTIVE) || + (db->flags & CNAT_DB_FLAG_PPTP_TUNNEL_INIT))) + { + /* FTP on a PPTP Control session? Ignore FTP */ + goto handle_ttl_n_checksum; + } + + if (PREDICT_FALSE(tcp->flags & (TCP_FLAG_SYN | TCP_FLAG_RST | + TCP_FLAG_FIN))) { + + FTP_ALG_DEBUG_PRINTF("SYN Case setting delta = 0") + + /* reset the delta */ + if(PREDICT_FALSE(session_db != NULL)) { + session_db->alg.delta = 0; + } else { + db->alg.delta = 0; + } + + } else { + + /* need to adjust seq # for in2out pkt if delta is not 0 */ + if (PREDICT_TRUE((session_db && (session_db->alg.delta != 0)) + || ((!session_db) && (db->alg.delta != 0)))) { + seq = net2host32(&tcp->seq_num); + + FTP_ALG_DEBUG_PRINTF("Orig Seq Num 0x%x", seq) + /* + * for ftp packets, due to PORT command translation, + * we may have cases that a packet/payload len gets + * changed for tcp, we need to adjust the packet's + * sequence numbers to match the changes. The delta + * of orig pkt len and new len is in alg_dlt[1] together + * with the sequence number that cuased the delta. When + * there are multiple len changes, we keep theprevious + * delta in alg_dlt[0] for case like pkt retransmission. + * So depends on packet seq number, we decide to use + * either latest delta or previous delta ([0]) + * We won't be here if both delta values are 0 + */ + if(PREDICT_FALSE(session_db != NULL)) { + seq1 = seq > session_db->tcp_seq_num ? + (seq + session_db->alg.alg_dlt[1]): + (seq + session_db->alg.alg_dlt[0]); + } else { + seq1 = seq > db->proto_data.seq_pcp.tcp_seq_num ? + (seq + db->alg.alg_dlt[1]): + (seq + db->alg.alg_dlt[0]); + } + + FTP_ALG_DEBUG_PRINTF("Old_seq_num 0x%x New Seq Num 0x%x", + seq, seq1) + + if (PREDICT_TRUE(seq1 != seq)) { + + tcp->seq_num = host2net32(seq1); + + FTP_ALG_DEBUG_PRINTF("Old TCP Checksum 0x%x", + net2host16(&tcp->tcp_checksum)) + + /* + * fix checksum incremental for seq # changes + * newchecksum = ~(~oldchecksum + ~old + new) + */ + CNAT_UPDATE_TCP_SEQ_ACK_CHECKSUM(seq, seq1) + } /* There is a diff in seq */ + + } /* ALG Delta is non zero */ + + rc = cnat_ftp_alg((u8*) ip, &delta, db, dslite_entry_ptr, ipv6_hdr); + + FTP_ALG_DEBUG_PRINTF("cnat_ftp_alg rc 0x%x", rc) + + /*if located PORT cmd, packet being updated, take the delta and seq # */ + if (PREDICT_FALSE(rc)) { + + /* set alg flag for this ftp control connection */ + if(PREDICT_FALSE(session_db != NULL)) { + session_db->flags |= CNAT_DB_FLAG_ALG_CTRL_FLOW; + } else { + db->flags |= CNAT_DB_FLAG_ALG_CTRL_FLOW; + } + + /* + * rc != 0 indicates this packet has triggered a new pkt len delta + * we need to update db entry's seq# with seq# of this packet. + * + * Move alg_dlt[1] to [0], (current delta -> previous delta) + * then apply latest delta to alg_dlt[1] (keep [1] as latest delta) + */ + if(PREDICT_FALSE(session_db != NULL)) { + session_db->tcp_seq_num = net2host32(&tcp->seq_num); + session_db->alg.alg_dlt[0] = session_db->alg.alg_dlt[1]; + + /* accumulate the delta ! */ + session_db->alg.alg_dlt[1] += delta; + FTP_ALG_DEBUG_PRINTF( + "cnat_ftp_alg seq_num 0x%x, dlt0 0x%x, dlt1 0x%x", + session_db->tcp_seq_num, + session_db->alg.alg_dlt[0], + session_db->alg.alg_dlt[1]) + + } else { + db->proto_data.seq_pcp.tcp_seq_num = net2host32(&tcp->seq_num); + db->alg.alg_dlt[0] = db->alg.alg_dlt[1]; + + /* accumulate the delta ! */ + db->alg.alg_dlt[1] += delta; + + FTP_ALG_DEBUG_PRINTF( + "cnat_ftp_alg seq_num 0x%x, dlt0 0x%x, dlt1 0x%x", + db->proto_data.seq_pcp.tcp_seq_num, + db->alg.alg_dlt[0], + db->alg.alg_dlt[1]) + } + ctx->current_length += delta; + }/* cnat_ftp_alg returned non zero */ + } /* It is not a SYN, RST or FIN */ + } else if (PREDICT_FALSE(rtsp_alg_port_num && + ((spp_net_to_host_byte_order_16(&tcp->dest_port) == rtsp_alg_port_num) || + (spp_net_to_host_byte_order_16(&tcp->src_port) == rtsp_alg_port_num))) ) { + + if (PREDICT_FALSE(tcp->flags & (TCP_FLAG_SYN | TCP_FLAG_RST | + TCP_FLAG_FIN))) { + + FTP_ALG_DEBUG_PRINTF("SYN Case setting delta = 0") + + /* reset the delta */ + if(PREDICT_FALSE(session_db != NULL)) { + session_db->alg.delta = 0; + } else { + db->alg.delta = 0; + } + + } else { +#define RTSP_ALG_DELTA_MASK 0xFF + /* need to adjust seq # for in2out pkt if delta is not 0 */ + if (PREDICT_FALSE((session_db && + (session_db->alg.delta & RTSP_ALG_DELTA_MASK) != 0) || + ((!session_db) && + (db->alg.delta & RTSP_ALG_DELTA_MASK) != 0))) { + seq = net2host32(&tcp->seq_num); + + if(PREDICT_FALSE(session_db != NULL)) { + seq1 = seq > session_db->tcp_seq_num ? + (seq + db->alg.alg_dlt[1]): + (seq + db->alg.alg_dlt[0]); + } else { + seq1 = seq > db->proto_data.seq_pcp.tcp_seq_num ? + (seq + db->alg.alg_dlt[1]): + (seq + db->alg.alg_dlt[0]); + } + + FTP_ALG_DEBUG_PRINTF("Old_seq_num 0x%x New Seq Num 0x%x", + seq, seq1) + + if (PREDICT_TRUE(seq1 != seq)) { + + tcp->seq_num = host2net32(seq1); + + FTP_ALG_DEBUG_PRINTF("Old TCP Checksum 0x%x", + net2host16(&tcp->tcp_checksum)) + + /* + * fix checksum incremental for seq # changes + * newchecksum = ~(~oldchecksum + ~old + new) + */ + CNAT_UPDATE_TCP_SEQ_ACK_CHECKSUM(seq, seq1) + } + + } + } + if ((session_db && (!session_db->alg.il)) || + ((!session_db) && (!db->alg.il))) { + cnat_rtsp_alg((u8*) ip, + &delta, + db, + ctx->current_length, + NULL, + NULL); + } + } +handle_ttl_n_checksum: + if (PLATFORM_HANDLE_TTL_DECREMENT) { + /* + * Decrement TTL and update IPv4 checksum + */ + ipv4_decr_ttl_n_calc_csum(ip); + } + + tcp_in2out_nat_mss_n_checksum(ip, + tcp, + db->out2in_key.k.ipv4, + db->out2in_key.k.port, + db); +/* CNAT_PPTP_ALG_SUPPORT */ + /* code to handle pptp control msgs */ + if(PREDICT_FALSE( + (spp_net_to_host_byte_order_16(&tcp->dest_port) == + TCP_PPTP_PORT))) { + + u32 ret; + + PPTP_DBG(3, "PPTP mgmt/ctrl msg recieved"); + + ret = cnat_handle_pptp_msg(ctx, db , tcp, PPTP_PNS ); + + if( PREDICT_FALSE( ret != CNAT_SUCCESS) ) { + PPTP_DBG(3, "PPTP mgmt/ctrl msg drop"); + disposition = CNAT_DROP; + PPTP_INCR(ctrl_msg_drops); + goto drop_pkt; + } + } + +/* CNAT_PPTP_ALG_SUPPORT */ + + /* update transaltion counters */ + db->in2out_pkts++; + + in2out_forwarding_count++; + + PLATFORM_CNAT_SET_TX_VRF(ctx,db->out2in_key.k.vrf); + + /* update the timer for good mode, or evil mode dst_ip match */ + +// if (!address_dependent_filtering || fd->dbl.dst_ipv4 == db->dst_ipv4) { + if(PREDICT_FALSE(session_db != NULL)) { + V4_TCP_UPDATE_SESSION_DB_FLAG(session_db, tcp); + CNAT_DB_TIMEOUT_RST(session_db); + } else { + V4_TCP_UPDATE_SESSION_FLAG(db, tcp); + CNAT_DB_TIMEOUT_RST(db); + } + +// } + + } + + /* Pick up the answer and put it into the context */ + fd->dbl.db_index = db_index; + +drop_pkt: + + DISP_PUSH_CTX(np, ctx, disposition, disp_used, last_disposition, last_contexts_ptr, last_nused_ptr); + +} + diff --git a/plugins/vcgn-plugin/vcgn/cnat_va_db.c b/plugins/vcgn-plugin/vcgn/cnat_va_db.c new file mode 100644 index 00000000..7423bdf2 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_va_db.c @@ -0,0 +1,286 @@ +/* + *------------------------------------------------------------------ + * cnat_va_db.c - virtual assembly database + * + * Copyright (c) 2009, 2013 Cisco and/or its affiliates. + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +va_bucket_t va_bucket[VA_BUCKETS]; + +void va_bucket_init () { + + u32 i; + + /* + * set the pointer in each bucket + * points to nowhere + */ + for (i=0; i [%d, %d]\n", + bucket_index, entry_p->src_port, + entry_p->dst_port, key->e.src_port, key->e.dst_port) + + /* found match entry, update it */ + entry_p->src_port = key->e.src_port; + entry_p->dst_port = key->e.dst_port; + + FRAG_DEBUG_PRINTF3("VA_ADD_NEW: Existing bucket %d, counter %d\n", + bucket_index, + va_bucket[bucket_index].new_entry_counter) + + } else { + + /* no match, add a new one */ + head = va_bucket[bucket_index].head_entry; + next = va_bucket[bucket_index].next_available_entry; + + FRAG_DEBUG_PRINTF5( + "\nVA_ADD_NEW: Filling bucket %d, index %d with key 0x%llx %x\n", + bucket_index, next, key->k.key64, key->k.key32) + + va_bucket[bucket_index].va_entry[next] = key->e; + + /* increase next pointer */ + va_bucket[bucket_index].next_available_entry = (next+1) & VA_BUCKET_MASK; + + if (PREDICT_FALSE(head == va_bucket[bucket_index].next_available_entry)) { + /* adjust head circular pointer */ + va_bucket[bucket_index].head_entry = (head+1) & VA_BUCKET_MASK; + } + + va_bucket[bucket_index].new_entry_counter++; + + FRAG_DEBUG_PRINTF4( + "VA_ADD_NEW: NEW bucket %d, entry %d counter %d\n", + bucket_index, next, va_bucket[bucket_index].new_entry_counter) + } +} + + +/* + * use the key, + * return pointer to the entry if found, + * NULL if not + */ + +inline +va_entry_t * va_db_lookup (u32 bucket_index, va_lookup_key * key) +{ + + u32 index, next; + va_entry_t * entry_p; + va_bucket_t * bucket; + + bucket = &va_bucket[bucket_index]; + index = bucket->head_entry; + next = bucket->next_available_entry; + entry_p = NULL; + + FRAG_DEBUG_PRINTF4( + "\nVA_DB_LOOKUP: bucket index %d head %d next %d\n", + bucket_index, index, next) + + /* loop through the entries in the bucket */ + while( index != next) { + + if(PREDICT_TRUE(memcmp(&bucket->va_entry[index], key, VA_KEY_SIZE)==0)) { + + entry_p = &bucket->va_entry[index]; + /*In add frag entry function we are again assigning key's src + port to entry_p's src port. So when a main DB entry is deleted/ + timed out, and again another entry is created for the same + src ip and src port pair, the frag's entry_p will have the + previous port info stored and not updated. Hence the below + line is not required*/ + + /* *(u32*)&key->e.src_port = *(u32*)&entry_p->src_port; */ + /* do two ports as u32 :) */ + + break; + } + + index = (index +1) & VA_BUCKET_MASK; + + } + +#ifdef FRAG_DEBUG + if (PREDICT_TRUE(entry_p)) { + FRAG_DEBUG_PRINTF3("VA_DB_LOOKUP: bucket index %d entry index %d\n", + bucket_index, index) + FRAG_DEBUG_PRINTF5("VA_DB_LOOKUP: SRC-->DST [0x%x, %d] [0x%x, %d]\n", + entry_p->src_ip, entry_p->src_port, + entry_p->dst_ip, entry_p->dst_port) + FRAG_DEBUG_PRINTF3("[vrf 0x%x, id 0x%x]\n", + entry_p->vrf, entry_p->ip_id) + } else { + FRAG_DEBUG_PRINTF1("\nNULL ENTRY\n") + } +#endif + + return entry_p; + +} + +inline +int va_db_delete_entry (u32 bucket_index, va_lookup_key * key) +{ + + u32 index, next; + int entry_found = 0; + va_bucket_t * bucket; + + bucket = &va_bucket[bucket_index]; + index = bucket->head_entry; + next = bucket->next_available_entry; + + FRAG_DEBUG_PRINTF4( + "\nVA_DB_DELETE_ENTRY: bucket index %d head %d next %d\n", + bucket_index, index, next); + + /* loop through the entries in the bucket */ + while( index != next) { + if(PREDICT_TRUE(memcmp(&bucket->va_entry[index], key, + VA_KEY_SIZE)==0)) { + /* Clear the entry */ + FRAG_DEBUG_PRINTF1("Entry found in delete API"); + memset(&bucket->va_entry[index], 0, sizeof(va_entry_t)); + entry_found = 1; + break; + } + index = (index +1) & VA_BUCKET_MASK; + } + return entry_found; +} + + + +void cnat_va_bucket_used (int argc, unsigned long * argv) +{ + + u32 i, sum = 0;; + + for(i=0;i 0)) sum ++; + } + + PLATFORM_DEBUG_PRINT("buckets in use: %d\n", sum); + + sum = 0; + for(i=0; i= VA_BUCKETS)) { + PLATFORM_DEBUG_PRINT("invalid bucket index %d\n", index); + return; + } + + PLATFORM_DEBUG_PRINT("\n====== Bucket %d ======\n", index); + + PLATFORM_DEBUG_PRINT("bucket head index %d\n", va_bucket[index].head_entry); + + PLATFORM_DEBUG_PRINT("bucket next index %d\n", va_bucket[index].next_available_entry); + + PLATFORM_DEBUG_PRINT(" source IP dest IP VRF ip-id srcP dstP\n"); + + for(i=0;i + +#define FRAG_DEBUG 1 + +/* virtual assemble hash database size ~ 16B x 64K = 1MB */ + +#define VA_TOTAL_ENTRIES (64*1024) +#define VA_ENTRY_PER_BUCKET (8) /* make sure size is power of 2 for circular FIFO */ +#define VA_BUCKET_MASK (VA_ENTRY_PER_BUCKET -1) +#define VA_BUCKETS (VA_TOTAL_ENTRIES / VA_ENTRY_PER_BUCKET) +#define VA_KEY_SIZE 12 + +typedef struct _va_entry { + /* key: top 12 bytes */ + u32 src_ip; + u32 dst_ip; + u16 vrf; /* overloaded with protocol info with top two bits */ + u16 ip_id; + + /* values */ + u16 src_port; + u16 dst_port; +} va_entry_t; + +typedef struct _va_keys { + u64 key64; /* src & dst IP */ + u32 key32; /* vrf, protocol and ip_id */ +} va_keys; + +typedef union { + va_entry_t e; + va_keys k; +} va_lookup_key; + +typedef struct _va_bucket_t { + u32 head_entry; + u32 next_available_entry; /* ~0 for empty bucket */ + u32 new_entry_counter; /* for debug purpose */ + va_entry_t va_entry[VA_ENTRY_PER_BUCKET]; +} va_bucket_t; + +extern va_bucket_t va_bucket[]; /* hash table in cnat_va_db.c */ + +void va_bucket_init (); + +inline void va_db_add_new_entry (u32 bucket_index, va_lookup_key * ); +inline int va_db_delete_entry (u32 bucket_index, va_lookup_key * ); +inline va_entry_t * va_db_lookup (u32 bucket_index, va_lookup_key * key); + +#ifdef FRAG_DEBUG + +#define FRAG_DEBUG_PRINTF1(a) \ + if (frag_debug_flag) { \ + PLATFORM_DEBUG_PRINT(a); \ + } + +#define FRAG_DEBUG_PRINTF2(a, b) \ + if (frag_debug_flag) { \ + PLATFORM_DEBUG_PRINT(a, b); \ + } + +#define FRAG_DEBUG_PRINTF3(a, b, c) \ + if (frag_debug_flag) { \ + PLATFORM_DEBUG_PRINT(a, b, c); \ + } + +#define FRAG_DEBUG_PRINTF4(a, b, c, d) \ + if (frag_debug_flag) { \ + PLATFORM_DEBUG_PRINT(a, b, c, d); \ + } + +#define FRAG_DEBUG_PRINTF5(a, b, c, d, e) \ + if (frag_debug_flag) { \ + PLATFORM_DEBUG_PRINT(a, b, c, d, e); \ + } + +#define FRAG_DEBUG_PRINTF6(a, b, c, d, e, f) \ + if (frag_debug_flag) { \ + PLATFORM_DEBUG_PRINT(a, b, c, d, e, f); \ + } +#else + +#define FRAG_DEBUG_PRINTF1(a) + +#define FRAG_DEBUG_PRINTF2(a, b) + +#define FRAG_DEBUG_PRINTF3(a, b, c) + +#define FRAG_DEBUG_PRINTF4(a, b, c, d) + +#define FRAG_DEBUG_PRINTF5(a, b, c, d, e) + +#define FRAG_DEBUG_PRINTF6(a, b, c, d, e, f) + +#endif + +#endif /* __CNAT_VA_DB_H__ */ + + diff --git a/plugins/vcgn-plugin/vcgn/dslite_db.h b/plugins/vcgn-plugin/vcgn/dslite_db.h new file mode 100644 index 00000000..2269b98c --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/dslite_db.h @@ -0,0 +1,170 @@ +/* + *------------------------------------------------------------------ + * dslite_db.h - Stateful DSLITE translation database definitions + * + * Copyright (c) 2010-2013 Cisco and/or its affiliates. + * 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 __DSLITE_DB_H__ +#define __DSLITE_DB_H__ + +#include "cnat_cli.h" +#include "index_list.h" +#include "cnat_ports.h" +#include "cnat_db.h" +#include "dslite_defs.h" + +#define DSLITE_PRINTF(level, ...) \ + if (dslite_debug_level > level) PLATFORM_DEBUG_PRINT(__VA_ARGS__); +/* +#define DSLITE_PRINTF(lvl, ...) \ +{ \ + avsm_dispatlib_debug (__VA_ARGS__); \ +} +*/ + +#define HASH_ENHANCE 4 +//#define DSLITE_DEF +#define DSLITE_MAIN_DB_SIZE (20000000 / PLATFORM_CNAT_INSTS) +#define DSLITE_MAIN_HASH_SIZE \ + (HASH_ENHANCE * PLATFORM_CNAT_MAIN_PRELIM_HASH_SIZE) + +#define DSLITE_MAIN_HASH_MASK (DSLITE_MAIN_HASH_SIZE-1) + + +/* nb: 200000 users / 64 CNAT = 3125, 76% occupancy */ +#define DSLITE_USER_HASH_SIZE CNAT_USER_HASH_SIZE +#define DSLITE_USER_HASH_MASK (DSLITE_USER_HASH_SIZE-1) + +/* No. of per ip/port config will be limited to 1000 */ +#define DSLITE_TIMEOUT_HASH_SIZE 1000 +#define DSLITE_TIMEOUT_HASH_MASK (DSLITE_TIMEOUT_HASH_SIZE - 1) +#define DSLITE_TIMEOUT_FULL_MASK 0xFFFFFFFFFFFFFFFF + +#define CNAT_MAX_SESSIONS_PER_BIB 0xFFFF + +#define FORCE_DEL 1 /* Delete static BIB entries as well */ + +/* default timeout values */ +#define DSLITE_UDP_DEFAULT 300 /* 5 min */ +#define DSLITE_UDP_MIN 120 /* 2 min */ +#define DSLITE_TCP_TRANS 240 /* 4 min */ +#define DSLITE_TCP_EST 7200 /* 2 hrs */ +#define DSLITE_TCP_V4_SYN 6 /* 6 sec */ +#define DSLITE_FRAG_MIN 2 /* 2 sec */ +#define DSLITE_ICMP_DEFAULT 60 /* 1 min */ + +extern u32 dslite_translation_create_count; +extern u32 dslite_translation_delete_count; +extern u32 dslite_translation_create_rate; +extern u32 dslite_translation_delete_rate; +extern u32 dslite_in2out_forwarding_count; +extern u32 dslite_in2out_forwarding_rate; +extern u32 dslite_out2in_forwarding_count; +extern u32 dslite_out2in_forwarding_rate; + +#define DSLITE_V6_GET_HASH(in_key, hash, mask) \ + a = in_key->ipv6[0] ^ in_key->ipv6[1] ^ in_key->ipv6[2] ^ in_key->ipv6[3] \ + ^ in_key->ipv4_key.k.ipv4 ^ ((in_key->ipv4_key.k.port << 16) | in_key->ipv4_key.k.vrf); \ + DSLITE_PRINTF(1, "%x:%x:%x:%x:%x:%x:%x\n", in_key->ipv6[0], in_key->ipv6[1], in_key->ipv6[2], in_key->ipv6[3], \ + in_key->ipv4_key.k.ipv4, in_key->ipv4_key.k.port, in_key->ipv4_key.k.vrf); \ + b = c = 0x9e3779b9;\ + /* Jenkins hash, arbitrarily use c as the "answer" */ \ + hash_mix32(a, b, c); \ + hash = c & mask; \ + + +#define DSLITE_V6_GET_USER_HASH(ipv6, hash, mask) \ + a = ipv6[0] ^ ipv6[1] ^ ipv6[2] ^ ipv6[3]; \ + b = c = 0x9e3779b9;\ + /* Jenkins hash, arbitrarily use c as the "answer" */ \ + hash_mix32(a, b, c); \ + hash = c & mask; \ + +#define DSLITE_V4_GET_HASH(in_key, hash, mask) \ + a = in_key.ipv4 ^ ((in_key.port << 16) | in_key.vrf); \ + b = c = 0x9e3779b9; \ + /* Jenkins hash, arbitrarily use c as the "answer" */ \ + hash_mix32(a, b, c); \ + hash = c & mask; + +#define PRIVATE_V4_ADDR_CHECK(addr, invalid) \ + invalid = 0; \ + int range1 = ((addr & 0xFF000000) >> 24); \ + int range2 = ((addr & 0xFFF00000) >> 20); \ + int range3 = ((addr & 0xFFFF0000) >> 16); \ + int range4 = ((addr & 0xFFFFFFF8) >> 3); \ + if(range1 != 0xa && range2 != 0xac1 && range3 != 0xc0a8 && range4 != 0x18000000) \ + invalid = 1; + +#define V4_MAPPED_V6_CHECK(v6_addr, invalid) \ + invalid = 0; \ + int word1 = v6_addr[0]; \ + int word2 = v6_addr[1]; \ + int word3 = v6_addr[2]; \ + if(!((word1 == 0) && (word2 == 0) && (word3 == 0x0000FFFF))) \ + invalid = 1; + + +extern dslite_table_entry_t dslite_table_array[DSLITE_MAX_DSLITE_ENTRIES]; +extern dslite_table_entry_t *dslite_table_ptr; + +#define DSLITE_CMP_V6_KEY(key1, key2) \ + memcmp(key1, key2, sizeof(dslite_v6_key_t)) + +#define DSLITE_CMP_V4_KEY(key1, key2) \ + memcmp(key1, key2, sizeof(dslite_v4_key_t)) + + +#define DSLITE_CMP_V6_IP(ip1, ip2) \ + memcmp(ip1, ip2, (sizeof(u32) * 4)) + + +#define DSLITE_CMP_V6_KEY1(key1, key2) \ + (key1.ipv6[0] == key2.ipv6[0]) && (key1.ipv6[1] == key2.ipv6[1]) && \ + (key1.ipv6[2] == key2.ipv6[2]) && (key1.ipv6[3] == key2.ipv6[3]) && \ + (key1.port == key2.port) && (key1.vrf == key2.vrf) + + +#define DSLITE_CMP_V6_IP1(ip1, ip2) \ + ((ip1[0] == ip2[0]) && (ip1[1] == ip2[1]) && \ + (ip1[2] == ip2[2]) && (ip1[3] == ip2[3])) + +#define DSLITE_CMP_V4_KEY1(key1, key2) \ + (key1.key64 == key2.key64) + +cnat_main_db_entry_t* +dslite_get_main_db_entry_v2(dslite_db_key_bucket_t *ki, + port_pair_t port_pair_type, + port_type_t port_type, + cnat_gen_icmp_info *info, + dslite_table_entry_t *dslite_entry_ptr, + cnat_key_t *dest_info); + +cnat_main_db_entry_t* +dslite_main_db_lookup_entry(dslite_db_key_bucket_t *ki); + + +cnat_user_db_entry_t* +dslite_user_db_lookup_entry(dslite_db_key_bucket_t *uki); + +cnat_user_db_entry_t* +dslite_user_db_create_entry(dslite_db_key_bucket_t *uki, u32 portmap_index); + +cnat_main_db_entry_t* +dslite_create_main_db_entry_and_hash(dslite_db_key_bucket_t *ki, + cnat_db_key_bucket_t *ko, + cnat_user_db_entry_t *udb); + +#endif diff --git a/plugins/vcgn-plugin/vcgn/dslite_defs.h b/plugins/vcgn-plugin/vcgn/dslite_defs.h new file mode 100644 index 00000000..4860adcb --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/dslite_defs.h @@ -0,0 +1,336 @@ +/* + *------------------------------------------------------------------ + * dslite_defs.h - DSLITE structure definiitions + * + * Copyright (c) 2011-2012 Cisco and/or its affiliates. + * 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 __DSLITE_DEFS_H__ +#define __DSLITE_DEFS_H__ + +#ifdef TOBE_PORTED +#include "spp_platform_common.h" +#include "cgse_defs.h" +#endif +#include "cnat_cli.h" +#include "cnat_config.h" +#include "cnat_ports.h" +#include "cnat_bulk_port_defs.h" + +extern u32 ds_lite_config_debug_level; + +#define SWAP_IPV6_ADDR(ipv6_hdr, dslite_entry_ptr) \ + ipv6_hdr->dst_addr[0] = ipv6_hdr->src_addr[0]; \ + ipv6_hdr->dst_addr[1] = ipv6_hdr->src_addr[1]; \ + ipv6_hdr->dst_addr[2] = ipv6_hdr->src_addr[2]; \ + ipv6_hdr->dst_addr[3] = ipv6_hdr->src_addr[3]; \ + ipv6_hdr->src_addr[0] = spp_host_to_net_byte_order_32(dslite_entry_ptr->AFTR_v6_address[0]); \ + ipv6_hdr->src_addr[1] = spp_host_to_net_byte_order_32(dslite_entry_ptr->AFTR_v6_address[1]); \ + ipv6_hdr->src_addr[2] = spp_host_to_net_byte_order_32(dslite_entry_ptr->AFTR_v6_address[2]); \ + ipv6_hdr->src_addr[3] = spp_host_to_net_byte_order_32(dslite_entry_ptr->AFTR_v6_address[3]); + +#define DSLITE_SET_TX_PKT_TYPE(type) { \ + ctx->ru.tx.packet_type = type; \ +} + +#define DSLITE_INC_STATS_V4(PTR, COUNTER, IPV4_SRC_ADDR) { \ + PTR->COUNTER++; \ +} + +#define DSLITE_INC_STATS_V6(PTR, COUNTER, IPV6_DEST_ADDR) { \ + PTR->COUNTER++; \ +} + + +#define DSLITE_INVALID_UIDX 0xffff /*invalid svi app uidb index */ +#define DSLITE_INVALID_VRFID 0xffffffff /*invalid vrf id */ + +#define DSLITE_VRF_MASK 0x3fff +#define DSLITE_MAX_VRFMAP_ENTRIES (DSLITE_VRF_MASK + 1) + +#define DSLITE_VRFMAP_ENTRY_INVALID 0xffff + +#define DSLITE_V6_PREFIX_MASK_MIN 16 +#define DSLITE_V6_PREFIX_MASK_MAX 96 +#define DSLITE_V6_PREFIX_MASK_MULTIPLE 8 + +#define DSLITE_TUNNEL_MTU_MIN 1280 +#define DSLITE_TUNNEL_MTU_MAX 9216 + +#define DSLITE_TUNNEL_TTL_MIN 0 +#define DSLITE_TUNNEL_TTL_MAX 255 + +#define DSLITE_TUNNEL_TOS_MIN 0 +#define DSLITE_TUNNEL_TOS_MAX 255 + +#define DSLITE_V4_MASK_MAX 32 + +//#define XLAT_MAX_FRAG_ID_COUNTERS (256) +#define DSLITE_AFTR_IPV4_ADDR 0xC0000001 + +#define DSLITE_MAX_TAP_RG_ENTRIES 2 +#define DSLITE_MAX_DSLITE_ENTRIES (256) +#define DSLITE_MAX_DSLITE_ID (DSLITE_MAX_DSLITE_ENTRIES-1) +/* Define the below value as 64 if first 64 entries are for NAT44 */ +#define DSLITE_INDEX_OFFSET 1 + +#define DSLITE_INVALID_DSLITE_ID (0) + +#define DSLITE_TABLE_ENTRY_DELETED 0 +#define DSLITE_TABLE_ENTRY_ACTIVE 1 +#define DSLITE_TABLE_ENTRY_DORMANT 2 +#define DSLITE_TABLE_ENTRY_INVALID_UIDB 3 + +typedef struct { + u16 tcp_initial_setup_timeout; + u16 tcp_active_timeout; + u16 udp_init_session_timeout; + u16 udp_act_session_timeout; + u16 icmp_session_timeout; + u16 temp; +} dslite_timeout_info_t; + + +typedef struct { + + u16 state; /* To use nat44 enums ?? TBD */ + u16 dslite_id; /* DSLITE_ID value for this table entry - for easy access */ + + u16 i_vrf; /* V6 uidb index */ + u16 o_vrf; /* V4 uidb index */ + + u16 cnat_main_db_max_ports_per_user; /* port limit */ + u16 tcp_mss; /*tcp max segment size for this inside vrf */ + + u32 delete_time; + + cnat_portmap_v2_t *portmap_list; + + u32 nfv9_logging_index; + u32 syslog_logging_index; + u32 AFTR_v6_address[4]; + +#define DSLITE_IPV4_TOS_OVERRIDE_FLAG 0x00000001 +#define DSLITE_IPV6_TOS_OVERRIDE_FLAG 0x00000002 +#define DSLITE_IPV4_TTL_OVERRIDE_FLAG 0x00000004 +#define DSLITE_IPV6_TTL_OVERRIDE_FLAG 0x00000008 +#define DSLITE_IPV6_FRAG_REASSEMB_ENG 0x00000010 +#define DSLITE_FTP_ALG_ENABLE 0x00000020 +#define DSLITE_RTSP_ALG_ENABLE 0x00000040 +#define DSLITE_NETFLOW_ENABLE 0x00000080 +#define DSLITE_SYSLOG_ENABLE 0x00000100 + + u16 feature_flags; + u16 tunnel_mtu; + + u8 ipv4_ttl_value; + u8 ipv6_ttl_value; + u8 ipv4_tos_value; + u8 ipv6_tos_value; + + u32 v4_if_num; /* V4 SVI ifnum */ + u32 v6_if_num; /* V6 SVI ifnum */ + u32 i_vrf_id; //inside vrf id + u32 o_vrf_id; //outside vrf id + + dslite_timeout_info_t timeout_info; + u16 cnat_static_port_range; + u16 dyn_start_port; + + u32 AFTR_v4_addr; + bulk_alloc_size_t bulk_size; /* should be equivalent to u16 - 2 bytes */ + u32 pcp_server_addr; + u16 pcp_server_port; + u8 mapping_refresh_both_direction; + u8 pad; + u16 rtsp_port; +#define DSLITE_BIDIR_REFRESH 1 + u8 dslite_enable; /* DS-Lite enable check flag */ + u8 syslog_logging_policy; /* DS-Lite Session Logging check flag */ + u8 nf_logging_policy; + + u8 temp1; + u16 temp2; + u32 temp3; + u32 rseed_ip; +} dslite_table_entry_t; + +typedef struct { + u64 v4_to_v6_invalid_uidb_drop_count; + u64 v6_to_v4_invalid_uidb_drop_count; + u64 v4_to_v6_frag_invalid_uidb_drop_count; +} dslite_global_counters_t; + +typedef struct { + u32 tap_enable; + u32 ipv4_addr; + u32 ipv6_addr[4]; +} dslite_tap_rg_t; + +extern dslite_table_entry_t *dslite_table_db_ptr; + + +#define DSLITE_ADD_UIDB_INDEX_DSLITE_ID_MAPPING(uidb_index, dslite_id) \ + *(cgse_uidb_index_cgse_id_mapping_ptr + uidb_index) = dslite_id; + +extern u8 my_instance_number; + +extern void dslite_clear_counters(u16 dslite_id); +extern void dslite_clear_per_RG_counters(); +extern dslite_global_counters_t dslite_global_counters; +extern u32 dslite_config_debug_level; +extern u32 dslite_data_path_debug_level; +extern u32 dslite_defrag_debug_level; +extern u32 dslite_debug_level; + +typedef struct { + u64 v6_to_v4_tcp_input_count; + u64 v6_to_v4_tcp_nat_error; + u64 v6_to_v4_tcp_output_count; +} dslite_v6_to_v4_tcp_counter_t; + +typedef struct { + u64 v4_to_v6_tcp_input_count; + u64 v4_to_v6_tcp_no_entry; + u64 v4_to_v6_tcp_output_count; +} dslite_v4_to_v6_tcp_counter_t; + +typedef struct { + u64 v6_to_v4_udp_input_count; + u64 v6_to_v4_udp_nat_error; + u64 v6_to_v4_udp_output_count; +} dslite_v6_to_v4_udp_counter_t; + +typedef struct { + u64 v4_to_v6_udp_input_count; + u64 v4_to_v6_udp_no_entry; + u64 v4_to_v6_udp_output_count; +} dslite_v4_to_v6_udp_counter_t; + +typedef struct { + u64 v6_to_v4_icmp_qry_input_count; + u64 v6_to_v4_icmp_qry_nat_error; + u64 v6_to_v4_icmp_qry_output_count; +} dslite_v6_to_v4_icmp_qry_counter_t; + +typedef struct { + u64 v4_to_v6_icmp_qry_input_count; + u64 v4_to_v6_icmp_qry_no_nat_entry; + u64 v4_to_v6_icmp_qry_output_count; +} dslite_v4_to_v6_icmp_qry_counter_t; + +typedef struct { + u64 v6_to_v4_icmp_error_input_count; + u64 v6_to_v4_icmp_error_nat_error; + u64 v6_to_v4_icmp_error_output_count; +} dslite_v6_to_v4_icmp_error_counter_t; + +typedef struct { + u64 v4_to_v6_icmp_error_input_count; + u64 v4_to_v6_icmp_error_no_nat_entry; + u64 v4_to_v6_icmp_error_output_count; +} dslite_v4_to_v6_icmp_error_counter_t; + +typedef struct { + u64 v6_icmp_error_input_count; + u64 v6_AFTR_echo_reply_count; + u64 v6_to_v4_icmp_error_unsupported_type_drop_count; + u64 v6_to_v4_icmp_error_no_db_entry_count; + u64 v6_to_v4_icmp_err_throttled_count; + u64 v6_to_v4_icmp_error_xlated_count; +} dslite_v6_icmp_error_counter_t; + +typedef struct { + u64 v4_to_v6_ttl_gen_count; + u64 v4_to_v6_icmp_throttle_count; + u64 v4_to_v6_ptb_gen_count; + u64 v4_to_v6_aftr_v4_echo_reply_count; + u64 v6_to_v4_ttl_gen_count; + u64 v6_to_v4_icmp_throttle_count; + u64 v6_to_v4_admin_prohib_icmp_count; + u64 v6_to_v4_aftr_v4_echo_reply_count; + u64 v6_icmp_gen_count; +} dslite_icmp_gen_counter_t; + +typedef struct { + u64 dslite_input_tunnel_pkt; + u64 dslite_encap_count; + u64 dslite_decap_count; + u64 dslite_sec_check_failed; + u64 dslite_unsupp_packet; +} dslite_common_counter_t; + +typedef struct { + + dslite_v6_to_v4_tcp_counter_t v64_tcp_counters; + dslite_v4_to_v6_tcp_counter_t v46_tcp_counters; + dslite_v6_to_v4_udp_counter_t v64_udp_counters; + dslite_v4_to_v6_udp_counter_t v46_udp_counters; + dslite_v6_to_v4_icmp_qry_counter_t v64_icmp_counters; + dslite_v4_to_v6_icmp_qry_counter_t v46_icmp_counters; + dslite_v6_to_v4_icmp_error_counter_t v64_icmp_error_counters; + dslite_v4_to_v6_icmp_error_counter_t v46_icmp_error_counters; + dslite_v6_icmp_error_counter_t dslite_v6_icmp_err_counters; + dslite_icmp_gen_counter_t dslite_icmp_gen_counters; + dslite_common_counter_t dslite_common_counters; +} dslite_counters_t; + +typedef struct { + u32 active_translations; + u32 translation_create_rate; + u32 translation_delete_rate; + u32 in2out_forwarding_rate; + u32 out2in_forwarding_rate; + u32 in2out_drops_port_limit_exceeded; + u32 in2out_drops_system_limit_reached; + u32 in2out_drops_resource_depletion; + u32 no_translation_entry_drops; + u32 pool_address_totally_free; + u32 num_subscribers; + u32 dummy; + u64 drops_sessiondb_limit_exceeded; +} dslite_common_stats_t; + +typedef struct { + u16 msg_id; + u8 rc; + u8 pad[5]; + dslite_counters_t counters; +} dslite_show_statistics_summary_resp; + + +#define CMD_GENERATE_PTB 0x1 +#define CMD_GENERATE_TTL 0x2 + +/* + * This structure is to provide abstraction for data exchanged from one + * VPP node to its disposition or further in the dslite node graph. + */ +typedef struct { + u32 icmp_gen_type; // ctx->feature_data[0] + u32 reserved1; // ctx->feature_data[1] + u32 reserved2; // ctx->feature_data[2] + u32 reserved3; // ctx->feature_data[3] +} dslite_feature_data_t; + +extern dslite_counters_t dslite_all_counters[DSLITE_MAX_DSLITE_ENTRIES]; +//extern dslite_inst_gen_counter_t dslite_inst_gen_counters[DSLITE_MAX_DSLITE_ENTRIES]; + + + extern void dslite_show_config(void); +#define STAT_PORT_RANGE_FROM_INST_PTR(inst) ((inst)->cnat_static_port_range) + +#endif /* __DSLITE_DEFS_H__ */ + diff --git a/plugins/vcgn-plugin/vcgn/index_list.c b/plugins/vcgn-plugin/vcgn/index_list.c new file mode 100644 index 00000000..ec1b83b0 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/index_list.c @@ -0,0 +1,336 @@ +/* + *------------------------------------------------------------------ + * index_list.c - vector-index-based lists. 64-bit pointers suck. + * + * Copyright (c) 2008-2009, 2011 Cisco and/or its affiliates. + * 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 +#include +//#include +#include +#include "index_list.h" + +/* + * index_slist_addhead + * + * args: headp -- pointer to e.g. a hash bucket + * vector -- vector containing the list + * elsize -- size of an element in this vector + * offset -- offset in each vector element of this list thread + * index_to_add -- index in the vector to add to the list + * + * Adds new items to the head of the list. Try not to screw up the args! + */ +void index_slist_addhead (index_slist_t *headp, + u8 *vector, u32 elsize, u32 offset, u32 index_to_add) +{ + return (index_slist_addhead_inline(headp, vector, elsize, offset, + index_to_add)); +} + +/* + * index_slist_remelem + * + * args: headp -- pointer to e.g. a hash bucket + * vector -- vector containing the list + * elsize -- size of an element in this vector + * offset -- offset in each vector element of this list thread + * index_to_del -- index in the vector to delete from the list + * + * Try not to screw up the args! + */ + +int index_slist_remelem (index_slist_t *headp, + u8 *vector, u32 elsize, u32 offset, + u32 index_to_delete) +{ + return (index_slist_remelem_inline(headp, vector, elsize, offset, + index_to_delete)); +} + + +/* + * index_dlist_addtail + * + * Append the indicated vector element to the doubly-linked list + * whose first element is pointed to by headp. + * + * args: head_index -- listhead vector element index. + * vector -- vector containing the list + * elsize -- size of an element in this vector + * offset -- offset in each vector element of this list thread + * index_to_add -- index in the vector to add to the list + * + * Do not call this routine to create the listhead. Simply set + * index_dlist->next = index_dlist->prev = index of item. + * + * Try not to screw up the args. + */ + +void index_dlist_addtail (u32 head_index, u8 *vector, u32 elsize, + u32 offset, u32 index_to_add) +{ + index_dlist_t *elp; + index_dlist_t *elp_next; + index_dlist_t *headp; + + headp = (index_dlist_t *)(vector + offset + elsize*head_index); + elp = (index_dlist_t *)(vector + offset + elsize*index_to_add); + elp->next = index_to_add; + elp->prev = index_to_add; + + elp->next = headp->next; + headp->next = index_to_add; + + elp_next = (index_dlist_t *)(vector + offset + elsize*elp->next); + elp->prev = elp_next->prev; + elp_next->prev = index_to_add; +} + +u32 index_dlist_remelem (u32 head_index, + u8 *vector, u32 elsize, u32 offset, + u32 index_to_delete) +{ + u32 rv = head_index; + index_dlist_t *headp, *elp, *elp_next; + + elp = (index_dlist_t *)(vector + offset + elsize*index_to_delete); + + /* Deleting the head index? */ + if (PREDICT_FALSE(head_index == index_to_delete)) { + rv = elp->next; + /* The only element on the list? */ + if (PREDICT_FALSE(rv == head_index)) + rv = EMPTY; + } + + headp = (index_dlist_t *)(vector + offset + elsize*elp->prev); + headp->next = elp->next; + elp_next = (index_dlist_t *)(vector + offset + elsize*elp->next); + elp_next->prev = elp->prev; + + elp->next = elp->prev = EMPTY; + + return rv; +} + + +#ifdef TEST_CODE2 + +typedef struct tv_ { + char junk[43]; + index_dlist_t l; +} tv_t; + + +void index_list_test_cmd(int argc, unsigned long *argv) +{ + int i, j; + u32 head_index; + index_dlist_t *headp; + tv_t *tp=0; + + vec_validate(tp, 3); + head_index = 3; + + memset(tp, 0xa, sizeof(tp[0])*vec_len(tp)); + + /* Here's how to set up the head element... */ + headp = &((tp + head_index)->l); + headp->next = headp->prev = head_index; + + for (i = 0; i < 3; i++) { + index_dlist_addtail(head_index, (u8 *)tp, sizeof(tp[0]), + STRUCT_OFFSET_OF(tv_t, l), i); + printf("headp next %d prev %d\n", + headp->next, headp->prev); + for (j = 0; j <= 3; j++) { + printf ("[%d]: next %d prev %d\n", j, + tp[j].l.next, tp[j].l.prev); + } + printf("---------------\n"); + + } + + printf("After all adds:\n"); + + printf("headp next %d prev %d\n", + headp->next, headp->prev); + + for (j = 0; j <= 3; j++) { + printf ("[%d]: next %d prev %d\n", j, + tp[j].l.next, tp[j].l.prev); + } + printf("---------------\n"); + + head_index = index_dlist_remelem (head_index, (u8 *)tp, sizeof(tp[0]), + STRUCT_OFFSET_OF(tv_t, l), 1); + + printf("after delete 1, head index %d\n", head_index); + headp = &((tp + head_index)->l); + printf("headp next %d prev %d\n", + headp->next, headp->prev); + for (j = 0; j <= 3; j++) { + printf ("[%d]: next %d prev %d\n", j, + tp[j].l.next, tp[j].l.prev); + } + printf("---------------\n"); + + index_dlist_addtail(head_index, (u8 *)tp, sizeof(tp[0]), + STRUCT_OFFSET_OF(tv_t, l), 1); + + printf("after re-add 1, head index %d\n", head_index); + headp = &((tp + head_index)->l); + printf("headp next %d prev %d\n", + headp->next, headp->prev); + for (j = 0; j <= 3; j++) { + printf ("[%d]: next %d prev %d\n", j, + tp[j].l.next, tp[j].l.prev); + } + printf("---------------\n"); + + for (i = 3; i >= 0; i--) { + head_index = index_dlist_remelem (head_index, (u8 *)tp, sizeof(tp[0]), + STRUCT_OFFSET_OF(tv_t, l), i); + printf("after delete, head index %d\n", head_index); + if (head_index != EMPTY) { + headp = &((tp + head_index)->l); + printf("headp next %d prev %d\n", + headp->next, headp->prev); + for (j = 0; j <= 3; j++) { + printf ("[%d]: next %d prev %d\n", j, + tp[j].l.next, tp[j].l.prev); + } + } else { + printf("empty list\n"); + } + printf("---------------\n"); + } +} +#endif /* test code 2 */ + +#ifdef TEST_CODE + +typedef struct tv_ { + char junk[43]; + index_slist_t l; +} tv_t; + + +void index_list_test_cmd(int argc, unsigned long *argv) +{ + int i, j; + tv_t *tp = 0; + index_slist_t *buckets = 0; + + vec_add1((u32 *)buckets, EMPTY); + vec_validate(tp, 9); + + for (i = 0; i < 10; i++) { + index_slist_addhead(buckets, (u8 *)tp, sizeof(*tp), + STRUCT_OFFSET_OF(tv_t, l), i); + } + + printf ("after adds, buckets[0] = %u\n", buckets[0]); + + for (j = 0; j < 10; j++) { + printf("tp[%d] next %u\n", j, tp[j].l); + + } + + for (i = 0; i < 10; i++) { + if (PREDICT_FALSE(index_slist_remelem(buckets, (u8 *) tp, sizeof(*tp), + STRUCT_OFFSET_OF(tv_t, l), i))) { + printf("OUCH: remelem failure at index %d\n", i); + } + if (PREDICT_FALSE(tp[i].l.next != EMPTY)) { + printf("OUCH: post-remelem next not EMPTY, index %d\n", i); + } + } + + printf ("after deletes, buckets[0] = %x\n", buckets[0]); + + for (i = 0; i < 10; i++) { + index_slist_addhead(buckets, (u8 *)tp, sizeof(*tp), + STRUCT_OFFSET_OF(tv_t, l), i); + } + + printf ("after adds, buckets[0] = %u\n", buckets[0]); + + for (j = 0; j < 10; j++) { + printf("tp[%d] next %u\n", j, tp[j].l); + + } + + for (i = 9; i >= 0; i--) { + if (PREDICT_FALSE(index_slist_remelem(buckets, (u8 *) tp, sizeof(*tp), + STRUCT_OFFSET_OF(tv_t, l), i))) { + printf("OUCH: remelem failure at index %d\n", i); + } + if ((tp[i].l.next != EMPTY)) { + printf("OUCH: post-remelem next not EMPTY, index %d\n", i); + } + } + + printf ("after deletes, buckets[0] = %x\n", buckets[0]); + + printf("add evens, then odds...\n"); + + for (i = 0; i < 10; i += 2) { + index_slist_addhead(buckets, (u8 *)tp, sizeof(*tp), + STRUCT_OFFSET_OF(tv_t, l), i); + + printf ("head = buckets[0].next = %d\n", buckets[0].next); + for (j = 0; j < 10; j++) { + printf("tp[%d] next %u\n", j, tp[j].l); + } + printf("-------------\n"); + } + + for (i = 1; i < 10; i += 2) { + index_slist_addhead(buckets, (u8 *)tp, sizeof(*tp), + STRUCT_OFFSET_OF(tv_t, l), i); + + printf ("head = buckets[0].next = %d\n", buckets[0].next); + for (j = 0; j < 10; j++) { + printf("tp[%d] next %u\n", j, tp[j].l); + } + printf("-------------\n"); + } + + printf ("after adds, buckets[0] = %u\n", buckets[0]); + + for (j = 0; j < 10; j++) { + printf("tp[%d] next %u\n", j, tp[j].l); + + } + + for (i = 9; i >= 0; i--) { + if (PREDICT_FALSE(index_slist_remelem(buckets, (u8 *) tp, sizeof(*tp), + STRUCT_OFFSET_OF(tv_t, l), i))) { + printf("OUCH: remelem failure at index %d\n", i); + } + if (PREDICT_FALSE(tp[i].l.next != EMPTY)) { + printf("OUCH: post-remelem next not EMPTY, index %d\n", i); + } + } + + printf ("after deletes, buckets[0] = %x\n", buckets[0]); + + vec_free(buckets); + vec_free(tp); +} +#endif /* test code */ diff --git a/plugins/vcgn-plugin/vcgn/index_list.h b/plugins/vcgn-plugin/vcgn/index_list.h new file mode 100644 index 00000000..498cd7eb --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/index_list.h @@ -0,0 +1,118 @@ +/* + *------------------------------------------------------------------ + * index_list.h - vector-index-based doubly-linked lists + * + * Copyright (c) 2008-2009 Cisco and/or its affiliates. + * 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 _INDEX_LIST_H_ +#define _INDEX_LIST_H_ 1 + +/* An index we can't possibly see in practice... */ +#define EMPTY ((u32)~0) + +typedef struct index_slist_ { + u32 next; +} index_slist_t; + +/* + * index_slist_addhead + * + * args: headp -- pointer to e.g. a hash bucket + * vector -- vector containing the list + * elsize -- size of an element in this vector + * offset -- offset in each vector element of this list thread + * index_to_add -- index in the vector to add to the list + * + * Adds new items to the head of the list. Try not to screw up the args! + */ +static inline void + index_slist_addhead_inline (index_slist_t *headp, + u8 *vector, u32 elsize, + u32 offset, u32 index_to_add) +{ + index_slist_t *addme; + + addme = (index_slist_t *)(vector + offset + elsize*index_to_add); + addme->next = EMPTY; + + if (headp->next == EMPTY) { + headp->next = index_to_add; + return; + } else { + addme->next = headp->next; + headp->next = index_to_add; + } +} + +/* + * index_slist_remelem + * + * args: headp -- pointer to e.g. a hash bucket + * vector -- vector containing the list + * elsize -- size of an element in this vector + * offset -- offset in each vector element of this list thread + * index_to_del -- index in the vector to delete from the list + * + * Try not to screw up the args! + */ + +static inline int + index_slist_remelem_inline (index_slist_t *headp, + u8 *vector, u32 elsize, + u32 offset, u32 index_to_delete) +{ + index_slist_t *findme; + index_slist_t *prev; + index_slist_t *cur; + + findme = (index_slist_t *)(vector + offset + elsize*index_to_delete); + + if (headp->next == index_to_delete) { + headp->next = findme->next; + findme->next = EMPTY; + return 0; + } + + prev = (index_slist_t *)(vector + offset + elsize*headp->next); + cur = (index_slist_t *)(vector + offset + elsize*prev->next); + while (cur != findme) { + if (cur->next == EMPTY) + return (1); + prev = cur; + cur = (index_slist_t *)(vector + offset + elsize*cur->next); + } + prev->next = findme->next; + findme->next = EMPTY; + return 0; +} + +void index_slist_addhead (index_slist_t *headp, + u8 *vector, u32 elsize, u32 offset, u32 index); +int index_slist_remelem (index_slist_t *headp, + u8 *vector, u32 elsize, u32 offset, u32 index); + +typedef struct index_dlist_ { + u32 next; + u32 prev; +} index_dlist_t; + +void index_dlist_addtail (u32 head_index, u8 *vector, u32 elsize, + u32 offset, u32 index_to_add); + +u32 index_dlist_remelem (u32 head_index, + u8 *vector, u32 elsize, u32 offset, + u32 index_to_delete); +#endif /* _INDEX_LIST_H_ */ diff --git a/plugins/vcgn-plugin/vcgn/nat64_db.h b/plugins/vcgn-plugin/vcgn/nat64_db.h new file mode 100644 index 00000000..837464f6 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/nat64_db.h @@ -0,0 +1,480 @@ +/* + *------------------------------------------------------------------ + * nat64_db.h - Stateful NAT64 translation database definitions + * + * Copyright (c) 2010-2013 Cisco and/or its affiliates. + * 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 __NAT64_DB_H__ +#define __NAT64_DB_H__ + +#include "cnat_cli.h" +#include "index_list.h" +#include "cnat_ports.h" +#include "cnat_db.h" +#include "nat64_defs.h" +#include "cnat_bulk_port_defs.h" + +nat64_vrfmap_t *nat64_map_by_vrf; + +#define SESSION_OPT + +#define HASH_ENHANCE 4 + + +#define NAT64_MAIN_DB_SIZE \ + (PLATFORM_NAT64_MAX_SESSIONS / PLATFORM_CNAT_INSTS) +#define NAT64_MAIN_HASH_SIZE \ + (HASH_ENHANCE * PLATFORM_CNAT_MAIN_PRELIM_HASH_SIZE) + +#define NAT64_MAIN_HASH_MASK (NAT64_MAIN_HASH_SIZE-1) + + +/* nb: 200000 users / 64 CNAT = 3125, 76% occupancy */ +#define NAT64_USER_HASH_SIZE CNAT_USER_HASH_SIZE +#define NAT64_USER_HASH_MASK (NAT64_USER_HASH_SIZE-1) + +/* Number of sessions per BIB entry/NAT64 translation + - nsessions is u16 type. So selected 0xFFFF + - Ideally Sessions per transltion will not reach the limit + - Only DoS can possible. It can take care of it */ +#define NAT64_MAX_SESSIONS_PER_BIB 0xFFFF + +/* No. of per ip/port config will be limited to 1000 */ +/* totally 25K across all instances) */ +#define NAT64_TIMEOUT_HASH_SIZE \ + PLATFORM_NAT64_TIMEOUT_HASH_SIZE + +#define NAT64_TIMEOUT_HASH_MASK (NAT64_TIMEOUT_HASH_SIZE - 1) +#define NAT64_TIMEOUT_FULL_MASK 0xFFFFFFFFFFFFFFFF + + +#define FORCE_DEL 1 /* Delete static BIB entries as well */ + +/* default timeout values */ +#define NAT64_UDP_DEFAULT 300 /* 5 min */ +#define NAT64_UDP_MIN 120 /* 2 min */ +#define NAT64_TCP_TRANS 240 /* 4 min */ +#define NAT64_TCP_EST 7200 /* 2 hrs */ +#define NAT64_TCP_V4_SYN 6 /* 6 sec */ +#define NAT64_FRAG_MIN 2 /* 2 sec */ +#define NAT64_ICMP_DEFAULT 60 /* 1 min */ + + +#define NAT64_V6_GET_HASH(in_key, hash, mask) \ + a = in_key->ipv6[0] ^ in_key->ipv6[1] ^ in_key->ipv6[2] ^ in_key->ipv6[3] \ + ^ ((in_key->port << 16) | in_key->vrf); \ + b = c = 0x9e3779b9;\ + /* Jenkins hash, arbitrarily use c as the "answer" */ \ + hash_mix32(a, b, c); \ + hash = c & mask; \ + + +#define NAT64_V4_GET_HASH(in_key, hash, mask) \ + a = in_key.ipv4 ^ ((in_key.port << 16) | in_key.vrf); \ + b = c = 0x9e3779b9; \ + /* Jenkins hash, arbitrarily use c as the "answer" */ \ + hash_mix32(a, b, c); \ + hash = c & mask; + + + +#define NAT64_V6_GET_SESSION_HASH(bib_index, in_addr, port, vrf, hash, mask) \ + a = bib_index ^ in_addr[0] ^ in_addr[1] ^ in_addr[2] ^ in_addr[3] \ + ^ port ^ vrf; \ + b = c = 0x9e3779b9; \ + /* Jenkins hash, arbitrarily use c as the "answer" */ \ + hash_mix32(a, b, c); \ + hash = c & mask; + +#define NAT64_V4_GET_SESSION_HASH(bib_index, in_addr, port, vrf, hash, mask) \ + a = bib_index ^ in_addr ^ port ^ vrf; \ + b = c = 0x9e3779b9; \ + /* Jenkins hash, arbitrarily use c as the "answer" */ \ + hash_mix32(a, b, c); \ + hash = c & mask; + + +extern index_slist_t *nat64_bib_out2in_hash; +extern index_slist_t *nat64_bib_in2out_hash; +extern index_slist_t *nat64_bib_user_hash; +extern index_slist_t *nat64_session_out2in_hash; +#ifndef SESSION_OPT +extern index_slist_t *nat64_session_in2out_hash; +#endif +extern index_slist_t *nat64_frag_out2in_hash; +extern index_slist_t *nat64_frag_in2out_hash; +extern index_slist_t *nat64_timeout_hash; + + +/* + * nat64_ bib_entry_t + * This structure depicts Binding Information Base of NAT64 sessions. + * It stores information about the inside v6 source transport address and + * corresponding outside v4 source transport address for each protocol. + */ + +typedef struct { + + index_slist_t nat64_bib_out2in_hash; + index_slist_t nat64_bib_in2out_hash; + + /* 0x08 */ + u16 flags; /* flags in cnat_db.h (cnat_main_db_entry_t) */ +#define NAT64_DB_FLAG_STATIC_PORT CNAT_DB_FLAG_STATIC_PORT +#define NAT64_DB_NAT64_FLAG CNAT_DB_NAT64_FLAG +#define NAT64_DB_FLAG_ALG_ENTRY CNAT_DB_FLAG_ALG_ENTRY +#define NAT64_DB_FLAG_PCPI CNAT_DB_FLAG_PCPI +#define NAT64_DB_FLAG_PCPE CNAT_DB_FLAG_PCPE + + /* 0x0A */ + u16 nat64_inst_id; + /* 0x0C */ + u32 user_index; + + /* 0x10 */ + nat64_v4_key_t v4_out_key; + + /* 0x18 */ + nat64_v6_key_t v6_in_key; + + /* 0x2C */ + index_dlist_t user_ports; + /* 0x34 */ + u32 session_head_index; + /* 0x38 - 56B*/ + u16 nsessions; + u16 pad2; + + /* 0x3C - 60B */ + u32 in2outpkts; + u32 out2inpkts; + /* 0x44 - 68B */ + + /* 0x42 - 70B */ + union { /* used by FTP ALG, pkt len delta due to FTP PORT cmd */ + u16 delta; + i8 alg_dlt[2]; /* two delta values, 0 for previous, 1 for current */ + u16 il; /* Used to indicate if interleaved mode is used + in case of RTSP ALG */ + } alg; + + u16 temp1; + + u32 entry_expires; + + u32 temp3; + /* unused, temp1 ,temp2 and temp3 put to make it in sync with nat44 main db entry size */ + /* size of = 0x54 = 84 B */ + u32 unused; + +} nat64_bib_entry_t ; + +/* + * nat64_bib_user_entry_t + * This structure stores information about translations of a particular user + * (User here refers to a same inside source address) + */ +typedef struct { + /* 0x00 */ + index_slist_t user_hash; + /* 0x04 */ + u16 ntranslations; + /* 0x06 */ + u8 icmp_msg_count; + /* 0x07 */ + u8 flags; +#define NAT64_USER_DB_NAT64_FLAG CNAT_USER_DB_NAT64_FLAG + + /* 0x08 */ + u32 translation_list_head_index; + /* 0x0C */ + u32 portmap_index; + /* 0x10 */ + nat64_v6_key_t v6_in_key; + /* 0x24 = 36 B */ + + u32 align1; /* Make it 8B boundary and in sync with nat44 user db entry size */ +#ifndef NO_BULK_LOGGING + /* size of = 0x28 = 40 B */ + /* Now adding 8 more bytes for bulk allocation.. This makes it + * 0x30 (48). For nat64 stful, we may support bulk allocation + * later */ + /* Indicates the currently used bulk port range */ + i16 bulk_port_range_cache[BULK_RANGE_CACHE_SIZE]; +#endif /* NO_BULK_LOGGING */ +} nat64_bib_user_entry_t; + +/* + * nat64_session_entry_t + * This structure represents the session table. It maintains the information + * about the flow of the packets. It would consist of source and destination + * (inside and outside) ipv4 and ipv4 transport addresses. + */ +typedef struct { + + /* 0x00 */ + index_slist_t nat64_session_out2in_hash; + + /* 0x04 */ + u32 bib_index; /* would point to v4/v6 src transport address */ + + /* 0x08 */ + nat64_v4_key_t v4_dest_key; + +#ifndef SESSION_OPT + index_slist_t nat64_session_in2out_hash; + nat64_v6_key_t v6_dest_key; +#endif + + /* 0x10 */ + u16 flags;/* Will be used for flags same as nat44 session */ + + /* 0x12 */ + u16 timeout; + + /* 0x14 */ + u32 entry_expires; + /* 0x18 */ + index_dlist_t bib_list; + /* 0x20 = 32 B */ + + union { /* alg same as cnat_main_db_t */ + u16 delta; + i8 alg_dlt[2]; + u16 il; + } alg; + + /* 0x22 */ + u16 tcp_flags; /* Mainly TCP events - check nat64_tcp_sm.h */ + + /* 0x24 */ + u32 tcp_seq_num; + + /* 0x28 */ /* unused1, unused2 and unused3 are put to make it in sync with + * cnat_session_db */ + u32 unused1; + + /* 0x2C */ + u32 unused2; + + /* 0x30 */ + u16 unused3; + + /* 0x32 - 50B */ + +} nat64_session_entry_t; + +/* + * nat64_session_tcp_init_entry_t + * This structure will be used to store information about v4 initiation + * tcp entries. + */ +typedef struct { + nat64_v6_key_t v6_in_key; + nat64_v4_key_t v4_out_key; +} nat64_session_tcp_init_entry_t; + +/* + * nat64_in_v6_frag_entry_t + * This structure will be used to store information about fragment flows + * that are coming from inside v6 hosts. + */ +typedef struct { + index_slist_t nat64_frag_in2out_hash; + + u32 v6_src_addr[4]; + u32 v6_destn_addr[4]; + u32 frag_iden; + u16 vrf; + u16 pad1; +} nat64_in_v6_frag_entry_t ; + +/* + * nat64_out_v4_frag_entry_t + * This structure will be used to store information about fragment flows + * that are coming from outside v4 machines. + */ +typedef struct { + index_slist_t nat64_frag_out2in_hash; + + u32 v4_src_addr; + u32 v4_destn_addr; + u16 frag_iden; + u16 vrf; +} nat64_out_v4_frag_entry_t ; + +/* + * nat64_timeout _t + * These following structures will be used to store information destination + * timeouts configured. + */ +typedef struct { + nat64_v4_key_t timeout_key; + u16 timeout_value; +} nat64_timeout_t; + +/* + * nat64_timeout_db_entry_t + */ +typedef struct { + nat64_timeout_t t_key; + index_slist_t t_hash; +} nat64_timeout_db_entry_t; + + +typedef union { + cnat_main_db_entry_t nat44_main_db; + nat64_bib_entry_t nat64_bib_db; +} cgse_nat_db_entry_t; + +typedef union { + cnat_session_entry_t nat44_session_db; + nat64_session_entry_t nat64_session_db; +} cgse_nat_session_db_entry_t; + +typedef union { + cnat_user_db_entry_t nat44_user_db; + nat64_bib_user_entry_t nat64_user_db; +} cgse_nat_user_db_entry_t; + +extern index_slist_t *nat64_bib_out2in_hash; +extern index_slist_t *nat64_bib_in2out_hash; +extern index_slist_t *nat64_bib_user_hash; +extern index_slist_t *nat64_session_out2in_hash; +extern index_slist_t *nat64_session_in2out_hash; +extern index_slist_t *nat64_frag_out2in_hash; +extern index_slist_t *nat64_frag_in2out_hash; +extern index_slist_t *nat64_timeout_hash; + +extern nat64_bib_entry_t *nat64_bib_db; +extern nat64_bib_user_entry_t *nat64_bib_user_db; +extern nat64_session_entry_t *nat64_session_db; +extern nat64_in_v6_frag_entry_t *nat64_in_frag_db; +extern nat64_out_v4_frag_entry_t *nat64_out_frag_db; +extern nat64_session_tcp_init_entry_t *nat64_tcp_init_db ; +extern nat64_timeout_db_entry_t *nat64_timeout_db; + +extern nat64_table_entry_t nat64_table_array[NAT64_MAX_NAT64_ENTRIES]; +extern nat64_table_entry_t *nat64_table_ptr; + +extern cgse_nat_db_entry_t *cgse_nat_db; +extern cgse_nat_user_db_entry_t *cgse_user_db; +extern cgse_nat_session_db_entry_t *cgse_session_db; + +void nat64_bib_user_db_delete (nat64_bib_user_entry_t *up); + +nat64_bib_user_entry_t* +nat64_bib_user_db_create_entry(nat64_v6_key_t *uki, u32 bucket, + u32 portmap_index); + +nat64_bib_user_entry_t* +nat64_bib_user_db_lookup_entry(nat64_v6_key_t *uki, u32 *bucket); + + +nat64_bib_entry_t* +nat64_bib_db_lookup_entry(nat64_v6_key_t *ki); + +void nat64_bib_db_in2out_hash_delete (nat64_bib_entry_t *ep); + +void nat64_bib_db_out2in_hash_delete (nat64_bib_entry_t *ep); + +nat64_bib_entry_t * +nat64_create_bib_db_entry_and_hash(nat64_v6_key_t *ki, + nat64_v4_key_t *ko, + nat64_bib_user_entry_t *udb); + + +void nat64_delete_bib_db_entry (nat64_bib_entry_t *ep, u8 force); + +nat64_bib_entry_t * +nat64_bib_db_lookup_entry_out2in (nat64_v4_key_t *ko); + +nat64_bib_entry_t * +nat64_get_bib_db_entry (nat64_v6_key_t *ki, + port_pair_t port_pair_type, + port_type_t port_type, + cnat_gen_icmp_info *info); + + +nat64_bib_entry_t* +nat64_create_static_bib_db_entry (nat64_v6_key_t *ki, + nat64_v4_key_t *ko, + nat64_table_entry_t *my_table, + cnat_gen_icmp_info *info); + + + +//void nat64_session_db_in2out_hash_delete (nat64_session_entry_t *ep); +void nat64_session_db_out2in_hash_delete (nat64_session_entry_t *ep); + +/*nat64_session_entry_t * +nat64_session_db_lookup_entry(nat64_v6_key_t *ki, u32 bib_index); */ + + +nat64_session_entry_t * +nat64_session_db_lookup_entry_out2in (nat64_v4_key_t *ko,u32 bib_index); + +/* +nat64_session_entry_t * +nat64_create_session_db_entry(nat64_v6_key_t *ki, + nat64_v4_key_t *ko, + nat64_bib_entry_t *bdb); +*/ +nat64_session_entry_t * +nat64_create_session_db_entry_v2( nat64_v4_key_t *ko, + nat64_bib_entry_t *bdb); + + +//void nat64_delete_session_db_entry (nat64_session_entry_t *ep); +void nat64_delete_session_db_entry_v2 (nat64_session_entry_t *ep, u8 force); + +u32 nat64_timeout_db_hash_lookup (nat64_v4_key_t t_key); + +u16 query_and_update_db_timeout_nat64(nat64_session_entry_t *db); + +void nat64_timeout_db_hash_add (nat64_timeout_db_entry_t *t_entry); + +u16 nat64_timeout_db_create (nat64_timeout_t t_entry); + +void nat64_timeout_db_delete(nat64_v4_key_t t_key); + +#define NAT64_CMP_V6_KEY(key1, key2) \ + memcmp(key1, key2, sizeof(nat64_v6_key_t)) + +#define NAT64_CMP_V4_KEY(key1, key2) \ + memcmp(key1, key2, sizeof(nat64_v4_key_t)) + + +#define NAT64_CMP_V6_IP(ip1, ip2) \ + memcmp(ip1, ip2, (sizeof(u32) * 4)) + + +#define NAT64_CMP_V6_KEY1(key1, key2) \ + (key1.ipv6[0] == key2.ipv6[0]) && (key1.ipv6[1] == key2.ipv6[1]) && \ + (key1.ipv6[2] == key2.ipv6[2]) && (key1.ipv6[3] == key2.ipv6[3]) && \ + (key1.port == key2.port) && (key1.vrf == key2.vrf) + + +#define NAT64_CMP_V6_IP1(ip1, ip2) \ + ((ip1[0] == ip2[0]) && (ip1[1] == ip2[1]) && \ + (ip1[2] == ip2[2]) && (ip1[3] == ip2[3])) + +#define NAT64_CMP_V4_KEY1(key1, key2) \ + (key1.key64 == key2.key64) + + +extern u8 nat64_timeout_dirty_flag[NAT64_MAX_NAT64_ENTRIES]; + +#endif diff --git a/plugins/vcgn-plugin/vcgn/nat64_defs.h b/plugins/vcgn-plugin/vcgn/nat64_defs.h new file mode 100644 index 00000000..47e431a7 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/nat64_defs.h @@ -0,0 +1,576 @@ +/* + *------------------------------------------------------------------ + * nat64_defs.h - NAT64 structure definiitions + * + * Copyright (c) 2007-2013 Cisco and/or its affiliates. + * 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 __NAT64_DEFS_H__ +#define __NAT64_DEFS_H__ + +#ifdef TOBE_PORTED +#include "spp_platform_common.h" +#include "cgse_defs.h" +#include "xlat_defs.h" +#endif +#include "cnat_cli.h" +#include "cnat_ports.h" +#include "tcp_header_definitions.h" +#include "nat64_tcp_sm.h" +#include "cnat_db.h" + +#define NAT64_MAX_FRAG_ID_COUNTERS (256) + +#define NAT64_MAX_NAT64_ENTRIES 500 + +#define NAT64_MAX_ID (NAT64_MAX_NAT64_ENTRIES-1) + +#define NAT64_INVALID_ID (0) + +#define NAT64_MAX_CFG_INSTANCES 64 + +#define NAT64_TABLE_ENTRY_DELETED 0 +#define NAT64_TABLE_ENTRY_ACTIVE 1 +#define NAT64_TABLE_ENTRY_DORMANT 2 +#define NAT64_TABLE_ENTRY_INVALID_UIDB 3 + +#define NAT64_MAX_TRANSLATION_ENTRIES PLATFORM_MAX_TRANSLATION_ENTRIES + +#define NAT64_WKP_PREFIX_LEN 96 +#define NAT64_WKP_PREFIX_0 0x0064FF9B +#define NAT64_WKP_PREFIX_1 0x00000000 +#define NAT64_WKP_PREFIX_2 0x00000000 +#define NAT64_WKP_PREFIX_3 0x00000000 + + +/* Reset the expiry time only if it is not 0 +** if it is 0 - then queue for delete by clear command +**/ + +#define NAT64_TIMEOUT_RST(db) \ + if(PREDICT_TRUE(db->entry_expires !=0 )) \ + db->entry_expires = cnat_current_time; + +extern u32 nat64_config_debug_level; +extern u32 nat64_data_path_debug_level; + +extern u32 nat64_translation_create_count[NAT64_MAX_NAT64_ENTRIES]; +extern u32 nat64_translation_delete_count[NAT64_MAX_NAT64_ENTRIES]; +extern u32 nat64_translation_create_rate[NAT64_MAX_NAT64_ENTRIES]; +extern u32 nat64_translation_delete_rate[NAT64_MAX_NAT64_ENTRIES]; +extern u32 nat64_in2out_forwarding_count[NAT64_MAX_NAT64_ENTRIES]; +extern u32 nat64_in2out_forwarding_rate[NAT64_MAX_NAT64_ENTRIES]; +extern u32 nat64_out2in_forwarding_count[NAT64_MAX_NAT64_ENTRIES]; +extern u32 nat64_out2in_forwarding_rate[NAT64_MAX_NAT64_ENTRIES]; + +extern u32 nat64_translation_create_count_old[NAT64_MAX_NAT64_ENTRIES]; +extern u32 nat64_translation_delete_count_old[NAT64_MAX_NAT64_ENTRIES]; +extern u32 nat64_in2out_forwarding_count_old[NAT64_MAX_NAT64_ENTRIES]; +extern u32 nat64_out2in_forwarding_count_old[NAT64_MAX_NAT64_ENTRIES]; + +extern u16 *nat64_frag_id_counter_ptr; + +typedef struct { + u64 v6_to_v4_tcp_input_count; + u64 v6_to_v4_tcp_non_translatable_drop_count; + u64 v6_to_v4_tcp_state_drop_count; + u64 v6_to_v4_tcp_no_db_drop_count; + u64 v6_to_v4_tcp_output_count; +} nat64_v6_to_v4_tcp_counter_t; + +typedef struct { + u64 v4_to_v6_tcp_input_count; + u64 v4_to_v6_tcp_no_db_drop_count; + u64 v4_to_v6_tcp_v4_init_policy_drop_count; + u64 v4_to_v6_tcp_state_drop_count; + u64 v4_to_v6_tcp_output_count; + u64 v4_to_v6_tcp_filter_drop_count; +} nat64_v4_to_v6_tcp_counter_t; + +typedef struct { + u64 v6_to_v4_udp_input_count; + u64 v6_to_v4_udp_non_translatable_drop_count; + u64 v6_to_v4_udp_no_db_drop_count; + u64 v6_to_v4_udp_output_count; + u64 v6_to_v4_udp_checksum_zero_count; +} nat64_v6_to_v4_udp_counter_t; + +typedef struct { + u64 v4_to_v6_udp_input_count; + u64 v4_to_v6_udp_no_db_drop_count; + u64 v4_to_v6_udp_filter_drop_count; + u64 v4_to_v6_udp_output_count; + u64 v4_to_v6_udp_crc_zero_drop_count; + u64 v4_to_v6_udp_frag_crc_zero_drop_count; + u64 v4_to_v6_udp_crc_zero_recycle_sent_count; + u64 v4_to_v6_udp_crc_zero_recycle_drop_count; +} nat64_v4_to_v6_udp_counter_t; + +typedef struct { + u64 v6_to_v4_icmp_input_count; + u64 v6_to_v4_icmp_no_db_drop_count; + u64 v6_to_v4_icmp_non_translatable_drop_count; + u64 v6_to_v4_icmp_qry_output_count; +} nat64_v6_to_v4_icmp_counter_t; + +typedef struct { + u64 v4_to_v6_icmp_input_count; + u64 v4_to_v6_icmp_no_db_drop_count; + u64 v4_to_v6_icmp_filter_drop; + u64 v4_to_v6_icmp_qry_output_count; +} nat64_v4_to_v6_icmp_counter_t; + +typedef struct { + u64 v6_to_v4_icmp_error_input_count; + u64 v6_to_v4_icmp_error_no_db_drop_count; + u64 v6_to_v4_icmp_error_invalid_next_hdr_drop_count; + u64 v6_to_v4_icmp_error_non_translatable_drop_count; + u64 v6_to_v4_icmp_error_unsupported_type_drop_count; + u64 v6_to_v4_icmp_error_output_count; +} nat64_v6_to_v4_icmp_error_counter_t; + +typedef struct { + u64 v4_to_v6_icmp_error_input_count; + u64 v4_to_v6_icmp_error_no_db_drop_count; + u64 v4_to_v6_icmp_error_unsupported_type_drop_count; + u64 v4_to_v6_icmp_error_unsupported_protocol_drop_count; + u64 v4_to_v6_icmp_error_output_count; +} nat64_v4_to_v6_icmp_error_counter_t; + + + +typedef struct { + u64 nat64_v4_frag_input_count; + u64 nat64_v4_frag_forward_count; + u64 nat64_v4_frag_drop_count; + u64 nat64_v4_frag_throttled_count; + u64 nat64_v4_frag_timeout_drop_count; + u64 nat64_v4_frag_tcp_input_count; + u64 nat64_v4_frag_udp_input_count; + u64 nat64_v4_frag_icmp_input_count; + + u64 nat64_v6_frag_input_count; + u64 nat64_v6_frag_forward_count; + u64 nat64_v6_frag_drop_count; + u64 nat64_v6_frag_throttled_count; + u64 nat64_v6_frag_timeout_drop_count; + u64 nat64_v6_frag_tcp_input_count; + u64 nat64_v6_frag_udp_input_count; + u64 nat64_v6_frag_icmp_input_count; + u64 nat64_v6_frag_invalid_input_count; +} nat64_frag_counter_t; + +typedef struct { + u64 v6_to_v4_options_input_count; + u64 v6_to_v4_options_drop_count; + u64 v6_to_v4_options_forward_count; + u64 v6_to_v4_options_no_db_drop_count; + u64 v6_to_v4_unsupp_proto_count; + + u64 v4_to_v6_options_input_count; + u64 v4_to_v6_options_drop_count; + u64 v4_to_v6_options_forward_count; + u64 v4_to_v6_options_no_db_drop_count; + u64 v4_to_v6_unsupp_proto_count; +} nat64_options_counter_t; + +typedef struct { + u64 v4_icmp_gen_count; + u64 v6_icmp_gen_count; +} nat64_icmp_gen_counter_t; + +typedef struct{ + u32 nat64_num_translations; + u32 nat64_num_dynamic_translations; + u32 nat64_num_static_translations; + u32 nat64_sessions; + u64 nat64_port_limit_exceeded; + u64 nat64_system_limit_reached; + u64 nat64_resource_depletion_drops; + u64 nat64_no_translation_entry_drops; + u64 nat64_filtering_drops ; + u64 nat64_invalid_ipv6_prefix_drops; + u32 num_subscribers; + u32 dummy; + u64 drops_sessiondb_limit_exceeded; +} nat64_inst_gen_counter_t; + +typedef struct { + + nat64_v6_to_v4_tcp_counter_t v64_tcp_counters; + nat64_v4_to_v6_tcp_counter_t v46_tcp_counters; + nat64_v6_to_v4_udp_counter_t v64_udp_counters; + nat64_v4_to_v6_udp_counter_t v46_udp_counters; + nat64_v6_to_v4_icmp_counter_t v64_icmp_counters; + nat64_v4_to_v6_icmp_counter_t v46_icmp_counters; + nat64_v6_to_v4_icmp_error_counter_t v64_icmp_error_counters; + nat64_v4_to_v6_icmp_error_counter_t v46_icmp_error_counters; + nat64_frag_counter_t nat64_frag_counters; + nat64_options_counter_t nat64_options_counters; + nat64_icmp_gen_counter_t nat64_icmp_gen_counters; + +} nat64_counters_t; + +/* + * nat64_portmap_v2_t + * This structure stores information about the IP address and ports + * available for NAT for this nat64 instance. + */ + +typedef struct { + u32 delete_time; + u32 last_sent_timestamp; + u32 inuse; + u32 ipv4_address; /* native bit order */ + uword bm[(BITS_PER_INST + BITS(uword)-1)/BITS(uword)]; +} nat64_portmap_t; + +/* + * nat64_v4_db_key_t + * This structure gives information about the v4 transport address + * (ipv4, port, protocol) + */ +typedef struct { + u32 ipv4; + u16 port; + u16 vrf; //bit0-12:inst_id, bit13:unused, bit14-15:protocol +} nat64_v4_db_key_t; + +/* Union will be easier while compare/hash */ +typedef union { + nat64_v4_db_key_t k; + u64 key64; +} nat64_v4_key_t; +/* + * nat64_v6_db_key_t + * This structure gives information about the v6 transport address + * (ipv6, port, protocol) + */ +typedef struct { + u32 ipv6[4]; + u16 port; + u16 vrf; //bit0-12:inst_id, bit13:unused, bit14-15:protocol +} nat64_v6_key_t; + + +typedef struct { + u16 udp_timeout; + u16 tcp_trans_timeout; + u16 tcp_est_timeout; + u16 tcp_v4_init_timeout; + u16 frag_timeout; + u16 icmp_timeout; +} nat64_timeout_info_t; + +#define NAT64_UDP_DEF 300 /* 5min */ +#define NAT64_TCP_TRANS_DEF 240 /* 4min */ +#define NAT64_TCP_EST_DEF 7200 /* 2Hrs */ +#define NAT64_TCP_V4_DEF 6 /* 6 sec */ +#define NAT64_FRAG_DEF 2 /* 2 sec */ +#define NAT64_ICMP_DEF 60 /* 60 sec */ + +/* + * nat64_table_entry_t + * This structure is used to store information regarding every nat64 instance. + */ + +/* structure will hold the L4 information, of a particular frag stream set + * src_port - holds the original src port + * dst_port - holds the original dst port + * total_len - useful only in ICMP nodes + * cnat_port - vlaue used for looksups + * next_prot - Protocol after translation */ + +typedef struct l4_frag_info { + u16 next_node_idx; + u16 src_port; + u16 dst_port; + u16 total_length; + u8 protocol; + u16 cnat_prot; + u16 next_prot; +} l4_frag_info_t; + +typedef struct { + u16 state; + u16 nat64_id; /* nat64_id value for this table entry - for easy access */ + + u16 v4_uidb_index; /* V4 uidb index */ + u16 v6_uidb_index; /* V6 uidb index */ + + u8 octet0_position; + u8 octet1_position; + u8 octet2_position; + u8 octet3_position; + + u16 v4_to_v6_tcp_mss; /* TCP MSS */ + u16 v6_to_v4_tcp_mss; /* TCP MSS */ + + /* + * V6 NAT64 prefix value and mask size + */ + u32 v6_prefix[4]; + u32 v6_prefix_mask[4]; + + u8 v6_prefix_mask_len; + u8 ubits_reserved_on; +#define IPV4_TOS_OVERRIDE_FLAG 0x1 +#define IPV6_TOS_OVERRIDE_FLAG 0x2 +#define NAT64_STFUL_RTSP_ALG_ENABLE 0x4 + u8 feature_flags; + + u8 ipv4_tos_value; + u8 ipv6_tos_value; + u8 df_bit_clear; + u8 ipv6_mtu_set; + + u8 filtering_policy; +#define NAT64_ADDRESS_DEPENDENT_ENABLE 1 + u8 tcp_policy; +#define NAT64_TCP_SECURITY_FLAG_DISABLE 1 + u8 ftp_flags; + + u8 tcp_v4_init_enable; +#define NAT64_TCP_V4_INIT_ENABLE 1 + + u8 logging_policy; +#define NAT64_BIB_LOG_ENABLE 0 /* Default */ +#define NAT64_SESSION_LOG_ENABLE 1 + +#define NAT64_BIDIR_REFRESH 1 /* 1 - timer refresh in both direction */ +#define NAT64_UNIDIR_REFRESH 0 /* 0 - default (only v6 side refresh timer)*/ + + u8 nat64_refresh_both_direction; /* 0 - default (only v6 side refresh timer) */ +#define NAT64_BIDIR_REFRESH 1 /* 1 - timer refresh in both direction */ + + u8 udp_zero_checksum; /* 0 - default (calc checksum) */ +#define NAT64_UDP_ZERO_CHECKSUM_DROP 1 /* 1 -drop */ + + u16 port_limit; + + cnat_portmap_v2_t *port_map; + + u32 logging_index; + + nat64_timeout_info_t timeout_info; + /* + * These fields are not used much, let us keep it in the end + */ + u32 v4_vrf_id; /* V4 vrf id */ + u32 v6_vrf_id; /* V6 vrf id */ + + u32 v4_if_num; /* V4 SVI ifnum */ + u32 v6_if_num; /* V6 SVI ifnum */ + + u16 dyn_start_port; + + u16 pcp_server_port; + u32 pcp_server_addr[4]; + u32 rseed_ip; +#define NAT64_FRAG_ENABLE 1 +#define NAT64_FRAG_DISABLE 0 + u8 frag_state; + u8 nat64_enable; /* Enable/Disable this instance. */ + + u16 rtsp_port; + +} nat64_table_entry_t; + + + +extern nat64_table_entry_t nat64_table_array[NAT64_MAX_NAT64_ENTRIES]; +extern nat64_table_entry_t *nat64_table_ptr; +extern nat64_counters_t nat64_all_counters[NAT64_MAX_NAT64_ENTRIES]; +extern nat64_inst_gen_counter_t nat64_inst_gen_counters[NAT64_MAX_NAT64_ENTRIES]; + +typedef struct nat64_common_pipeline_data_ { +#ifdef TOBE_PORTED + spp_node_main_vector_t *nmv; +#endif + + u16 *nat64_id_ptr; + + nat64_table_entry_t *nat64_entry_ptr; + +} nat64_common_pipeline_data_t; + +typedef struct nat64_v6_to_v4_pipeline_data_ { + nat64_common_pipeline_data_t common_data; + + u32 bib_bucket; + u32 session_bucket; + + nat64_v6_key_t v6_in_key; + nat64_v6_key_t v6_dest_key; + + /* + * IPv6 Data, everthing in host order except for the addr fields + */ + u32 version_trafficclass_flowlabel; + + u16 payload_length; + u8 next_header; + u8 hop_limit; + + /* + * These Address fields are in Network Order, so that + * it is easy to extract the IPv4 address from them + */ + u32 ipv6_src[4]; + + u32 ipv6_dst[4]; + + u8 frag_next_header; + u8 frag_reserved; + u16 frag_offset_res_m; + u32 frag_identification; + + ipv4_header *ipv4_header; + union { + struct _v4_l4_info { + u8 *ipv4_l4_header; + u8 pad0; + u8 pad1; + u8 pad2; + u8 pad3; + } v4_l4_info; + struct _v4_icmp_info { + icmp_v4_t *ipv4_icmp_header; + u8 old_icmp_type; + u8 new_icmp_type; + u8 old_icmp_code; + u8 new_icmp_code; + u16 checksum; + u16 old_iden; // length (ICMP extn), ptr (param) + u16 new_iden; // ----- do ------------- + u16 old_seq; // MTU for PTB case + u16 new_seq; // ----- do ------------- + } v4_icmp_info; + struct _v4_udp_info { + udp_hdr_type_t *ipv4_udp_header; + u8 pad0; + u8 pad1; + u8 pad2; + u8 pad3; + } v4_udp_info; + struct _v4_tcp_info { + tcp_hdr_type *ipv4_tcp_header; + u16 old_src_port; + u16 new_src_port; + u16 dest_port; + nat64_tcp_events tcp_event; + } v4_tcp_info; + } l4_u; + + + l4_frag_info_t *frag_info; /* port for tcp/udp, ident - icmp */ + + + /* Counters will be added here */ + union { + nat64_v6_to_v4_tcp_counter_t *tcp_counter; + nat64_v6_to_v4_udp_counter_t *udp_counter; + nat64_v6_to_v4_icmp_counter_t *icmp_counter; + nat64_v6_to_v4_icmp_error_counter_t *icmp_error_counter; + nat64_frag_counter_t *frag_counter; + nat64_options_counter_t *options_counter; + } nat64_ctr_u; + nat64_icmp_gen_counter_t *icmp_gen_counter; +} nat64_v6_to_v4_pipeline_data_t; + + +typedef struct nat64_v4_to_v6_pipeline_data_ { + nat64_common_pipeline_data_t common_data; + + u32 bib_bucket; + u32 session_bucket; + + nat64_v4_key_t v4_src_key; /* Will be translated using Prefix */ + nat64_v4_key_t v4_dest_key; /* will be the out key for NAT64 */ + + /* + * IPv4 data + */ + u8 version_hdr_len_words; + u8 tos; + u16 total_len_bytes; + + u16 identification; + u16 frag_flags_offset; + + u8 ttl; + u8 protocol; + u16 l4_checksum; + + u32 ipv4_src_addr; + u32 ipv4_dst_addr; + + /* + * Pointers to IPv6 headers + */ + ipv6_header_t *ipv6_header; + ipv6_frag_header_t *ipv6_frag_header; + + union { + struct _v6_l4_info { + u8 *ipv6_l4_header; + u8 pad0; + u8 pad1; + u8 pad2; + u8 pad3; + } v6_l4_info; + struct _v6_icmp_info { + icmp_v6_t *ipv6_icmp_header; + u8 old_icmp_type; + u8 new_icmp_type; + u8 old_icmp_code; + u8 new_icmp_code; + u16 old_iden; // length (ICMP extn), ptr (param) + u16 new_iden; // ----- do ------------- + u16 old_seq; // MTU for PTB case + u16 new_seq; // ----- do ------------- + } v6_icmp_info; + struct _v6_udp_info { + udp_hdr_type_t *ipv6_udp_header; + u8 pad0; + u8 pad1; + u8 pad2; + u8 pad3; + } v6_udp_info; + struct _v6_tcp_info { + tcp_hdr_type *ipv6_tcp_header; + u16 old_dest_port; + u16 new_dest_port; + u16 src_port; + nat64_tcp_events tcp_event; + } v6_tcp_info; + } l4_u; + + l4_frag_info_t *frag_info; /* port for tcp/udp, ident - icmp */ + + /* Need to add counters here */ + union { + nat64_v4_to_v6_tcp_counter_t *tcp_counter; + nat64_v4_to_v6_udp_counter_t *udp_counter; + nat64_v4_to_v6_icmp_counter_t *icmp_counter; + nat64_v4_to_v6_icmp_error_counter_t *icmp_error_counter; + nat64_frag_counter_t *frag_counter; + nat64_options_counter_t *options_counter; + } nat64_ctr_u; + nat64_icmp_gen_counter_t *icmp_gen_counter; + +} nat64_v4_to_v6_pipeline_data_t; + +#endif diff --git a/plugins/vcgn-plugin/vcgn/nat64_tcp_sm.h b/plugins/vcgn-plugin/vcgn/nat64_tcp_sm.h new file mode 100644 index 00000000..3a505bc1 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/nat64_tcp_sm.h @@ -0,0 +1,91 @@ +/* + *------------------------------------------------------------------ + * nat64_tcp_sm.h - Stateful NAT64 translation TCP State machine + * + * Copyright (c) 2011 Cisco and/or its affiliates. + * 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 __NAT64_TCP_SM_H__ +#define __NAT64_TCP_SM_H__ + + +/* TCP States */ +typedef enum { + TCP_CLOSED, + TCP_V4_INIT, + TCP_V6_INIT, + TCP_ESTABLISHED, + TCP_V4_FIN_RCV, + TCP_V6_FIN_RCV, + TCP_V4V6_FIN_RCV, + TCP_TRANS, + TCP_NONE +} nat64_tcp_states; + +/* TCP Events */ +typedef enum { + TCP_TIMEOUT_EV, + TCP_V6_SYN_EV, + TCP_V4_SYN_EV, + TCP_V6_FIN_EV, + TCP_V4_FIN_EV, + TCP_V6_RST_EV, + TCP_V4_RST_EV, + TCP_DEFAULT_EV, + TCP_EV_COUNT +} nat64_tcp_events; + +/* TCP Actions */ +typedef enum { + TCP_FORWARD, + TCP_COND_FORWARD, /* Conditional forward, based on presence of + * session and bib entries */ + TCP_STORE, + TCP_PROBE, + TCP_CREATE_SESSION, + TCP_DELETE_SESSION, + TCP_DROP, + TCP_ACTION_NONE, + TCP_ACTION_COUNT +} nat64_tcp_actions; + +typedef struct { + nat64_tcp_states next_state; + nat64_tcp_actions action; +} nat64_tcp_trans_t; + +typedef struct { + nat64_tcp_trans_t event[TCP_EV_COUNT]; +} nat64_tcp_state_trans_t; + +extern nat64_tcp_state_trans_t nat64_tcp_sm_lookup[TCP_NONE]; + +/* +inline void +nat64_update_v6_to_v4_tcp (nat64_v6_to_v4_pipeline_data_t *pctx_ptr, + nat64_bib_entry_t *bib_ptr); + +inline u8 nat64_v6_to_v4_tcp_perform_action ( + spp_ctx_t *ctx, + nat64_v6_to_v4_pipeline_data_t *pctx_ptr, + nat64_bib_entry_t *bib_db, + nat64_session_entry_t *session_db); + +inline void +nat64_copy_tcp_into_pctx (nat64_v6_to_v4_pipeline_data_t *pctx_ptr); +*/ + + + +#endif diff --git a/plugins/vcgn-plugin/vcgn/platform_common.h b/plugins/vcgn-plugin/vcgn/platform_common.h new file mode 100644 index 00000000..2805b607 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/platform_common.h @@ -0,0 +1,136 @@ +/* + *--------------------------------------------------------------------------- + * platform_common.h -- file has all platform related macros defined as NULL + * included "platform_common_override.h will have actual + * platform specific defines + * + * Copyright (c) 2011-2013 Cisco and/or its affiliates. + * 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 __PLATFORM_COMMON_H__ +#define __PLATFORM_COMMON_H__ + +/* $$$ FIXME causes printf format warnings */ +#define PLATFORM_DEBUG_PRINT(...) /* printf(__VA_ARGS__) */ +#define PLATFORM_FILL_DST_ADDR_PORT_TABLE +#define PLATFORM_SET_CTX_RU_TX_FROM_NODE(ctx, value) +#define PLATFORM_SET_CTX_RU_TX_DST_IPPORT_IDX(ctx, value) +#define PLATFORM_SET_CTX_RU_TX_PKT_TYPE(ctx, type) +#define PLATFORM_SET_RX_VRF(ctx, rx_vrf, hardcode, mask) +#define PLATFORM_SET_TX_VRF(ctx, tx_vrf) +/* PLATFORM_CNAT_SET_RX_VRF definition is not same as PLATFORM_SET_RX_VRF, + * So, maintaining two different definitions + */ +#define PLATFORM_CNAT_SET_RX_VRF(ctx, rx_vrf, proto) +#define PLATFORM_CNAT_SET_TX_VRF(ctx, tx_vrf) + +#define PLATFORM_PRINT_TESTING_PG() +#define PLATFORM_INIT_TEMP_SENSORS() +#define PLATFORM_READ_CPU_SENSORS(value) +#define PLATFORM_SET_TEMP_READ_BLOCK(var, val) +#define PLATFORM_NFV9_DISP_NODE_IDX + + +/* Assumption is, syslog packets + * are sent out via same channel as that of NFV9. + * Has to be overridden if this assumption is false. + */ +#define PLATFORM_SYSLOG_DISP_NODE_IDX PLATFORM_NFV9_DISP_NODE_IDX + +#define PLATFORM_CNAT_DB_DUMP_POLICY_PRINT() +#define PLATFORM_PRINT_CTX_VALUES(ctx) +#define PLATFORM_ADD_VRF_MAP_HANDLE_PARTITION(uidb_index, partition_id) +#define PLATFORM_DEL_VRF_MAP_HANDLE_PARTITION(uidb_index, partition_id) +#define PLATFORM_ALLOC_NFV9_PKT_BUFFER(ctx, to_lc_cpu) +#define PLATFORM_SET_DSLITE_ENABLE_FLAG(uidb_index, dslite_id) +#define PLATFORM_CHECK_DSLITE_ENABLE_FLAG + +#define PLATFORM_CNAT_INSTS 1 +#define PLATFORM_HANDLE_TTL_DECREMENT 0 // Don't handle TTL in NAT44 Application (default). + +// For ISM, we need to copy the ipv6->hop_limit to ipv4 ttl. +#define PLATFORM_6RD_COPY_TTL_IPV6_TO_IPV4 0 + +//For ISM case, need to allow as the TTL decrement happens at ingress LC +#define PLATFORM_6RD_ALLOW_TTL_1 0 + +#define PLATFORM_HANDLE_ICMP_TTL_EXPIRED 0 // Don't handle ICMP_ERROR msg for TTL <=1 in NAT44 App (default). + +#define PLATFORM_IPV4_FRAG_FRAG_HOLD_LIMIT 1 +#define PLATFORM_MAX_IPV4_CTX_ENTRIES 1 +#define PLATFORM_MAPE_FRAG 0 + +#define PLATFORM_ADDR_MASK_PER_CORE 0 +#define PLATFORM_ADDR_MASK_PER_CORE_PER_PARTITION 0 +#define PLATFORM_MAX_CORES 1 +#define PLATFORM_MAX_CORES_PER_PARTITION 1 +#define PLATFORM_MAX_NAT_ENTRIES 1 +#define PLATFORM_MAX_USER_ENTRIES 1 +#define PLATFORM_CNAT_MAX_ADDR_POOL_SIZE 0x1 +#define PLATFORM_DBL_SUPPORT 0 /* Default no DBL support, no NAT44 session table */ + +#define PLATFORM_MAX_DB_ENTRY_PER_SCAN 1 +#define PLATFORM_MAX_DB_ENTRY_SELECTED_PER_SCAN 1 +#define MAX_COMBINED_DB_ENTRIES_PER_SCAN 0 + +#define PLATFORM_CNAT_TIMEOUT_IPPROT_MASK 0 +#define PLATFORM_CNAT_TIMEOUT_PORTPROT_MASK 0 + +#define PLATFORM_MAX_SHOW_BUFFER_SIZE 1700 +#define PLATFORM_MAX_TRANSLATION_ENTRIES (50) +#define PLATFORM_MAX_UTIL_ENTRIES (100) +#define PLATFORM_MAX_NAT44_UTIL_ENTRIES ((64)/PLATFORM_MAX_CORES) + +#define PLATFORM_CNAT_NFV9_SHIM_HDR_OFFSET 0 +#define PLATFORM_CNAT_NFV9_L2_ENCAPS_OFFSET 0 + + +/* Below are nat64 statful related define */ +#define PLATFORM_NAT64_SET_RX_VRF(rx_vrf, proto, inst_id) \ + rx_vrf = proto | (inst_id & CNAT_VRF_MASK); + +#define PLATFORM_NAT64_MAX_TRANSLATION_ENTRIES (30) +#define PLATFORM_DS_LITE_MAX_TRANSLATION_ENTRIES (30) + +#define PLATFORM_SET_NAT64_ENABLE_FLAG(uidb_index, nat64_id) \ + { \ + nat64_set_enable_flag(nat64_id, ENABLE); \ + } + +#define PLATFORM_CHECK_NAT64_ENABLE_FLAG 1 +#define PLATFORM_SET_MAPE_ENABLE_FLAG(uidb_index, mape_id) +#define PLATFORM_CHECK_MAPE_ENABLE_FLAG 1 + +/* very small number , PD has correct value. + this is bcoz, if platform doesnt support nat64..shudnt take too much..*/ +#define PLATFORM_NAT64_MAX_SESSIONS 10 +#define PLATFORM_NAT64_TIMEOUT_HASH_SIZE 10 +#define PLATFORM_MAP_ADDR_PER_CORE 1024 + +#define ENABLE 1 +#define DISABLE 0 + +/* Platform Xlat inline learn function */ +#define PLATFORM_INLINE_LEARN_FUNC(a,b,c) + + +/* Checksum calculation to be done in software */ +#define PLATFORM_XLAT_SW_CHECKSUM_CALC 0 + + +/* Below include overrides all the above null defs and defines platform specific + define */ +#include "platform_common_override.h" + +#endif /* __PLATFORM_COMMON_H__ */ diff --git a/plugins/vcgn-plugin/vcgn/platform_common_override.h b/plugins/vcgn-plugin/vcgn/platform_common_override.h new file mode 100644 index 00000000..d6d3b078 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/platform_common_override.h @@ -0,0 +1,304 @@ +/* + *--------------------------------------------------------------------------- + * platform_common_override.h -- Files has actual platform specific defines. + * Will only included by platform_common.h + * + * Copyright (c) 2011-2013 Cisco and/or its affiliates. + * 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 __PLATFORM_COMMON_OVERRIDE_H__ +#define __PLATFORM_COMMON_OVERRIDE_H__ + +extern unsigned char my_octeon_id; + +#undef PLATFORM_DBL_SUPPORT +#define PLATFORM_DBL_SUPPORT 1 // Destination Based logging support + // NAT44 session table required. + +#undef PLATFORM_ADDR_MASK_PER_CORE +/* commenting this. Currently we are considering only single core */ +//#define PLATFORM_ADDR_MASK_PER_CORE 0x3f // Using 64 cores +#define PLATFORM_ADDR_MASK_PER_CORE 0x01 + +#undef MAX_COMBINED_DB_ENTRIES_PER_SCAN +#define MAX_COMBINED_DB_ENTRIES_PER_SCAN 128 + +#undef PLATFORM_MAX_CORES +#define PLATFORM_MAX_CORES (PLATFORM_ADDR_MASK_PER_CORE + 1) + +// Roddick does not have any partition of cores +#undef PLATFORM_ADDR_MASK_PER_CORE_PER_PARTITION +#define PLATFORM_ADDR_MASK_PER_CORE_PER_PARTITION \ + PLATFORM_ADDR_MASK_PER_CORE + +#undef PLATFORM_MAX_CORES_PER_PARTITION +#define PLATFORM_MAX_CORES_PER_PARTITION PLATFORM_MAX_CORES + +#undef PLATFORM_CNAT_INSTS +//#define PLATFORM_CNAT_INSTS 64 +#define PLATFORM_CNAT_INSTS 1 /* currently its only single instance */ + +#undef PLATFORM_MAX_NAT_ENTRIES +//#define PLATFORM_MAX_NAT_ENTRIES 20000000 // 20M +#define PLATFORM_MAX_NAT_ENTRIES 1666660 // ~80M/48 (79999680/48) + +#undef PLATFORM_MAX_USER_ENTRIES +#define PLATFORM_MAX_USER_ENTRIES 20800 // ~1M/48 (998400/48) + + +/* 524288: + (20000000 translations) / (64 CNAT INSTANCES) = 312500 + nearest higher number which is power of 2 next to 312500 +*/ +#undef PLATFORM_CNAT_MAIN_PRELIM_HASH_SIZE +//#define PLATFORM_CNAT_MAIN_PRELIM_HASH_SIZE 524288 +#define PLATFORM_CNAT_MAIN_PRELIM_HASH_SIZE (5<<20) +/* 4096: + (200000 users) / (64 CNAT INSTANCES) = 3125 + nearest higher number which is power of 2 next to 3125 +*/ +#undef PLATFORM_CNAT_USER_PRELIM_HASH_SIZE +#define PLATFORM_CNAT_USER_PRELIM_HASH_SIZE 4096 + +#undef PLATFORM_CNAT_MAX_ADDR_POOL_SIZE +#define PLATFORM_CNAT_MAX_ADDR_POOL_SIZE 0x10000 // max /16 + +#undef PLATFORM_MAX_DB_ENTRY_PER_SCAN +#define PLATFORM_MAX_DB_ENTRY_PER_SCAN 400 + +#undef PLATFORM_MAX_DB_ENTRY_SELECTED_PER_SCAN +#define PLATFORM_MAX_DB_ENTRY_SELECTED_PER_SCAN 100 // 1/4th of above + +#undef PLATFORM_CNAT_TIMEOUT_IPPROT_MASK +#define PLATFORM_CNAT_TIMEOUT_IPPROT_MASK 0xFFFFFFFF0000FFFF + +#undef PLATFORM_CNAT_TIMEOUT_PORTPROT_MASK +#define PLATFORM_CNAT_TIMEOUT_PORTPROT_MASK 0x00000000FFFFFFFF + +#ifdef TARGET_RODDICK /* EVB doesnt need it */ +#undef PLATFORM_FILL_DST_ADDR_PORT_TABLE +#define PLATFORM_FILL_DST_ADDR_PORT_TABLE fill_dst_addr_port_table(); +#endif + + +#ifndef RODDICK_ON_LINUX_OR_EVB +#undef PLATFORM_SET_CTX_RU_TX_FROM_NODE +#undef PLATFORM_SET_CTX_RU_TX_DST_IPPORT_IDX +#undef PLATFORM_SET_CTX_RU_TX_PKT_TYPE + +#define PLATFORM_SET_CTX_RU_TX_FROM_NODE(ctx, value) \ + (vnet_buffer(ctx))->vcgn_uii.ru.tx.from_node = value; +#define PLATFORM_SET_CTX_RU_TX_DST_IPPORT_IDX(ctx, value) \ + (vnet_buffer(ctx))->vcgn_uii.ru.tx.dst_ip_port_idx = value; +#define PLATFORM_SET_CTX_RU_TX_PKT_TYPE(ctx, type) \ + (vnet_buffer(ctx))->vcgn_uii.ru.tx.packet_type = type; +#endif + +#undef PLATFORM_SET_RX_VRF +#undef PLATFORM_SET_TX_VRF +#ifdef TARGET_RODDICK +#define PLATFORM_SET_RX_VRF(ctx, rx_vrf, hardcode, mask) \ + rx_vrf = (ctx->ru.rx.uidb_index & CNAT_VRF_MASK); +#define PLATFORM_SET_TX_VRF(ctx, tx_vrf) \ + ctx->ru.tx.uidb_index = tx_vrf; +#else /*EVB */ +#define PLATFORM_SET_RX_VRF(ctx, rx_vrf, hardcode, mask) \ + rx_vrf = hardcode; +#define PLATFORM_SET_TX_VRF(ctx, tx_vrf) +#endif + +#undef PLATFORM_CNAT_SET_RX_VRF +#undef PLATFORM_CNAT_SET_TX_VRF + +#define PLATFORM_CNAT_SET_RX_VRF(if_index, rx_vrf, proto) \ + rx_vrf = proto | ((if_index) & CNAT_VRF_MASK); + +#define PLATFORM_CNAT_SET_TX_VRF(if_index, tx_vrf) \ + (if_index) = ((tx_vrf) & CNAT_VRF_MASK); + + + +#undef PLATFORM_NAT64_SET_RX_VRF + +#ifdef TARGET_RODDICK + +#define PLATFORM_NAT64_SET_RX_VRF(rx_vrf, proto, inst_id) \ + rx_vrf = proto | (inst_id & CNAT_VRF_MASK); + +#else /* EVB */ + +#define PLATFORM_NAT64_SET_RX_VRF(rx_vrf, proto, inst_id) \ + rx_vrf = proto | inst_id; + +#endif + +#ifdef TARGET_EVB +#define VRF_MAP_CONFIG +#endif + +#undef PLATFORM_PRINT_TESTING_PG +#if defined(TARGET_LINUX_UDVR) || defined(CNAT_PG) +#define PLATFORM_PRINT_TESTING_PG() printf("testing pg\n"); +#else +#define PLATFORM_PRINT_TESTING_PG() +#endif + +#ifdef TARGET_RODDICK +#undef PLATFORM_INIT_TEMP_SENSORS +#undef PLATFORM_READ_CPU_SENSORS +#undef PLATFORM_SET_TEMP_READ_BLOCK + +#define PLATFORM_INIT_TEMP_SENSORS() Init_temperature_sensors(); +#define PLATFORM_READ_CPU_SENSORS(value) read_octeon_sensors(value); +#define PLATFORM_SET_TEMP_READ_BLOCK(var, val) var = &val->param[0]; +#endif + +#undef PLATFORM_HANDLE_ICMP_TTL_EXPIRED +#define PLATFORM_HANDLE_ICMP_TTL_EXPIRED 1 // handle TTL in NAT44 Application (for AVSM) + +#undef PLATFORM_NFV9_DISP_NODE_IDX +#ifdef TARGET_RODDICK +#define PLATFORM_NFV9_DISP_NODE_IDX "roddick_infra_l3_tx" +#else /* EVB */ +#define PLATFORM_NFV9_DISP_NODE_IDX "cnat_rewrite_output" +#endif + +#undef PLATFORM_CNAT_DB_DUMP_POLICY_PRINT +#define PLATFORM_CNAT_DB_DUMP_POLICY_PRINT() \ + printf("my instance:%d\n" \ + "icmp timeout %d udp init timeout %d act timeout %d\n" \ + "tcp init timeout %d act timeout %d mapping refresh %d\n" \ + "port limit per user %d ftp alg %d lb debug %d\n" \ + "icmp rate limit 0x%x config delete timer 0x%x\n" \ + "global debug flag 0x%x\n" \ + "icmp rate limit (pkts/per sec) %d\n" \ + "dynamic port range start %d\n" \ + "debug ivrf 0x%x flag 0x%x start_addr 0x%x end_addr 0x%x\n" \ + "debug ovrf 0x%x flag 0x%x start_addr 0x%x end_addr 0x%x\n", \ + my_instance_number, \ + icmp_session_timeout, udp_init_session_timeout, udp_act_session_timeout, \ + tcp_initial_setup_timeout, tcp_active_timeout, \ + mapping_refresh_both_direction, cnat_main_db_max_ports_per_user, \ + ftp_alg_enabled, lb_debug_enable, per_user_icmp_msg_limit, \ + config_delete_timeout, \ + global_debug_flag, \ + cnat_main_db_icmp_rate_limit, \ + cnat_static_port_range, \ + debug_i_vrf, debug_i_flag, debug_i_addr_start, debug_i_addr_end, \ + debug_o_vrf, debug_o_flag, debug_o_addr_start, debug_o_addr_end); + + +#undef PLATFORM_PRINT_CTX_VALUES +#ifdef TARGET_RODDICK +#define PLATFORM_PRINT_CTX_VALUES(ctx) \ + printf("\nAFTER: %s cur_hdr %p, uidb %d, pkt_type %d, cur_len %d\n", \ + type_str, \ + ctx->current_header, \ + ctx->ru.tx.uidb_index, \ + ctx->ru.tx.packet_type, \ + ctx->current_length); +#else /* EVB */ +#define PLATFORM_PRINT_CTX_VALUES(ctx) \ + printf("\nAFTER: %s cur_hdr %p, cur_len %d\n", \ + type_str,\ + ctx->current_header, \ + ctx->current_length); +#endif + +#undef PLATFORM_ADD_VRF_MAP_HANDLE_PARTITION +#define PLATFORM_ADD_VRF_MAP_HANDLE_PARTITION(uidb_index, partition_id) + +#undef PLATFORM_DEL_VRF_MAP_HANDLE_PARTITION +#define PLATFORM_DEL_VRF_MAP_HANDLE_PARTITION(uidb_index, partition_id) + +#undef PLATFORM_ALLOC_NFV9_PKT_BUFFER +#define PLATFORM_ALLOC_NFV9_PKT_BUFFER(ctx, to_lc_cpu) + +#undef PLATFORM_CNAT_NFV9_SHIM_HDR_OFFSET +#ifdef TARGET_RODDICK +// This corresponds to the length of the IMETRO SHIM Header for RODDICK +#define PLATFORM_CNAT_NFV9_SHIM_HDR_OFFSET 8 +#else +#define PLATFORM_CNAT_NFV9_SHIM_HDR_OFFSET 0 +#endif + +#undef PLATFORM_CNAT_NFV9_L2_ENCAPS_OFFSET +#ifdef TARGET_RODDICK +#define PLATFORM_CNAT_NFV9_L2_ENCAPS_OFFSET 0 +#else +#define PLATFORM_CNAT_NFV9_L2_ENCAPS_OFFSET 16 +#endif + +#undef PLATFORM_MAX_SHOW_BUFFER_SIZE +#undef PLATFORM_MAX_TRANSLATION_ENTRIES +#undef PLATFORM_MAX_UTIL_ENTRIES + +#define PLATFORM_MAX_SHOW_BUFFER_SIZE 1700 +#define PLATFORM_MAX_TRANSLATION_ENTRIES (50) +#define PLATFORM_NAT64_MAX_TRANSLATION_ENTRIES (30) +#define PLATFORM_MAX_UTIL_ENTRIES (100) + + +#undef PLATFORM_NAT64_MAX_SESSIONS +#undef PLATFORM_NAT64_TIMEOUT_HASH_SIZE +#define PLATFORM_NAT64_MAX_SESSIONS 20000000 +#define PLATFORM_NAT64_TIMEOUT_HASH_SIZE 24001 /* Ref: CSCtr36242 */ + +#undef PLATFORM_CHECK_DSLITE_ENABLE_FLAG +#define PLATFORM_CHECK_DSLITE_ENABLE_FLAG 1 + +/* Fragment hold limit is Platform specific */ +/* For Roddick, it is 63 due to hardware limitation */ +#undef PLATFORM_IPV4_FRAG_FRAG_HOLD_LIMIT +#define PLATFORM_IPV4_FRAG_FRAG_HOLD_LIMIT 63 + +#undef PLATFORM_MAX_IPV4_CTX_ENTRIES +#define PLATFORM_MAX_IPV4_CTX_ENTRIES 80 + +#undef PLATFORM_DIRN_IN_TO_OUT +#undef PLATFORM_DIRN_OUT_TO_IN +#undef PLATFORM_SET_SVI_PARAMS_FIELD + +#define PLATFORM_DIRN_IN_TO_OUT +#define PLATFORM_DIRN_OUT_TO_IN +#define PLATFORM_SET_SVI_PARAMS_FIELD(var, value) + +#undef PLATFORM_GET_NFV9_L3_HDR_OFFSET +#define PLATFORM_GET_NFV9_L3_HDR_OFFSET \ + ((u8 *)ctx + ctx->data + CNAT_NFV9_IP_HDR_OFFSET); + +#undef PLATFORM_GET_NFV9_L4_HDR_OFFSET +#define PLATFORM_GET_NFV9_L4_HDR_OFFSET \ + ((u8 *) ctx + ctx->data + CNAT_NFV9_UDP_HDR_OFFSET); + +#undef PLATFORM_MEMSET_CNAT_LOG_PKT_DATA +#define PLATFORM_MEMSET_CNAT_LOG_PKT_DATA + +/* + Index 0 -- SE_P2MP + Index 1 -- HA Destination 1 + Index 2 -- HA Destination 2 + Index 3 -- EXT_LOG_SRVR +*/ +enum { + NODE_CGNCFG, + NODE_HA, + NODE_PD_CONFIG, + NODE_LOGGING, + NODE_TRACE_BACKUP, + NODE_MAX, +}; + +#endif /* __PLATFORM_COMMON_OVERRIDE_H__ */ diff --git a/plugins/vcgn-plugin/vcgn/spp_ctx.h b/plugins/vcgn-plugin/vcgn/spp_ctx.h new file mode 100644 index 00000000..2d3c95c8 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/spp_ctx.h @@ -0,0 +1,76 @@ +/* + *------------------------------------------------------------------ + * spp_ctx.h - packet / context definitions + * + * Copyright (c) 2007-2014 Cisco and/or its affiliates. + * 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 __SPP_CTX_H__ +#define __SPP_CTX_H__ + +/* Packet header / data */ + +/* Any change to spp_ctx_t structure should be updated in vnet/buffer.h + * as well. + */ +typedef struct _spp_ctx { +#ifdef TOBE_PORTED + /* Following fields are required to handle multibuffer */ + u32 num_buffers; /* Number of buffers part of packet */ + vlib_buffer_t *next_ctx_this_packet; + + /* Following is used by non-UDP protocols */ +#define SPP_CTX_FEATURE_DATA_SIZE 16 + + u8 feature_data[SPP_CTX_FEATURE_DATA_SIZE]; +#endif + + union { /* Roddick specific */ + u32 roddick_info; + struct __tx_pkt_info { /* Used by PI to PI communication for TX */ + u32 uidb_index:16; /* uidb_index to transmit */ + u32 packet_type:2; /* 1-IPv4, 2-Ipv6, - 0,3 - Unused */ + u32 ipv4_defrag:1; /* 0 - Normal, 1 - update first + * segment size + * (set by 6rd defrag node) + */ + + u32 dst_ip_port_idx:4;/* Index to dst_ip_port_table */ + u32 from_node:4; + u32 calc_chksum:1; + u32 reserved:4; + } tx; + struct __rx_pkt_info { /* Used by PD / PI communication */ + u32 uidb_index:16; /* uidb_index received in packet */ + u32 packet_type:2; /* 1-IPv4, 2-Ipv6, - 0,3 - Unused */ + u32 icmp_type:1; /* 0-ICMP query type, 1-ICMP error type */ + u32 protocol_type:2; /* 1-TCP, 2-UDP, 3-ICMP, 0 - Unused */ + u32 ipv4_defrag:1; /* 0 - Normal, 1 - update first + * segment size + * (set by 6rd defrag node) + */ + + u32 direction:1; /* 0-Outside, 1-Inside */ + u32 frag:1; /*IP fragment-1, Otherwise-0*/ + u32 option:1; /* 0-No IP option (v4) present, non-fragHdr + * option hdr present (v6) + */ + u32 df_bit:1; /* IPv4 DF bit copied here */ + u32 reserved1:6; + } rx; + } ru; +} spp_ctx_t; + +#endif diff --git a/plugins/vcgn-plugin/vcgn/spp_platform_trace_log.c b/plugins/vcgn-plugin/vcgn/spp_platform_trace_log.c new file mode 100644 index 00000000..a96894f9 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/spp_platform_trace_log.c @@ -0,0 +1,989 @@ +/* + *------------------------------------------------------------------ + * spp_platform_trace_log.c + * + * Copyright (c) 2008-2011, 2013 Cisco and/or its affiliates. + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include "tcp_header_definitions.h" +#include "platform_common.h" +#include "spp_platform_trace_log.h" + +#define WORD_SIZE sizeof(u32) + +int temperature_read_blocked = 1; + +spp_cnat_logger_tbl_t spp_cnat_logger_table[] = +{ + { CNAT_ERROR_SUCCESS, + 3, + 0, + {"i-vrf", + "ipv4 addr", + "port"} + }, + { CNAT_NO_CONFIG_ERROR, + 3, + 180, + {"i-vrf", + "ipv4 addr", + "port"} + }, + { CNAT_NO_VRF_RUN_ERROR, + 3, + 180, + {"i-vrf", + "ipv4 addr", + "port"} + }, + { CNAT_NO_POOL_FOR_ANY_ERROR, + 3, + 180, + {"i-vrf", + "ipv4 addr", + "port"} + }, + { CNAT_NO_PORT_FOR_ANY_ERROR, + 3, + 60, + {"i-vrf", + "ipv4 addr", + "port"} + }, + { CNAT_BAD_INUSE_ANY_ERROR, + 3, + 60, + {"i-vrf", + "ipv4 addr", + "port"} + }, + { CNAT_NOT_FOUND_ANY_ERROR, + 3, + 60, + {"i-vrf", + "ipv4 addr", + "port"} + }, + { CNAT_INV_PORT_FOR_DIRECT_ERROR, + 3, + 60, + {"i-vrf", + "ipv4 addr", + "port"} + }, + { CNAT_BAD_INUSE_DIRECT_ERROR, + 3, + 1, + {"i-vrf", + "ipv4 addr", + "port"} + }, + { CNAT_NOT_FOUND_DIRECT_ERROR, + 3, + 1, + {"i-vrf", + "ipv4 addr", + "port"} + }, + { CNAT_OUT_OF_PORT_LIMIT_ERROR, + 3, + 60, + {"i-vrf", + "ipv4 addr", + "port"} + }, + { CNAT_MAIN_DB_CREATE_ERROR, + 0, + 30, + {""} + }, + { CNAT_LOOKUP_ERROR, + 1, + 30, + {"Type"} + }, + { CNAT_INDEX_MISMATCH_ERROR, + 2, + 30, + {"in2out_index", + "out2in_index"} + }, + { CNAT_PACKET_DROP_ERROR, + 3, + 15, + {"i-vrf", + "ipv4 addr", + "port"} + }, + { CNAT_INV_UNUSED_USR_INDEX, + 1, + 10, + {"invalid/unused user index"} + }, + { CNAT_INVALID_VRFMAP_INDEX, + 0, + 60, + {""} + }, + { CNAT_USER_OUT_OF_PORTS, + 2, + 1800, + {"i-vrf", + "ipv4 addr"} + }, + { CNAT_EXT_PORT_THRESH_EXCEEDED, + 2, + 180, + {"i-vrf", + "ipv4 address"} + }, + { CNAT_EXT_PORT_THRESH_NORMAL, + 2, + 180, + {"vrf", + "ipv4 address"} + }, + { CNAT_NO_EXT_PORT_AVAILABLE, + 0, + 1, + {"",} + }, + { CNAT_SESSION_THRESH_EXCEEDED, + 2, + 1800, + {"vrf", + "ipv4 address"} + }, + { CNAT_SESSION_THRESH_NORMAL, + 2, + 30, /* changed to 30 */ + {"vrf", + "ipv4 address"} + }, + { WQE_ALLOCATION_ERROR, + 0, + 180, /* changed to 180 */ + {""} + }, + { ERROR_PKT_DROPPED, + 2, + 60, /* changed to 60 */ + {"spi-port", + "error-code"} + }, + { SYSMGR_PD_KEY_CREATION_ERROR, + 0, + 30, + {""} + }, + { SYSMGR_PD_SHMEM_ID_ERROR, + 0, + 1, + {""} + }, + { SYSMGR_PD_SHMEM_ATTACH_ERROR, + 0, + 1, + {""} + }, + { OCTEON_CKHUM_SKIPPED, + 2, + 60, /* changed to 60 */ + {"version", + "protocol"} + }, + { PK0_SEND_STATUS, + 1, + 15, + {"status"} + }, + { CMD_BUF_ALLOC_ERR, + 0, + 60, + {""} + }, + { SPP_CTX_ALLOC_FAILED, + 1, + 300, /* every 5 min */ + {"node"} + }, + { SPP_MAX_DISPATCH_REACHED, + 1, + 60, + {"node"} + }, + { HA_SIGCHILD_RECV, + 3, + 1, + {"pid", + "uid", + "signal",} + }, + { SIGACTION_ERR, + 0, + 1, + {""} + }, + { HA_INVALID_SEQ_OR_CONFIG_OR_TYPE, + 2, + 10, + {"seq-id or config option", + "Type"} + }, + { NODE_CREATION_ERROR, + 1, + 1, + {"node"} + }, + + { CNAT_CLI_INVALID_INPUT, + 4, + 0, + {"Error Type", + "Passed", + "Expected", + "Type"} + }, + { CNAT_DUMMY_HANDLER_HIT, + 1, + 0, + {"Handler"} + }, + { CNAT_CONFIG_ERROR, + 5, + 0, + {"Sub code", + "Param 1", + "Param 2", + "Param 3", + "Param 4"} + }, + { CNAT_NFV9_ERROR, + 1, + 180, /* changed to 180 */ + {"Sub code"} + }, + { CNAT_CMVX_TWSI_READ_WRITE_FAIL, + 3, + 180, + {"Operation", + "Location", + "Data"} + }, + { CNAT_TEMP_SENSOR_TIMEOUT, + 0, + 180, + {""} + }, + { CNAT_TEMP_SENSOR_DATA_MISMATCH, + 2, + 180, + {"Actual", + "Expected"} + }, + { CNAT_TEMP_SENSOR_CONFIG_FAILED, + 1, + 180, + {"Glik"} + }, + { HA_APP_NOT_RESPONDING, + 2, + 180, + {"CPU", + "Core"} + }, + { HA_DATA_PATH_TEST_FAILED, + 0, + 30, + {""} + }, + { CNAT_WRONG_PORT_ALLOC_TYPE, + 3, + 60, + {"i-vrf", + "ipv4 addr", + "port"} + }, + { CNAT_NEW_PORT_ALLOC_ERROR, + 3, + 60, + {"i-vrf", + "ipv4 addr", + "port"} + }, + { CNAT_INVALID_INDEX_TO_FREE_PORT, + 0, + 60, + {""} + }, + { CNAT_DELETE_DB_ENTRY_NO_PORTMAP, + 0, + 60, + {""} + }, + { CNAT_MAIN_DB_LIMIT_ERROR, + 0, + 180, + {""} + }, + { CNAT_USER_DB_LIMIT_ERROR, + 0, + 180, + {""} + }, + { CNAT_FRAG_DB_ERROR, + 1, + 180, + {"Type"} + }, + + { DROP_PKT_DUMP, + 0, + 20, + {""} + } +}; + +#define LOG_TABLE_MAX_ENTRIES \ + (sizeof(spp_cnat_logger_table)/sizeof(spp_cnat_logger_table[0])) + +u32 error_code_timestamps[LOG_TABLE_MAX_ENTRIES]; +spp_timer_t sensor_timer; +spp_trace_log_global_info_t spp_trace_log_global_info; +spp_global_counters_t spp_global_counters; + +/* + * Logging information structures + */ +spp_trace_log_info_t spp_default_trace_log_info; +spp_trace_log_info_t *spp_trace_log_info_pool; + +#ifdef TOBE_PORTED +/* + * The following 2 functions are temporary hacks until + * we have RTC support from the PD nodes + */ +inline +u32 spp_trace_log_get_sys_up_time_in_ms (void) +{ + spp_node_main_vector_t *nmv; + u32 sys_up_time; + + nmv = spp_get_node_main_vectorized_inline(); + + sys_up_time = (u32) (nmv->ticks / nmv->ticks_per_ms); + + return (sys_up_time); +} + +u32 spp_trace_log_get_unix_time_in_seconds (void) +{ + spp_node_main_vector_t *nmv; + u32 unix_time; + + nmv = spp_get_node_main_vectorized_inline(); + + unix_time = (u32) (nmv->ticks / nmv->ticks_per_second); + + return (unix_time); +} + +/* + * edt: * * spp_trace_log_send_queued_pkt + * + * Tries to send a logging pkt that has been queued earlier + * because it could not be sent due to downstream constipation + * + * Argument: spp_trace_log_info_t *trace_logging_info + * structure that contains the packet context + */ +inline +void spp_trace_log_send_queued_pkt (spp_trace_log_info_t *trace_logging_info) +{ + spp_node_t *output_node; + + output_node = spp_get_nodes() + + spp_trace_log_global_info.spp_trace_log_disp_node_index; + + if (PREDICT_TRUE(output_node->sf.nused < SPP_MAXDISPATCH)) { + /* + * Move the logging context to output node + */ + spp_dispatch_make_node_runnable(output_node); + output_node->sf.ctxs[output_node->sf.nused++] = + trace_logging_info->queued_logging_context; + + /* + * Context has been queued, it will be freed after the pkt + * is sent. Clear this from the logging_context_info structure + */ + trace_logging_info->queued_logging_context = NULL; + + } else { + /* + * Can't do much, just return, may be we can send it later + */ + spp_global_counters.spp_trace_log_downstream_constipation_count++; + } +} + +/* + * edt: * * spp_trace_log_send_pkt + * + * Tries to send a logging pkt. If the packet cannot be sent + * because of rewrite_output node cannot process it, queue + * it temporarily and try to send it later. + * + * Argument: spp_trace_log_info_t *trace_logging_info + * structure that contains the packet context + */ +inline +void spp_trace_log_send_pkt (spp_trace_log_info_t *trace_logging_info) +{ + spp_node_t *output_node; + + + output_node = spp_get_nodes() + + spp_trace_log_global_info.spp_trace_log_disp_node_index; + + if (PREDICT_TRUE(output_node->sf.nused < SPP_MAXDISPATCH)) { + /* + * Move the logging context to output node + */ + spp_dispatch_make_node_runnable(output_node); + output_node->sf.ctxs[output_node->sf.nused++] = + trace_logging_info->current_logging_context; + + } else { + /* + * Queue the context into the logging_info structure, + * We will try to send it later. Currently, we will + * restrict to only one context queued. + */ + spp_global_counters.spp_trace_log_downstream_constipation_count++; + + /* + * Attach the current logging context which is full to the + * queued context list in trace_logging_info structure + */ + trace_logging_info->queued_logging_context = + trace_logging_info->current_logging_context; + + /* + * Whether the context is queued or not, set the current context index + * to EMPTY, as the earlier context can no more be used to send + * more logging records. + */ + } + + trace_logging_info->current_logging_context = NULL; +} + +/* + * edt: * * spp_trace_log_send_pkt_always_success + * + * Tries to send a logging pkt. This cannot fail due to downstream + * constipation because we have already checked if the rewrite_output + * node can accept it. + * + * Argument: spp_trace_log_info_t *trace_logging_info + * structure that contains the packet context + * + * Argument: spp_node_t *output_node + * spp_node_t structure for rewrite_output node + */ +inline +void spp_trace_log_send_pkt_always_success ( + spp_trace_log_info_t *trace_logging_info, + spp_node_t *output_node) +{ + /* + * At this point we either have a current or queued logging context + */ + if (PREDICT_TRUE(trace_logging_info->current_logging_context != NULL)) { + + output_node->sf.ctxs[output_node->sf.nused++] = + trace_logging_info->current_logging_context; + + trace_logging_info->current_logging_context = NULL; + } else { + /* + * For queued logging context + */ + output_node->sf.ctxs[output_node->sf.nused++] = + trace_logging_info->queued_logging_context; + + trace_logging_info->queued_logging_context = NULL; + } + + /* + * Move the logging context to output node + */ + spp_dispatch_make_node_runnable(output_node); + +} + +/* + * edt: * * spp_create_trace_log_context + * + * Tries to create a logging context with packet buffer + * to send a new logging packet + * + * Argument: spp_trace_log_info_t *trace_logging_info + * structure that contains the nfv9 logging info and will store + * the packet context as well. + */ +inline +void spp_create_trace_log_context ( + spp_trace_log_info_t *trace_logging_info) +{ + spp_ctx_t *ctx; + + /* + * If queued_logging_context_index is non-EMPTY, we already have a logging + * packet queued to be sent. First try sending this before allocating + * a new context. We can have only one active packet context per + * trace_logging_info structure + */ + if (PREDICT_FALSE(trace_logging_info->queued_logging_context != NULL)) { + spp_trace_log_send_queued_pkt(trace_logging_info); + /* + * If we cannot still send the queued pkt, just return + * Downstream Constipation count would have increased anyway + */ + if (trace_logging_info->queued_logging_context != NULL) { + spp_global_counters.spp_trace_log_context_creation_deferred_count++; + return; + } + } + + + /* + * No context can be allocated, return silently + * calling routine will handle updating the error counters + */ + if (spp_ctx_alloc(&ctx, 1) < 1) { + spp_global_counters.spp_trace_log_context_creation_fail_count++; + return; + } + + trace_logging_info->current_logging_context = ctx; + trace_logging_info->pkt_length = 0; + + trace_logging_info->current_logging_context_timestamp = + spp_trace_log_get_sys_up_time_in_ms(); + + ctx->flags = SPP_CTX_END_OF_PACKET; + ctx->ru.tx.from_node = NODE_TRACE_BACKUP; + ctx->ru.tx.dst_ip_port_idx = EXT_TRACE_BACKUP_INDEX; + ctx->next_ctx_this_packet = (spp_ctx_t*) SPP_CTX_NO_NEXT_CTX; + ctx->current_header = &ctx->packet_data[SPP_TRACE_LOG_HDR_OFFSET]; + ctx->current_length = 0; + + trace_logging_info->log_record = 0; + trace_logging_info->total_record_count = 0; + trace_logging_info->next_data_ptr = + (u8 *) &ctx->packet_data[SPP_TRACE_LOG_HDR_OFFSET]; + +} + +/* + * edt: * * spp_trace_log_add_record_create + * + * Tries to create an add record to the NFV9 packet + * + * Argument: spp_trace_log_info_t *trace_logging_info + * structure that contains the nfv9 logging info and will store + * the packet context as well. + */ +inline +void spp_trace_log_add_record_create (spp_trace_log_info_t *trace_logging_info) +{ + + trace_logging_info->log_header = + (spp_trace_log_hdr_t *) (trace_logging_info->next_data_ptr); + + /* + * Initialize the number of traces recorded + */ + trace_logging_info->log_header->num_traces = + spp_host_to_net_byte_order_32(0); + + + trace_logging_info->log_record = + (spp_trace_log_t *) (trace_logging_info->log_header + 1); + + /* + * Update the length of the total pkt + */ + trace_logging_info->pkt_length += + SPP_LOG_TRACE_HEADER_LENGTH; + + /* + * Set the data pointer beyond the trace header field + */ + trace_logging_info->next_data_ptr = + (u8 *) (trace_logging_info->log_header + 1); + +} + +/* + * edt: * * spp_trace_logger + * + * Tries to log spp/cnat event/errors + * + * Argument: u8 *error_code + * Error code passed + * + * Argument: optional arguments + */ +void spp_trace_logger (u16 error_code, u16 num_args, u32 *arg) +{ + spp_trace_log_info_t *trace_logging_info = 0; + u8 i; + + trace_logging_info = + spp_trace_log_info_pool + + spp_trace_log_global_info.spp_log_pool_index[SPP_LOG_LTRACE]; + + if (PREDICT_FALSE(trace_logging_info->current_logging_context == NULL)) { + spp_create_trace_log_context(trace_logging_info); + + /* + * If still empty, return after increasing the count + */ + if (PREDICT_FALSE(trace_logging_info->current_logging_context == NULL)) { + return; + } + } + + if (PREDICT_FALSE(trace_logging_info->log_record == NULL)) { + spp_trace_log_add_record_create(trace_logging_info); + } + + /* + * We should definitely have add_record now, no need to sanitize + */ + trace_logging_info->log_record->error_code = + spp_host_to_net_byte_order_16(error_code); + trace_logging_info->log_record->num_args = + spp_host_to_net_byte_order_16(num_args); + + for (i = 0; i < num_args; i++) { + trace_logging_info->log_record->arg[i] = + spp_host_to_net_byte_order_32(*(arg + i)); + } + + trace_logging_info->pkt_length += SPP_TRACE_LOG_RECORD_LENGTH + WORD_SIZE*num_args; + trace_logging_info->current_logging_context->current_length = + trace_logging_info->pkt_length; + trace_logging_info->total_record_count += 1; + + trace_logging_info->next_data_ptr = + (u8 *) (trace_logging_info->next_data_ptr + WORD_SIZE + WORD_SIZE*num_args); + + trace_logging_info->log_record = + (spp_trace_log_t *) (trace_logging_info->next_data_ptr); + + /* + * Initialize the number of traces recorded + */ + trace_logging_info->log_header->num_traces = + spp_host_to_net_byte_order_32(trace_logging_info->total_record_count); + + + + /* + * If we have exceeded the packet length, let us send the + * packet now. There is buffer of additional bytes beyond + * max_pkt_length to ensure that the last add/delete record + * can be stored safely. + */ + if (trace_logging_info->pkt_length > + trace_logging_info->max_length_minus_max_record_size) { + spp_trace_log_send_pkt(trace_logging_info); + } +} + + +/* + * edt: * * spp_trace_log_timer_handler + * + * Timer handler for sending any pending NFV9 record + * + * Argument: spp_timer_t * timer_p + * Timer handler structure + */ +inline +void spp_trace_log_timer_handler (spp_timer_t * timer_p) +{ + spp_node_t *output_node; + spp_trace_log_info_t *trace_logging_info = 0; + u32 current_timestamp = spp_trace_log_get_sys_up_time_in_ms(); + i16 sf_nused; + + output_node = spp_get_nodes() + + spp_trace_log_global_info.spp_trace_log_disp_node_index; + + sf_nused = output_node->sf.nused; + + pool_foreach (trace_logging_info, spp_trace_log_info_pool, ({ + /* + * Check if no more logging contexts can be queued + */ + if (PREDICT_FALSE(sf_nused >= SPP_MAXDISPATCH)) { + break; + } + + /* + * If there is a current logging context and timestamp + * indicates it is pending for long, send it out + * Also if there is a queued context send it out as well + */ + if (trace_logging_info->queued_logging_context || + (trace_logging_info->current_logging_context && + (current_timestamp - + trace_logging_info->current_logging_context_timestamp) + > 1000)) { + spp_trace_log_send_pkt_always_success(trace_logging_info, + output_node); + sf_nused++; + } + })); + + timer_p->expires = + spp_timer_in_n_ms_inline(1000); /* every 1 sec */ + spp_timer_start(timer_p); + +} +inline +void spp_sensor_timer_handler (spp_timer_t * timer_p) +{ +#ifdef TARGET_RODDICK + if (!temperature_read_blocked) { + Init_temperature_sensors(); + read_octeon_sensors(TEMPERATURE_SENSOR_QUIET_MODE); + } + + timer_p->expires = + spp_timer_in_n_ms_inline(60000); /* every 1 sec */ + spp_timer_start(timer_p); + +#endif +} +void init_trace_log_buf_pool (void) +{ + spp_trace_log_info_t *my_spp_log_info; + u8 found; + spp_log_type_t log_type; + + /* + * Init SPP logging info as needed, this will be done only once + */ + spp_trace_log_init(); + + found = 0; + + for (log_type = SPP_LOG_LTRACE; log_type < SPP_LOG_MAX; log_type++ ) { + /* Do we already have a map for this log type? */ + pool_foreach (my_spp_log_info, spp_trace_log_info_pool, ({ + if (my_spp_log_info->log_type == log_type) { + found = 1; + break; + } + })); + + /* + * Entry not present + */ + if (!found) { + pool_get(spp_trace_log_info_pool, my_spp_log_info); + memset(my_spp_log_info, 0, sizeof(*my_spp_log_info)); + + /* + * Make the current and head logging context indeices as EMPTY. + * When first logging happens, these get set correctly + */ + my_spp_log_info->current_logging_context = NULL; + my_spp_log_info->queued_logging_context = NULL; + + my_spp_log_info->log_type = log_type; + my_spp_log_info->max_length_minus_max_record_size = + SPP_TRACE_LOG_MAX_PKT_LENGTH; + + spp_trace_log_global_info.spp_log_pool_index[log_type] = + my_spp_log_info - spp_trace_log_info_pool; + } + + } + + return; +} + + +/* + * one time function + * has to be called at the init time + */ +void spp_trace_log_init (void) +{ + if (!spp_trace_log_global_info.spp_trace_log_init_done) { + +#ifdef TARGET_RODDICK + spp_trace_log_global_info.spp_trace_log_disp_node_index = + spp_lookup_node_index("roddick_infra_l3_tx"); +#elif defined(TARGET_BOOSTER) + spp_trace_log_global_info.spp_trace_log_disp_node_index = + spp_lookup_node_index("booster_infra_l3_tx"); +#endif + ASSERT(spp_trace_log_global_info.spp_trace_log_disp_node_index != (u16)~0); + + spp_trace_log_global_info.log_timer.cb_index = + spp_timer_register_callback(spp_trace_log_timer_handler); + spp_trace_log_global_info.log_timer.expires = + spp_timer_in_n_ms_inline(1000); /* every 1 sec */ + spp_timer_start(&spp_trace_log_global_info.log_timer); + + if (!my_core_id) { + sensor_timer.cb_index = + spp_timer_register_callback(spp_sensor_timer_handler); + sensor_timer.expires = + spp_timer_in_n_ms_inline(60000); /* every 1 sec */ + spp_timer_start(&sensor_timer); + } + + spp_trace_log_global_info.spp_trace_log_init_done = 1; + + /* + * Set MSC ip_addr, port values + */ +#ifdef TARGET_RODDICK + dst_ipv4_port_table[EXT_TRACE_BACKUP_INDEX].ipv4_address = + vpp_boot_params.msc_ip_address; + switch(vpp_boot_params.octeon_number) { + case 0: + dst_ipv4_port_table[EXT_TRACE_BACKUP_INDEX].port = 0x15BF; + break; + case 1: + dst_ipv4_port_table[EXT_TRACE_BACKUP_INDEX].port = 0x15BF; + break; + case 2: + dst_ipv4_port_table[EXT_TRACE_BACKUP_INDEX].port = 0x15BF; + break; + case 3: + dst_ipv4_port_table[EXT_TRACE_BACKUP_INDEX].port = 0x15BF; + break; + } +#else + dst_ipv4_port_table[EXT_TRACE_BACKUP_INDEX].ipv4_address = 0x01020304; + dst_ipv4_port_table[EXT_TRACE_BACKUP_INDEX].port = 0x15BF; +#endif + + } +} + +void spp_printf (u16 error_code, u16 num_args, u32 *arg) +{ + u32 current_timestamp; + spp_node_main_vector_t *nmv; + + if (PREDICT_FALSE(error_code >= LOG_TABLE_MAX_ENTRIES)) + { + /* printf("Error code invalid %d, %d, %d, %d\n", + error_code, LOG_TABLE_MAX_ENTRIES, + sizeof(spp_cnat_logger_table), sizeof(spp_cnat_logger_table[0])); + */ + return; /* Should not happen */ + } + + nmv = spp_get_node_main_vectorized_inline(); + current_timestamp = nmv->ticks / nmv->ticks_per_second; + + /* Check if any further hashing is required */ + + if (PREDICT_FALSE(error_code == DUMP_PKT_IDX)) { +#ifdef TARGET_RODDICK || defined(TARGET_BOOSTER) + spp_trace_logger(error_code, num_args, arg); +#else + u8 j ; + + printf("PKT DUMP :: "); + for (j = 0 ; j < num_args; j++) { + printf("0x%x ", arg[j]); + if (j == (num_args - 1)) { + printf("\n"); + } + } +#endif + } else if (PREDICT_TRUE((current_timestamp - error_code_timestamps[error_code]) >= + spp_cnat_logger_table[error_code].rate_limit_time)) { + /* update timestamp */ + error_code_timestamps[error_code] = current_timestamp; + +#ifdef TARGET_RODDICK || defined(TARGET_BOOSTER) + spp_trace_logger(error_code, num_args, arg); +#else + u8 j ; + + for (j = 0 ; j < num_args; j++) { + printf("%s: %d ", spp_cnat_logger_table[error_code].param_name[j], arg[j]); + if (j == (num_args - 1)) { + printf("\n"); + } + } +#endif + } +} + +#else /* TOBE_PORTEED */ +void spp_trace_logger(u16 error_code, u16 num_args, u32 *arg) +{ + /* To be filled */ +} + +void spp_trace_log_init(void) +{ + /* To be filled */ +} + +void init_trace_log_buf_pool(void) +{ + /* To be filled */ +} + +void spp_printf(u16 error_code, u16 num_args, u32 *arg) +{ + /* To be filled */ +} + +inline u32 spp_trace_log_get_unix_time_in_seconds (void) +{ + vlib_main_t *vlib_main; + + vlib_main = vlib_get_main(); + return(vlib_time_now((vlib_main_t *) vlib_main)); +} + +#endif /* TOBE_PORTED */ + diff --git a/plugins/vcgn-plugin/vcgn/spp_platform_trace_log.h b/plugins/vcgn-plugin/vcgn/spp_platform_trace_log.h new file mode 100644 index 00000000..36da710f --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/spp_platform_trace_log.h @@ -0,0 +1,358 @@ +/* + *------------------------------------------------------------------ + * spp_platform_trace_log.h + * + * Copyright (c) 2009-2013 Cisco and/or its affiliates. + * 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 __SPP_PLATFORM_TRACE_LOG_H__ +#define __SPP_PLATFORM_TRACE_LOG_H__ + +#include +#include +#include +#include +#include +#include + +#include "spp_ctx.h" +#include "spp_timers.h" + + +typedef enum { + SPP_LOG_LTRACE, + SPP_LOG_MAX +} spp_log_type_t; + +typedef struct { + u32 num_traces; +} spp_trace_log_hdr_t; + +typedef struct { + u16 error_code; + u16 num_args; + u32 arg[0]; +} spp_trace_log_t; + +#define DUMP_PKT_IDX 61 +#define OCTEON_SENSOR_READ 62 + +typedef enum { + CNAT_ERROR_SUCCESS, + CNAT_NO_CONFIG_ERROR, + CNAT_NO_VRF_RUN_ERROR, + CNAT_NO_POOL_FOR_ANY_ERROR, + CNAT_NO_PORT_FOR_ANY_ERROR, + CNAT_BAD_INUSE_ANY_ERROR, + CNAT_NOT_FOUND_ANY_ERROR, + CNAT_INV_PORT_FOR_DIRECT_ERROR, + CNAT_BAD_INUSE_DIRECT_ERROR, + CNAT_NOT_FOUND_DIRECT_ERROR, + CNAT_OUT_OF_PORT_LIMIT_ERROR, + CNAT_MAIN_DB_CREATE_ERROR, + CNAT_LOOKUP_ERROR, + CNAT_INDEX_MISMATCH_ERROR, + CNAT_PACKET_DROP_ERROR, + CNAT_INV_UNUSED_USR_INDEX, + CNAT_INVALID_VRFMAP_INDEX, + CNAT_USER_OUT_OF_PORTS, + CNAT_EXT_PORT_THRESH_EXCEEDED, + CNAT_EXT_PORT_THRESH_NORMAL, + CNAT_NO_EXT_PORT_AVAILABLE, + CNAT_SESSION_THRESH_EXCEEDED, + CNAT_SESSION_THRESH_NORMAL, + WQE_ALLOCATION_ERROR, + ERROR_PKT_DROPPED, + SYSMGR_PD_KEY_CREATION_ERROR, + SYSMGR_PD_SHMEM_ID_ERROR, + SYSMGR_PD_SHMEM_ATTACH_ERROR, + OCTEON_CKHUM_SKIPPED, + PK0_SEND_STATUS, + CMD_BUF_ALLOC_ERR, + SPP_CTX_ALLOC_FAILED, + SPP_MAX_DISPATCH_REACHED, + HA_SIGCHILD_RECV, + SIGACTION_ERR, + HA_INVALID_SEQ_OR_CONFIG_OR_TYPE, + NODE_CREATION_ERROR, + CNAT_CLI_INVALID_INPUT, /* new adds as part of CSCto04510, see sub codes below */ + CNAT_DUMMY_HANDLER_HIT, /* Has sub codes , see spp_dummy_handler_sub_cdes_t */ + CNAT_CONFIG_ERROR, /* has subcodes-see spp_config_error_sub_codes_t below */ + CNAT_NFV9_ERROR, /* Has sub codes see spp_nfv9_error_sub_codes_t below */ + CNAT_CMVX_TWSI_READ_WRITE_FAIL, /* Hassub codes see spp_cmvx_error_sub_codes_t */ + CNAT_TEMP_SENSOR_TIMEOUT, + CNAT_TEMP_SENSOR_DATA_MISMATCH, + CNAT_TEMP_SENSOR_CONFIG_FAILED, + HA_APP_NOT_RESPONDING, + HA_DATA_PATH_TEST_FAILED, + CNAT_WRONG_PORT_ALLOC_TYPE, + CNAT_NEW_PORT_ALLOC_ERROR, + CNAT_INVALID_INDEX_TO_FREE_PORT, + CNAT_DELETE_DB_ENTRY_NO_PORTMAP, + CNAT_MAIN_DB_LIMIT_ERROR, + CNAT_USER_DB_LIMIT_ERROR, + CNAT_FRAG_DB_ERROR, /* see spp_frag_db_error_sub_codes_t below */ + + DROP_PKT_DUMP, + CNAT_NAT64_SYSTEM_LIMIT_ERROR, + CNAT_ERROR_MAX +} spp_error_codes_t; + +typedef enum { + + TCP_MSS_INVALID_IVRF = 10, /* 1 param - vrf id */ + NFV9_LOG_INVALID_IP_OR_PORT = 20, /* 2 params - nfv9 server ip and port */ + NFV9_LOG_INVALID_PARAMS_OTHERS, /* 3 params, ref rate, time out, path mtu */ + NFV9_LOG_PATH_MTU_TOO_SMALL, /* 1 param, path mtu passed */ + NFV9_LOG_CANNOT_ADD_VRF_NOT_FOUND, /* 1 param, in vrf id */ + + VRF_MAP_ADDR_POOL_START_ADDR_GT_END_ADDR = 30, /* 2 params, start and end addr */ + VRF_MAP_ADDR_POOL_ADDR_POOL_TOO_LARGE, /* 2 params, start and end addr */ + VRF_MAP_ADDR_POOL_INVALID_IN_OR_OUT_VRF, /* 2 params, in vrf and out vrf */ + VRF_MAP_ADDR_POOL_TOO_LARGE_FOR_CORE, /* 2 params, pool size, core instance */ + VRF_MAP_DEL_POOL_START_ADDR_GT_END_ADDR, /* 2 params, start and end addr */ + VRF_MAP_DEL_POOL_ADDR_POOL_NOT_FOUND, /* 2 params, start and end addr */ + VRF_MAP_DEL_POOL_VRF_MAP_EMPTY, /* 2 params, start and end addr */ + + ADD_SVI_ADDR_INVALID_VRF = 40, /* 2 params, vrf passed and ipv4 addr */ + ADD_SVI_INDEX_INVALID_VRF, /* 2 params, vrf, uidb_index */ + + MAPPED_STAT_PORT_INVALID_OUTPUT_PARAMS = 50, + /* 3 params, out vrf, out ip, out port */ + MAPPED_STAT_PORT_UDP_PORT_POLARITY_MISMATCH, /* 2 params, in port and out port */ + MAPPED_STAT_PORT_IN_VRF_MAP_EMPTY, /* 1 param, in vrf id passed */ + MAPPED_STAT_PORT_VRF_MAP_NOT_IN_S_RUN, /* 1 param, vrf map status */ + MAPPED_STAT_PORT_INVALID_OUT_VRF_ID, /* 1 param, out vrf id passed */ + MAPPED_STAT_PORT_FAILED_TO_ADD_STAT_PORT, /* 4 params, in vrf, in ip, in port, error code */ + + STAT_PORT_INVALID_IN_PARAMS = 60, /* 4 params, in vrf, in ip, in port, proto */ + STAT_PORT_FAILED_TO_ADD_STAT_PORT, /* 4 params, in vrf, in ip, in port, error code */ + STAT_PORT_CONFIG_IN_USE, /* 4 params, in vrf, in ip, in port, proto */ + + DEL_STAT_PORT_IN_VRF_MAP_EMPTY = 70, /* 1 param, in vrf id passed */ + DEL_STAT_PORT_INVALID_IN_PARAMS, /* 4 params, in vrf, in ip, in port, proto */ + DEL_STAT_PORT_CANNOT_DELETE_NO_ENTRY, /* 4 params, in vrf, in ip, in port, proto */ + DEL_STAT_PORT_CANNOT_DELETE_NOT_STATIC_PORT, /* 4 params, in vrf, in ip, in port, proto*/ + + XLAT_SVI_CFG_INVALID_INDEX = 80, /* 1 param - uidb_index */ + XLAT_WRONG_V6_PREFIX_MASK, /* 1 param - v6 prefix mask */ + XLAT_INVALID_XLAT_ID_ERROR, /* 1 param - id */ + + V6RD_INVALID_6RD_ID_ERROR = 90, /*1 param - id */ + MAPE_INVALID_MAPE_ID_ERROR = 100 /* param - id */ +} spp_config_error_sub_codes_t; + +typedef enum { + CONFIG_DUMMY, + CONFIG_DUMMY_MAX, + SHOW_DUMMY, + SHOW_DUMMY_MAX, + DEBUG_DUMMY, + DEBUG_DUMMY_MAX +} spp_dummy_handler_sub_cdes_t; + +typedef enum { + CMVX_READ, + CMVX_WRITE +} spp_cmvx_error_sub_codes_t; + +typedef enum { + FRAG_DB_INVALID_BUCKET, + FRAG_DB_NO_ENTRY +} spp_frag_db_error_sub_codes_t; + +typedef enum { + CLI_INVALID_PAYLOAD_SIZE, + CLI_INVALID_MSG_ID +} spp_cli_error_sub_codes_t; + +typedef enum { + NFV9_DOWNSTREAM_CONGESTION, + NFV9_FAILED_TO_CREATE_CONTEXT +} spp_nfv9_error_sub_codes_t; + +typedef struct spp_cnat_logger_tbl_t_ { + u16 error_code; // The thread id stored by software + u16 num_args; + u16 rate_limit_time; // If we need to rate_limit logging + u8 param_name[7][32];// Parameter name for debug purposes +} spp_cnat_logger_tbl_t; + +extern spp_cnat_logger_tbl_t spp_cnat_logger_table[]; + +/* + * This corresponds to the length of the IMETRO SHIM Header for RODDICK + * For non-roddick cases, introduce an Ethernet header as well + */ +#if defined(RODDICK) +#define SPP_TRACE_LOG_SHIM_HDR_OFFSET 8 +#define SPP_TRACE_LOG_ENCAPS_OFFSET 0 +#else +#define SPP_TRACE_LOG_SHIM_HDR_OFFSET 0 +#define SPP_TRACE_LOG_ENCAPS_OFFSET 16 +#endif + +#define SPP_LOG_TRACE_HEADER_LENGTH \ + (sizeof(spp_trace_log_hdr_t)) + + +#define SPP_TRACE_LOG_IP_HDR_OFFSET \ + (SPP_TRACE_LOG_ENCAPS_OFFSET + \ + SPP_TRACE_LOG_SHIM_HDR_OFFSET) + + +#define SPP_TRACE_LOG_UDP_HDR_OFFSET \ + (SPP_TRACE_LOG_IP_HDR_OFFSET + sizeof(ipv4_header)) + +#define SPP_TRACE_LOG_HDR_OFFSET \ + (SPP_TRACE_LOG_UDP_HDR_OFFSET + sizeof(udp_hdr_type_t)) + +#define SPP_TRACE_LOG_RECORD_LENGTH 4 + +/* + * Let us put the maximum length of the log data to be 1400 + */ +#define SPP_TRACE_LOG_MAX_PKT_LENGTH 800 + +/* Structures and defines to store log info for MSC */ +#define SPP_TRACE_LOG_INVALID_LOGGING_INDEX 0xffffffff + +/* + * This structure stores the Logging information on per LOG TYPE + * basis. This structure is allocated from a pool and index + * to this structure based on log type + */ +typedef struct { + /* + * This field determines the maximum size of the Netflow V9 information + * that can be stored in a logging packet + */ + u16 max_length_minus_max_record_size; + + u32 sequence_num; /* Sequence number of the logging packet */ + u32 last_pkt_sent_count; + u16 pkt_length; /* Length of the currently NFv9 information */ + u16 log_record_length; /* Length of add record */ + u16 total_record_length; /* number of trace records */ + u16 total_record_count; + spp_log_type_t log_type; + /* + * current logging context + */ + spp_ctx_t *current_logging_context; + + /* + * Timestamp in UNIX seconds corresponding to when the current + * logging packet was created + */ + u32 current_logging_context_timestamp; + + /* + * Queued logging context waiting to be sent to the l3 infra node + */ + spp_ctx_t *queued_logging_context; + + /* + * Headers corresponding to various records in this + * current nfv9 logging context + */ + spp_trace_log_t *log_record; + spp_trace_log_hdr_t *log_header; + u8 *next_data_ptr; + +} spp_trace_log_info_t; + +typedef struct { + /* + * spp_ctx_alloc() call failed + */ + u64 spp_trace_log_context_creation_fail_count; + + /* + * Cannot send the existing logging pkt, so cannot create + * any additional packets for logging purposes + */ + u64 spp_trace_log_context_creation_deferred_count; + + /* + * Cannot send the existing logging pkt due to cnat_rewrite_output + * superframe being full. + */ + u64 spp_trace_log_downstream_constipation_count; +} spp_global_counters_t; + + +/* + * Global structure for SPP LOGS + */ +typedef struct { + /* A timer structure to periodically send log packets + * that have been waiting to be full for a long time. This will + * ensure event/error logs don't get delayed too much before they + * are sent to the MSC. + */ + spp_timer_t log_timer; + + /* + * Node index corresponding to the infra L3 output node + * to which the nfv9 logging node will send the packet + */ + u16 spp_trace_log_disp_node_index; + + /* + * Whether we have initialized the NFv9 information + */ + u8 spp_trace_log_init_done; + + /* + * pool index in global pool based on log type + */ + u32 spp_log_pool_index[SPP_LOG_MAX]; + +} spp_trace_log_global_info_t; + + +extern spp_timer_t sensor_timer; +extern spp_trace_log_info_t spp_default_trace_log_info; +extern spp_trace_log_info_t *spp_trace_log_info_pool; + +extern spp_trace_log_global_info_t spp_trace_log_global_info; + +void spp_trace_logger(u16 error_code, u16 num_args, u32 *arg); +void spp_trace_log_init(void); +void init_trace_log_buf_pool(void); +void spp_printf(u16 error_code, u16 num_args, u32 *arg); + +/* + * The following 2 functions are temporary hacks until + * we have RTC support from the PD nodes + */ +#if 0 +inline +u32 spp_trace_log_get_sys_up_time_in_ms (void); +#endif +extern +u32 spp_trace_log_get_unix_time_in_seconds (void); + +enum { + TEMPERATURE_SENSOR_TEST_MODE, + TEMPERATURE_SENSOR_QUIET_MODE, +}; + +extern int temperature_read_blocked; + +void read_octeon_sensors(u8 mode); +void Init_temperature_sensors(); +#endif /* __SPP_PLATFORM_TRACE_LOG_H__ */ diff --git a/plugins/vcgn-plugin/vcgn/spp_timers.h b/plugins/vcgn-plugin/vcgn/spp_timers.h new file mode 100644 index 00000000..afb0147b --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/spp_timers.h @@ -0,0 +1,139 @@ +/* + *------------------------------------------------------------------ + * spp_timers.h + * + * Copyright (c) 2008-2009 Cisco and/or its affiliates. + * 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 __SPP_TIMERS_H__ +#define __SPP_TIMERS_H__ + + +typedef struct d_list_el_ { + struct d_list_el_ *next; + struct d_list_el_ *prev; +} d_list_el_t; + +/* + * d_list_init + */ + +static inline void d_list_init (d_list_el_t *headp) +{ + headp->prev = headp->next = headp; +} + +/* + * d_list_init - add at head of list + */ + +static inline void d_list_add_head (d_list_el_t *headp, + d_list_el_t *elp) +{ + ASSERT(elp->prev == elp); /* multiple enqueue, BAD! */ + ASSERT(elp->next == elp); + + elp->next = headp->next; + headp->next = elp; + elp->prev = elp->next->prev; + elp->next->prev = elp; +} + +/* + * d_list_add_tail - add element at tail of list + */ +static inline void d_list_add_tail (d_list_el_t *headp, + d_list_el_t *elp) +{ + ASSERT(elp->prev == elp); /* multiple enqueue, BAD! */ + ASSERT(elp->next == elp); + + headp = headp->prev; + + elp->next = headp->next; + headp->next = elp; + elp->prev = elp->next->prev; + elp->next->prev = elp; +} + +/* + * d_list_rem_head - removes first element from list + */ +static inline d_list_el_t *d_list_rem_head (d_list_el_t *headp) +{ + d_list_el_t *elp; + + elp = headp->next; + if (elp == headp) + return (NULL); + headp->next = elp->next; + elp->next->prev = elp->prev; + + elp->next = elp->prev = elp; + return (elp); +} + +/* + * d_list_rem_elem - removes specific element from list. + */ +static inline void d_list_rem_elem (d_list_el_t *elp) +{ + d_list_el_t *headp; + + headp = elp->prev; + + headp->next = elp->next; + elp->next->prev = elp->prev; + elp->next = elp->prev = elp; +} + +#define TIMER_BKTS_PER_WHEEL 128 /* power of 2, please */ +#define TIMER_NWHEELS 4 + +typedef struct { + i32 curindex; /* current index for this wheel */ + d_list_el_t *bkts; /* vector of bucket listheads */ +} spp_timer_wheel_t; + + +typedef struct { + u64 next_run_ticks; /* Next time we expire timers */ + spp_timer_wheel_t **wheels; /* pointers to wheels */ +} spp_timer_axle_t; + + +typedef struct { + d_list_el_t el; + u16 cb_index; + u16 flags; + u64 expires; +} spp_timer_t; + +#define SPP_TIMER_RUNNING 0x0001 + + +/* + * prototypes + */ +void spp_timer_set_ticks_per_ms(u64); +void spp_timer_axle_init (spp_timer_axle_t *ta); +void spp_timer_expire(spp_timer_axle_t *ta, u64 now); +void spp_timer_final_init(void); + +void spp_timer_start(spp_timer_t *tp); +void spp_timer_start_axle(spp_timer_axle_t *ta, spp_timer_t *tp); +void spp_timer_stop(spp_timer_t *tp); +u16 spp_timer_register_callback (void (*fp)(spp_timer_t *)); + +#endif /* __SPP_TIMERS_H__ */ diff --git a/plugins/vcgn-plugin/vcgn/tcp_header_definitions.h b/plugins/vcgn-plugin/vcgn/tcp_header_definitions.h new file mode 100644 index 00000000..02920bcc --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/tcp_header_definitions.h @@ -0,0 +1,1582 @@ +/* + *----------------------------------------------------------------------------- + * + * Filename: tcp_header_definitions.h + * + * Description: Layer 2, 3, 4 definitions and header types + * + * Assumptions and Constraints: + * + * Copyright (c) 2012-2013 Cisco and/or its affiliates. + * 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 __TCP_HEADER_DEFINITIONS_H__ +#define __TCP_HEADER_DEFINITIONS_H__ + +/* + * A general list of Layer 3 protocols, used by many Layer 2 encaps. + * + * formerly: + * TYPE_IP TYPE_IP10MB + * TYPE_ARP TYPE_RFC826_ARP + * TYPE_RARP TYPE_REVERSE_ARP + * TYPE_MPLS TYPE_TAGSWITCH + */ +#define TYPE_IP 0x0800 +#define TYPE_IP_V6 0x86DD +#define TYPE_ARP 0x0806 +#define TYPE_RARP 0x8035 +#define TYPE_MPLS 0x8847 +#define TYPE_CDP 0x2000 +#define TYPE_CGMP 0x2001 +#define TYPE_LACP 0x8808 /* 802.3ad */ +#define TYPE_CLNS 0xFEFE + +#define TYPE_PPPOE_SESSION 0x8864 /* PTA plus */ +#define TYPE_PPPOE_DISCOVERY 0x8863 /* PTA plus */ + +/* + * for atm arp handling + */ +#define IN_ATM_ARP_BIT 0x0008 + +/* + * The Layer 2 header structures. + */ + + +/* +** HDLC +*/ + +typedef struct hdlc_hdr_type { + u16 addr; + u16 type; + u8 data[0]; +} hdlc_hdr_type; + +#define HDLC_ADDR_CMD 0x0F00 +#define HDLC_HDR_LEN 4 +#define HDLC_BROADCAST_BIT 31 +#define TYPE_KEEP 0x8035 + +#define HDLC_CLNS (HDLC_ADDR_CMD<<16|TYPE_CLNS) +#define HDLC_CDP (HDLC_ADDR_CMD<<16|TYPE_CDP) +#define HDLC_MPLS (HDLC_ADDR_CMD<<16|TYPE_MPLS) +#define HDLC_IP (HDLC_ADDR_CMD<<16|TYPE_IP) +#define HDLC_IP_V6 (HDLC_ADDR_CMD<<16|TYPE_IP_V6) +#define HDLC_KEEPALIVE_CMD (HDLC_ADDR_CMD<<16|TYPE_KEEP) + +/* +** PPP +*/ + +typedef struct ppp_comp_hdr_type { + union { + u8 ppp_u8[4]; + u16 ppp_u16[2]; + u32 ppp_u32; + } ppp_comp_u; +} ppp_comp_hdr_type; + +#define PPP_STATION 0xFF03 +#define PPP_STATION_LEN 0x2 +#define PPP_ENDPROTO 0x01 +#define PPP_NOT_ENDPROTO 0xfffffffe +#define PPP_CONTROL_PROTOCOL_MASK 0x8000 +#define PPP_CONTROL_PROTOCOL_BIT 15 +#define PPP_CSCO_LEN 4 +#define PPP_RFC1661_LEN 2 +#define PPP_RFC1661_COMP_LEN 1 + +#define TYPE_PPP_IP 0x0021 +#define TYPE_PPP_IP_V6 0x0057 +#define TYPE_PPP_MPLS_UNICAST 0x0281 +#define TYPE_PPP_MPLS_CONTROL 0x8281 +#define TYPE_PPP_CLNS 0x0023 +#define TYPE_PPP_CDP 0x0207 + +#define TYPE_PPP_IPCP 0x8021 +#define TYPE_PPP_LCP 0xC021 +#define TYPE_PPP_PAP 0xC023 +#define TYPE_PPP_LQR 0xC025 +#define TYPE_PPP_CHAP 0xC223 + + +#define TYPE_PPP_LCP_ECHO_REQUEST 0x09 +/* +** MultiLink PPP +*/ + +#define MLPPP_FLAGS_FIELD_LEN 4 +#define MLPPP_BEGIN_MASK 0x80000000 +#define MLPPP_END_MASK 0x40000000 +#define MLPPP_BEGIN_END_MASK (MLPPP_BEGIN_MASK|MLPPP_END_MASK) +#define MLPPP_BEGIN_END_SHIFT 30 +#define MLPPP_SEQUENCE_NUM_MASK 0x00FFFFFF +#define MLPPP_MC_CLASS_ID_MASK 0x3C000000 +#define MLPPP_MC_CLASS_SHIFT 26 + +#define TYPE_PPP_MULTILINK 0x003D + +/* these are needed in the micro-code, for optimizations */ +#define TYPE_PPP_FULL_IP_4 0xff030021 +#define TYPE_PPP_FULL_IP_3 0xff0321 +#define TYPE_PPP_FULL_IP_2 0x0021 +#define TYPE_PPP_FULL_IP_1 0x21 + +#define MLPPP_BEGIN_END_MASK_BYTE 0xC0 +#define MLPPP_BEGIN_BIT 7 +#define MLPPP_END_BIT 6 +#define MLPPP_MC_CLASS_ID_MASK_BYTE 0x3C +#define MLPPP_MC_CLASS_ID_SHIFT_BYTE 2 + +#define MLPOA_BEGIN_END_SHIFT 24 + +/* +** Ethernet ARPA +*/ + + +typedef struct ethernet_arpa_hdr_type { + u8 daddr[6]; + u8 saddr[6]; + u16 type; + u8 data[0]; +} ethernet_arpa_hdr_type; + +typedef struct extension_802p3_type { + u16 type; + u8 ctl; + u8 data[0]; +} extension_802p3_type; + +typedef struct ethernet_802p3_hdr_type { + u8 daddr[6]; + u8 saddr[6]; + u16 length; + extension_802p3_type extension; +} ethernet_802p3_hdr_type; + + +typedef struct ethernet_vlan_802p3_hdr_type { + u8 daddr[6]; + u8 saddr[6]; + u16 type1; + u16 vlan_id; + u16 length; + extension_802p3_type extension; +} ethernet_vlan_802p3_hdr_type; + +#define MIN_ETHERNET_PKT_LEN 60 +#define MAX_ETHERNET_PKT_LEN 1500 +#define ETHERNET_ARPA_HDR_LEN 14 +#define ETHERNET_TYPE_FIELD_SIZE 2 + + +/* +** Ethernet 802.1q (VLAN) +*/ + +typedef struct ethernet_vlan_hdr_type { + u8 dest_addr[6]; + u8 src_addr[6]; + u16 type1; + u16 vlan_hdr; + u16 type2; + u8 data[0]; +} ethernet_vlan_hdr_type; + + +/* +** Ethernet 802.1.q-in-q (QinQ) +*/ + +typedef struct ethernet_qinq_hdr_type { + u8 dest_addr[6]; + u8 src_addr[6]; + u16 type1; + u16 vlan_hdr1; + u16 type2; + u16 vlan_hdr2; + u16 type3; + u8 data[0]; +} ethernet_qinq_hdr_type; + + +/* +** Ethernet 802.3ad EtherChannel control +*/ + +typedef struct ethernet_lacp_hdr_type { + u8 daddr[6]; + u8 saddr[6]; + u16 type; + u16 LAcmd; + u8 data[0]; +} ethernet_lacp_hdr_type; + + +/* +** Ethernet 802.1 Bridge (spanning tree) PDU +*/ + +typedef struct ethernet_bpdu_hdr_type { + u8 daddr[6]; + u8 saddr[6]; + u8 dsap; + u8 ssap; + u8 control; + u8 more[0]; +} ethernet_bpdu_hdr_type; + +#define ETH_BPDU_DSAP 0x42 +#define ETH_BPDU_SSAP 0x42 +#define ETH_BPDU_CONTROL 0x03 +#define ETH_BPDU_MATCH 0x424203 + + +/************************************************************/ +/* PTA PLUS ETHERNET ENCAPSULATIONS */ +/* + * PPPoEoARPA 20 bytes + */ +typedef struct ethernet_pppoe_arpa_hdr_type { + u8 daddr[6]; + u8 saddr[6]; + u16 type; + /* pppoe hdr at begining of enet payload */ + u16 vtc; /* version(4b), type(4b) and code(8b) fields */ + u16 sid; + u16 len; + u8 ppp_header[0]; /* PPP header start, no ff03 field present */ +} ethernet_pppoe_arpa_hdr_type; + +typedef struct pppoe_hdr_type { + /* pppoe hdr at begining of enet payload */ + u16 vtc; /* version(4b), type(4b) and code(8b) fields */ + u16 sid; + u16 len; + u8 ppp_header[0]; /* PPP header start, no ff03 field present */ +} pppoe_hdr_type; + +/* +** PPPoEoVLAN (802.1p or 802.1q) 24 bytes +*/ +typedef struct ethernet_pppoe_vlan_hdr_type { + u8 dest_addr[6]; + u8 src_addr[6]; + u16 type1; + u16 vlan_hdr; + u16 type2; + /* pppoe hdr at begining of enet payload */ + u16 vtc; /* version(4b), type(4b) and code(8b) fields */ + u16 sid; + u16 len; + u8 ppp_header[0]; /* PPP header start, no ff03 field present */ +} ethernet_pppoe_vlan_hdr_type; + +/* +** PPPoEoQinQ 28 bytes +*/ +typedef struct ethernet_pppoe_qinq_hdr_type { + u8 dest_addr[6]; + u8 src_addr[6]; + u16 type1; + u16 vlan_hdr1; + u16 type2; + u16 vlan_hdr2; + u16 type3; + /* pppoe hdr at begining of enet payload */ + u16 vtc; /* version(4b), type(4b) and code(8b) fields */ + u16 sid; + u16 len; + u8 ppp_header[0]; /* PPP header start, no ff03 field present */ +} ethernet_pppoe_qinq_hdr_type; + +#define ETH_PPPOE_ARPA_HDR_LEN sizeof(ethernet_pppoe_arpa_hdr_type) +#define ETH_PPPOE_VLAN_HDR_LEN sizeof(ethernet_pppoe_vlan_hdr_type) +#define ETH_PPPOE_QINQ_HDR_LEN sizeof(ethernet_pppoe_qinq_hdr_type) +#define PPPOE_HDR_LEN 6 +/* End PTA PLUS ETHERNET ENCAPSULATIONS */ +/****************************************************************/ + + + +#define TYPE_DOT1Q 0x8100 +#define DOT1Q_HDR_LEN 18 +#define DOT1Q_VLAN_ID_MASK 0x0FFF +#define DOT1Q_VLAN_ID_RES_0 0x0000 +#define DOT1Q_VLAN_ID_RES_4095 0x0FFF +#define DOT1Q_ARPA_INDEX DOT1Q_VLAN_ID_RES_0 + +#define TYPE_QINQ_91 0x9100 +#define TYPE_QINQ_92 0x9200 +#define TYPE_QINQ_88A8 0x88A8 +#define QINQ_HDR_LEN 22 + +/* + * 802.1p support + */ +#define DOT1P_VLAN_COS_MASK 0xE000 +#define DOT1P_VLAN_COS_SHIFT 13 +#define DOT1P_MAX_COS_VALUE 7 + +/* +** Frame Relay +*/ + +/* + * formerly: + * TYPE_FR_IETF_IPV4 ENCAPS_FR_IETF + * TYPE_FR_CISCO_IPV4 ENCAPS_FR_CISCO + * TYPE_FR_ISIS ENCAPS_FR_ISIS + * + * FR_LMI_DLCI_CISCO LMI_DLCI_CISCO + * FR_LMI_DLCI_IETF LMI_DLCI_ITUANSI + */ + +typedef struct frame_relay_hdr_type { + u16 address; + u16 control_nlpid; + u8 data[0]; +} frame_relay_hdr_type; + +typedef struct fr_snap_hdr_type { + u16 address; + u8 control; + u8 pad; + u8 nlpid; + u8 oui[3]; + u16 protocol_id; +} fr_snap_hdr_type; + +#define FR_ADDR_LEN 2 +#define FR_CTL_NLPID_LEN 2 +#define FR_HDR_LEN (FR_ADDR_LEN+FR_CTL_NLPID_LEN) + +/* + * These defines are for the FR-SNAP header. + * The SNAP header is set up solely so that we can + * identify ARP packets, which look like this: + * + * control pad nlpid oui protocol_id + * 03 00 80 00 00 00 0806 + */ +#define FR_ARP_CONTROL 0x03 +#define FR_ARP_PAD 0x00 +#define FR_ARP_NLPID 0x80 +#define FR_ARP_OUI_0 0x00 +#define FR_ARP_OUI_1 0x00 +#define FR_ARP_OUI_2 0x00 +/* + * these are used only in the tmc code + */ +#define FR_NLPID_OUI_LEN 4 +#define FR_ARP_CONTROL_PAD 0x0300 +#define FR_ARP_NLPID_OUI 0x80000000 + + +#define FR_DLCI_UPPER_MASK 0xFC00 +#define FR_DLCI_UPPER_SHIFT 6 +#define FR_DLCI_LOWER_MASK 0x00F0 +#define FR_DLCI_LOWER_SHIFT 4 + +/* + * Defines for converting a DLCI for insertion into a synthesized FR address + * field for FRoMPLS disposition. + + * bit 8 7 6 5 4 3 2 1 + * +-------------------------------+ + * | Flag | + * | 0 1 1 1 1 1 1 0 | + * +-------------------------------+ + * | Upper DLCI |C/R| 0 | + * +-------------------------------+ + * | Lower DLCI | F | B | DE| 1 | + * +-------------------------------+ + * | | + * :Frame relay information field : + * : (i.e.payload) : + * | | + * +-------------------------------+ + * | FCS (2 or 4 octets) | + * | | + * +-------------------------------+ + * | Flag | + * | 0 1 1 1 1 1 1 0 | + * +-------------------------------+ + * + * a-With 10 bits for the DLCI + */ +#define FR_DLCI_TO_HDR_UPPER_MASK 0x3f0 +#define FR_DLCI_TO_HDR_UPPER_SHIFT (10-4) +#define FR_DLCI_TO_HDR_LOWER_MASK 0xf +#define FR_DLCI_TO_HDR_LOWER_SHIFT 4 + +#define TYPE_FR_IETF_IP 0x03CC +#define TYPE_FR_IETF_IP_V6 0x038E +#define TYPE_FR_CISCO_IP 0x0800 +#define TYPE_FR_CISCO_IP_V6 0x86DD +#define TYPE_FR_ISIS 0x0383 +#define TYPE_FR_SNAP0PAD 0x0380 +#define TYPE_FR_SNAP1PAD 0x0300 +#define TYPE_FR_FRF12 0x03B1 +#define TYPE_FR_MLP 0x03CF +#define TYPE_FR_EEK 0x8037 + +#define FR_LMI_DLCI_CISCO 1023 +#define FR_LMI_DLCI_IETF 0 + +#define FR_NOT_NOT_NOT 0 +#define FR_NOT_NOT_DE 1 +#define FR_NOT_BECN_NOT 2 +#define FR_NOT_BECN_DE 3 +#define FR_FECN_NOT_NOT 4 +#define FR_FECN_NOT_DE 5 +#define FR_FECN_BECN_NOT 6 +#define FR_FECN_BECN_DE 7 + +#define FR_FECN_BECN_DE_MASK 0x000E +#define FR_FECN_BECN_DE_SHIFT 1 + +/* Address field extension bit for standard 2-byte FR address field */ +#define FR_EA1_MASK 0x0001 +#define FR_EA1_MASK_BIT 0 + +/* + * these are needed in the micro-code, for optimizations + */ + +/* the bit position (in the address field) of the LSB of the DLCI */ +#define FR_DLCI_LS_BIT 4 + + +/* +** +** MultiLink Frame Relay +** +*/ + +typedef struct mlfr_hdr_type { + u16 frag_hdr; + u16 address; + u16 control_nlpid; + u8 data[0]; +} mlfr_hdr_type; + +/* + * LIP frames have B, E and C set--the other + * bits in the frag_hdr field are irrelevant. + * + * NOTE: Injected LIP packets have a frag_hdr of 0xE100. + * + */ +#define MLFR_LIP_FRAME 0xE100 +#define MLFR_LIP_MASK 0xE000 +#define MLFR_FRAG_HDR_LEN 2 + +#define MLFR_BEGIN_MASK 0x8000 +#define MLFR_END_MASK 0x4000 +#define MLFR_BEGIN_END_MASK (MLFR_BEGIN_MASK|MLFR_END_MASK) +#define MLFR_BEGIN_END_SHIFT 14 + +#define MLFR_SEQ_NUM_HI_MASK 0x1E00 +#define MLFR_SEQ_NUM_HI_SHIFT 1 +#define MLFR_SEQ_NUM_LO_MASK 0x00FF + +/* + * these are needed in the micro-code, for optimizations + */ +#define MLFR_BEGIN_END_MASK_BYTE 0xC0 + + +/* + * FRF.12 definitions + */ +typedef struct frf12_hdr_type_ { + u16 address; + u16 control_nlpid; + u16 frag_hdr; + u8 data[0]; +} frf12_hdr_type; + +#define FRF12_FRAG_HDR_LEN sizeof(frf12_hdr_type) + +#define FRF12_BEGIN_MASK 0x8000 +#define FRF12_END_MASK 0x4000 +#define FRF12_BEGIN_END_MASK (FRF12_BEGIN_MASK|FRF12_END_MASK) +#define FRF12_BEGIN_END_SHIFT 8 + +#define FRF12_SEQ_NUM_HI_MASK 0x1E00 +#define FRF12_SEQ_NUM_HI_SHIFT 1 +#define FRF12_SEQ_NUM_LO_MASK 0x00FF +#define FRF12_BEGIN_END_MASK_BYTE 0xC0 + + + +/* +** +** MLP over Frame Relay +** The ppp hdr can be either a +** an MLP hdr or a PPP hdr +** +** MLP can be compressed or not: +** a) 0xff03003d +** b) 0x003d +** c) 0x3d +** followed by: +** 1 byte with begin/end bits +** 3 bytes of a sequence # +** +** PPP can be also be compressed or not. +** Only these will be fwded: +** a) 0xff030021 +** b) 0xff0321 +** c) 0x0021 +** d) 0x21 +** +** +*/ +typedef struct mlpofr_hdr_type { + u16 address; + u16 control_nlpid; + u8 ppp_header[0]; +} mlpofr_hdr_type; + +/* +** ATM - +*/ + +/* + * channel_handle is defined as follows: + * + * bits 15 = reserved (must be 0) + * bits 14 - 0 = channel handle + * + * + * flags is a bitfield defined as follows: + * + * bits 15 - 13 = proto (PPPoA RFC1661 = 0, + * PPPoE = 1, + * RBE = 2, + * PPPoA Cisco = 3, + * MLPoATM RFC1661 = 4, + * MLPoATM Cisco = 5, + * Reserved = 6-7) + * bit 12 = encap (MUX=0, + * SNAP=1) + * bits 11 - 6 = reserved (must be 0) + * bits 5 - 3 = pkt_type (AAL5 pkt = 0, + * Raw cell (includes F4 OAM) = 1, + * F5 segment OAM cell = 2 + * F5 end-to-end OAM cell = 3 + * Reserved = 4-7) + * bit 2 = EFCI (congestion indication) + * bit 1 = reserved (must be 0) + * bit 0 = CLP (cell loss priority) + */ + +typedef struct apollo_atm_generic_hdr_type { + u16 channel_handle; + u16 flags; +} apollo_atm_generic_hdr_type; + +typedef struct apollo_atm_aal5_snap_hdr_type { + u16 channel_handle; + u16 flags; + u8 dsap; + u8 ssap; + u8 control; + u8 oui[3]; + u16 type; + u8 data[0]; +} apollo_atm_aal5_snap_hdr_type; + +typedef struct atm_aal5_snap_hdr_type { + u8 dsap; + u8 ssap; + u8 control; + u8 oui[3]; + u16 pid; + u16 pad; + u8 data[0]; +} atm_aal5_snap_hdr_type; + + +typedef struct apollo_atm_aal5_snap_hdr1_type { + u16 channel_handle; + u16 flags; + u8 dsap; + u8 ssap; + u8 control; + u8 oui0; + u8 oui1; + u8 oui2; + u16 type; + u8 data[0]; +} apollo_atm_aal5_snap_hdr1_type; + +typedef struct apollo_atm_aal5_clns_hdr_type { + u16 channel_handle; + u16 flags; + u16 type; + u16 data; +} apollo_atm_aal5_clns_hdr_type; + +typedef struct apollo_atm_aal5_ilmi_hdr_type { + u16 channel_handle; + u16 flags; + u8 data[0]; +} apollo_atm_aal5_ilmi_hdr_type; + +typedef struct apollo_atm_aal5_mux_hdr_type { + u16 channel_handle; + u16 flags; + u8 data[0]; +} apollo_atm_aal5_mux_hdr_type; + +typedef struct apollo_atm_oam_f4_hdr_type { + u16 channel_handle; + u16 flags; + /* + * gcf_vpi_vci_pt_clp is a bitfield defined as follows: + * + * bits 31 - 28 = GCF + * bits 27 - 20 = VPI + * bits 19 - 4 = VCI + * bits 3 - 1 = PT + * bit 0 = CLP + */ + u32 gcf_vpi_vci_pt_clp; + u8 data[0]; +} apollo_atm_oam_f4_hdr_type; + +#define APOLLO_ATM_OAM_F4_HDR_PT_MASK 0xE +#define APOLLO_ATM_OAM_F4_HDR_PT_SHIFT 1 + +typedef struct apollo_atm_oam_f5_hdr_type { + u16 channel_handle; + u16 flags; + u8 data[0]; +} apollo_atm_oam_f5_hdr_type; + +#define APOLLO_IRONBUS_EXT_LESS_PROTO 0xFFFF0FFF +#define APOLLO_CHANNEL_HANDLE_MASK 0xFFFF +#define APOLLO_PKT_TYPE_MASK 0x0038 +#define APOLLO_PKT_TYPE_SHIFT 3 +#define APOLLO_FLAG_CLP_MASK 0x0001 +#define APOLLO_FLAG_CLP_BIT 0 + +#define APOLLO_CHANNEL_HANDLE_RES_0 0x0000 +/* + * The 1 byte HEC field is removed by the line card. + */ +#define APOLLO_F4_RX_CELL_SIZE 52 +#define APOLLO_F5_RX_CELL_SIZE 52 + +#define APOLLO_ATM_PACKET_TYPE_AAL5 0 +#define APOLLO_ATM_PACKET_TYPE_F4 1 +#define APOLLO_ATM_PACKET_TYPE_F5_SEG 2 +#define APOLLO_ATM_PACKET_TYPE_F5_E_TO_E 3 +#define APOLLO_ATM_PACKET_TYPE_4 4 +#define APOLLO_ATM_PACKET_TYPE_5 5 +#define APOLLO_ATM_PACKET_TYPE_6 6 +#define APOLLO_ATM_PACKET_RESERVED 7 + +#define APOLLO_AAL5_MUX_IP_HDR_LEN 4 +#define APOLLO_AAL5_SNAP_HDR_LEN 12 + +#define APOLLO_RCV_IRON_BUS_EXT_LEN 4 +#define APOLLO_TX_IRON_BUS_EXT_LEN 8 + +/* + * MLPoA type definitions + */ +#define MLPOA_CISCO_HDR 0xFF03 +#define MLPOA_SNAP_HDR_LEN 4 +#define MLPOA_CISCO_HDR_LEN 2 + +/************************************************************/ +/* PTA PLUS ATM ENCAPSULATIONS */ + +/* RBE header 28 bytes*/ +typedef struct apollo_atm_aal5_llcsnap_rbe_hdr_type { + u16 channel_handle; + u16 flags; + u8 dsap; + u8 ssap; + u8 control; + u8 oui[3]; + u16 pid; + u16 pad; + /* enet header within */ + u8 daddr[6]; + u8 saddr[6]; + u16 type; + u8 data[0]; /* start of IP */ +} apollo_atm_aal5_llcsnap_rbe_hdr_type; + +/* PPPoEoA header 34 bytes*/ +typedef struct apollo_atm_aal5_llcsnap_pppoe_hdr_type { + u16 channel_handle; + u16 flags; + u8 dsap; + u8 ssap; + u8 control; + u8 oui[3]; + u16 pid; + u16 pad; + /* enet header within */ + u8 daddr[6]; + u8 saddr[6]; + u16 type; + /* pppoe hdr at begining of enet payload */ + u16 vtc; /* version(4b), type(4b) and code(8b) fields */ + u16 sid; + u16 len; + u8 ppp_header[0]; /* PPP header start, no ff03 field present */ +} apollo_atm_aal5_llcsnap_pppoe_hdr_type; + + +/* PPPoA MUX 4 bytes*/ +typedef struct apollo_atm_aal5_mux_pppoa_hdr_type { + u16 channel_handle; + u16 flags; + u8 ppp_header[0]; +} apollo_atm_aal5_mux_pppoa_hdr_type; + + +/* PPPoA SNAP LLC 8 bytes */ +typedef struct apollo_atm_aal5_llcsnap_pppoa_hdr_type { + u16 channel_handle; + u16 flags; + u8 dsap; + u8 ssap; + u8 control; + u8 nlpid; + u8 ppp_header[0]; +} apollo_atm_aal5_llcsnap_pppoa_hdr_type; + +/* MLPoA MUX (generic) */ +typedef struct apollo_atm_aal5_mux_mlpoa_hdr_type { + u16 channel_handle; + u16 flags; + u8 ppp_header[0]; +} apollo_atm_aal5_mux_mlpoa_hdr_type; + +/* MLPoA SNAP LLC */ +typedef struct apollo_atm_aal5_llcsnap_mlpoa_hdr_type { + u16 channel_handle; + u16 flags; + u8 dsap; + u8 ssap; + u8 control; + u8 nlpid; + u8 ppp_header[0]; +} apollo_atm_aal5_llcsnap_mlpoa_hdr_type; + + +#define PPPOA_SNAPLLC_HDR_LEN sizeof(apollo_atm_aal5_llcsnap_pppoa_hdr_type) +#define PPPOA_MUX_HDR_LEN sizeof(apollo_atm_aal5_mux_pppoa_hdr_type) +#define PPPOE_SNAPLLC_HDR_LEN sizeof(apollo_atm_aal5_llcsnap_pppoe_hdr_type) +#define RBE_SNAPLLC_HDR_LEN sizeof(apollo_atm_aal5_llcsnap_rbe_hdr_type) + +/* End PTA PLUS ATM ENCAPSULATIONS */ +/****************************************************************/ + +#define LLCSNAP_PID_DOT3_NOFCS 0x0007 + +/* +** the SNAP header +*/ + +/* + * Note that some of these definitions are split + * up along certain word or half word boundaries + * to help expediate the TMC code. + */ +#define LLC_SNAP_HDR_DSAP 0xAA +#define LLC_SNAP_HDR_SSAP 0xAA +#define LLC_SNAP_HDR_CONTROL 0x03 +#define LLC_SNAP_HDR_OUI_0 0x00 +#define LLC_SNAP_HDR_OUI_1 0x00 +#define LLC_SNAP_HDR_OUI_2 0x00 +#define LLC_SNAP_HDR_OUI_2_CDP 0x0C + +#define LLC_SNAP_HDR_DSAP_SSAP 0xAAAA +#define LLC_SNAP_HDR_DSAP_SSAP_CTRL_OUI0 0xAAAA0300 +#define LLC_SNAP_HDR_CONTROL_OUI 0x03000000 +#define LLC_SNAP_HDR_OUI1_OUI2_CDP 0x000C2000 + + + +/* +** SRP +*/ + +/* + * The v2_gen_hdr is a 2-byte field that contains the following: + * + * [ ttl | ring_id | mode | priority | parity ] + * bits 8 1 3 3 1 + */ +typedef struct srp_hdr_type { + u16 v2_gen_hdr; + u8 dest_addr[6]; + u8 src_addr[6]; + u16 protocol; + u8 data[0]; +} srp_hdr_type; + +#define SRP_HDR_LEN 16 + +#define SRP_IB_CHANNEL_CONTROL 0x0000 +#define SRP_IB_CHANNEL_DATA_HI 0x0001 +#define SRP_IB_CHANNEL_DATA_LO 0x0002 + +#define SRP_RING_ID_MASK 0x0080 +#define SRP_RING_ID_BIT 7 + +#define SRP_MODE_BITS_MASK 0x0070 +#define SRP_MODE_BITS_SHIFT 4 +#define SRP_MODE_CONTROL_TOPOLOGY 4 +#define SRP_MODE_CONTROL_IPS 5 +#define SRP_MODE_DATA 7 + +#define SRP_PRIORITY_BITS_MASK 0x000E +#define SRP_PRIORITY_BITS_SHIFT 1 +#define SRP_PRIORITY_HIGH 7 +#define SRP_PRIORITY_PAK_PRIORITY 6 + +/* this is for the tmc code */ +#define SRP_INV_PRIORITY_BITS_MASK 0xFFF1 + +#define SRP_PROT_CONTROL_TOPOLOGY 0x2007 +#define SRP_PROT_CONTROL_IPS 0x2007 + +/* this is for the tmc code */ +#define SRP_TRUE 1 +#define SRP_FALSE 0 + +/* +** MPLS +*/ +#define MPLS_EOS_BIT 0x00000100 +#define MPLS_EOS_SHIFT 8 +#define MPLS_LABEL_SIZE 4 +#define MAX_MPLS_LABEL_STACK 6 +#define MPLS_LABEL_MASK 0xfffff000 +#define MPLS_LABEL_SHIFT 12 +#define MPLS_TTL_MASK 0x000000ff +#define MPLS_EXP_MASK 0x00000e00 +#define MPLS_EXP_SHIFT 9 +#define MPLS_EXP_TTL_MASK 0x00000eff + + + +typedef union _layer2 { + hdlc_hdr_type hdlc; + ppp_comp_hdr_type ppp; + ethernet_arpa_hdr_type eth_arpa; + ethernet_vlan_hdr_type eth_vlan; + ethernet_qinq_hdr_type eth_qinq; + ethernet_lacp_hdr_type eth_lacp; + ethernet_bpdu_hdr_type eth_bpdu; + ethernet_802p3_hdr_type eth_802p3; + ethernet_vlan_802p3_hdr_type eth_vlan_802p3; + ethernet_pppoe_arpa_hdr_type eth_pppoe_arpa; /* PTA plus */ + ethernet_pppoe_vlan_hdr_type eth_pppoe_vlan; /* PTA plus */ + ethernet_pppoe_qinq_hdr_type eth_pppoe_qinq; /* PTA plus */ + frame_relay_hdr_type frame_relay; + fr_snap_hdr_type fr_snap; + mlfr_hdr_type mlfr; + mlpofr_hdr_type mlpofr; + frf12_hdr_type frf12; + apollo_atm_generic_hdr_type atm_generic; + apollo_atm_aal5_snap_hdr_type atm_aal5_snap; + apollo_atm_aal5_snap_hdr1_type atm_aal5_snap1; + apollo_atm_aal5_clns_hdr_type atm_aal5_clns; + apollo_atm_aal5_ilmi_hdr_type atm_aal5_ilmi; + apollo_atm_aal5_mux_hdr_type atm_aal5_mux; + apollo_atm_oam_f4_hdr_type atm_oam_f4; + apollo_atm_oam_f5_hdr_type atm_oam_f5; + apollo_atm_aal5_llcsnap_rbe_hdr_type atm_aal5_rbe_snapllc; /* PTA plus */ + apollo_atm_aal5_llcsnap_pppoe_hdr_type atm_aal5_pppoe_snapllc; /* PTA plus */ + apollo_atm_aal5_mux_pppoa_hdr_type atm_aal5_pppoa_mux; /* PTA plus */ + apollo_atm_aal5_llcsnap_pppoa_hdr_type atm_aal5_pppoa_snapllc; /* PTA plus */ + apollo_atm_aal5_mux_mlpoa_hdr_type mlpoa_generic; + apollo_atm_aal5_llcsnap_mlpoa_hdr_type mlpoa_snapllc; + srp_hdr_type srp; +} layer2_t; + +/* + * Define the Common OAM cell format - F4 & F5 cells + * For F4 cells: + * VPI == User VPI + * VCI == (3 == Segment), (4 == End-to-End) + * + * For F5 cells: + * VPI == User VPI + * VCI == User VCI + * PT == (100 == Segment, 101 == End-to-End) + * + * OAM Cell Type & Function Type: + * + * OAM_TYPE = (0001 == Fault management) + * OAM_FUNC == (0000 == AIS, 0001 == RDI, 0100 == CC, + * 1000 == loopback) + * + * OAM_TYPE = (0010 == Performance management) + * OAM_FUNC == (0000 == Forward Monitoring(FM), + * 0001 == Backward monitoring(BR), + * 0010 == Monitoring & reporting (FM+BR)) + * + * OAM_TYPE = (1000 == Activation/Deactivation) + * OAM_FUNC == (0000 == Performance Monitoring, + * 0001 == Continuity Check) + * + * OAM_TYPE = (1111 == Sytem Management) + * OAM_FUNC == (0001 == Security - non-real-time, + * 0010 == Security - real-time) + * + */ +#define ATM_OAM_FAULT_MGMT 0x1 /* OAM Fault mgmt. code */ +#define ATM_OAM_PRFRM_MGMT 0x2 /* performance mgmt code */ +#define ATM_OAM_ACT_DEACT 0x8 /* OAM Activation/Deactivation + code */ +#define ATM_OAM_SYSTEM_MGMT 0xF /* System Management code */ + +#define ATM_OAM_AIS_FUNC 0x0 /* AIS function type */ +#define ATM_OAM_RDI_FUNC 0x1 /* RDI function type */ +#define ATM_OAM_CC_FUNC 0x4 /* OAM CC FM function code */ +#define ATM_OAM_LOOP_FUNC 0x8 /* Loopback function type */ + +#define ATM_OAM_F5_SEGMENT 0x4 /* Segment function */ +#define ATM_OAM_F5_ENDTOEND 0x5 /* End-to-End function */ +#define ATM_OAM_F4_SEGMENT 0x3 /* Segment function */ +#define ATM_OAM_F4_ENDTOEND 0x4 /* End-to-End function */ +#define ATM_OAM_F4_PTI_ZERO 0x0 /* PTI=0 for F4 OAM */ + +typedef struct atm_oam_hdr_t_ { + unsigned oam_gfc:4; /* GFC */ + unsigned oam_vpi:8; /* VPI */ + unsigned oam_vci_ms:4; /* VCI (Most Significant Bits) */ + + unsigned oam_vci_ls:12; /* VCI (Least Significant Bits) */ + unsigned oam_pt:3; /* Payload Type */ + unsigned oam_clp:1; /* Cell Loss Priority */ + u8 data[0]; +} atm_oam_hdr_t; + +typedef struct atm_oam_type_func_t_ { + u8 oam_type:4; + u8 oam_func:4; + u8 data[0]; +} atm_oam_type_func_t; + +/* +** IP Version 4 header +*/ + +/* + * version_hdr_len_words [7-4] IP Header Version + * [3-0] IP Header Length in 32-bit words + * tos Type of Service + * total_len_bytes Total IP datagram length in bytes + * (including IP header) + * identification Unique fragmentation identifier + * frag_flags_offset [15-13] Fragmentation flags + * [12-0] Fragmentation Offset + * ttl Time To Live + * protocol_id Protocol Identifier + * checksum 16-bit 1's complement IP Header checksum + * src_addr IP Source Address + * dest_addr IP Destination Address + */ +typedef struct ipv4_header { + u8 version_hdr_len_words; + u8 tos; + u16 total_len_bytes; + u16 identification; + u16 frag_flags_offset; + u8 ttl; + u8 protocol; + u16 checksum; + u32 src_addr; + u32 dest_addr; + u8 data[0]; +} ipv4_header; + +/*OPTIONS PACKET TYPE + * +-+-+-+-+-+-+-+-+ + * |C| CL| OP | + * +-+-+-+-+-+-+-+-+ + */ +typedef struct ipv4_options { + u8 copy :1 ; + u8 op_class :2 ; + u8 option :5 ; + u8 pad ; +}ipv4_options; + +#define LOOSE_SOURCE_ROUTE 131 +#define STRICT_SOURCE_ROUTE 137 +#define IPV4_NO_OPTIONS_HDR_LEN (sizeof(ipv4_header)) +#define IPV4_VERSION 4 +#define IPV4_HEADER_LENGTH_WORDS 5 +#define IPV4_VERSION_HDR_LEN_FIELD ((u8) 0x45) +#define IPV4_HEADER_LENGTH_WORDS 5 +#define IPV4_MIN_HEADER_LENGTH_BYTES 20 +#define IP_HDR_LEN sizeof(ipv4_header) +#define IPV4_VERSION_VALUE_SHIFT 4 + +#define IPV4_FRAG_OFFSET_MASK (0x1fff) +#define IPV4_FRAG_MF_MASK (0x2000) +#define IPV4_FRAG_MF_SHIFT (13) + +/* 0.0.0.0 */ +#define IP_BOOTP_SOURCE_ADDRESS 0 +/* 255.255.255.255 */ +#define IP_LIMITED_BROADCAST_ADDRESS 0xFFFFFFFF + +/* + * IPv4 header - version & length fields + */ +#define IP_VER_LEN 0x45 +#define IP_VER 0x4 +#define IP_MIN_LEN 0x5 +#define IP_VER_MASK 0xf0 +#define IP_LEN_MASK 0x0f + +/* + * IPv4 header - TOS field + */ +#define PS_IP_TOS_MASK 0xff +#define IP_PRECEDENCE_SHIFT 5 /* shift value up to precedence bits */ +#define IP_DSCP_SHIFT 2 /* shift value up to dscp bits */ + +#define IP_TOS_PRECEDENCE 0xe0 /* mask of precedence in tos byte */ +#define IP_TOS_NO_PRECEDENCE 0x1f +#define IP_TOS_LOW_DELAY 8 /* values must be shifted 1 bit */ +#define IP_TOS_HIGH_TPUT 4 /* before using */ +#define IP_TOS_HIGH_RELY 2 +#define IP_TOS_LOW_COST 1 +#define IP_TOS_NORMAL 0 +#define IP_TOS_MASK 0x1e /* mask of tos in tos byte */ +#define IP_TOS_MBZ_MASK 0x01 /* mask for MZB bit in tos byte */ +#define IP_TOS_DSCP 0xfc /* mask for dscp in tos byte */ +#define IP_TOS_NO_DSCP 0x03 + +#define IP_TOS_METRIC_TYPES 8 +#define IP_TOS_SHIFT 1 + +#define IP_TOS_PRECEDENCE_MASK (IP_TOS_PRECEDENCE | IP_TOS_MASK) + +/* + * IP TOS Precedence values (High order 3 bits) + */ +#define TOS_PREC_NET_CONTROL 0xe0 +#define TOS_PREC_INET_CONTROL 0xc0 +#define TOS_PREC_CRIT_ECP 0xa0 +#define TOS_PREC_FLASH_OVER 0x80 +#define TOS_PREC_FLASH 0x60 +#define TOS_PREC_IMMEDIATE 0x40 +#define TOS_PREC_PRIORITY 0x20 +#define TOS_PREC_ROUTINE 0x00 +#define TOS_PREC_ILLEGAL 0xff /* invalid precedence value */ + +#define TOS_PREC_NET_CONTROL_NUM 7 +#define TOS_PREC_INET_CONTROL_NUM 6 +#define TOS_PREC_CRIT_ECP_NUM 5 +#define TOS_PREC_FLASH_OVER_NUM 4 +#define TOS_PREC_FLASH_NUM 3 +#define TOS_PREC_IMMEDIATE_NUM 2 +#define TOS_PREC_PRIORITY_NUM 1 +#define TOS_PREC_ROUTINE_NUM 0 + + + +/* + * IPv4 header - flags and fragment offset fields + */ +#define IP_FRAG_OFFSET_MASK 0x1fff + + +#define IP_FRAG_MORE_MASK 0x2000 +#define IP_FRAG_DF_MASK 0x4000 +#define IP_FRAG_UNDEF_MASK 0x8000 +#define IP_FRAG_NO_DF_SET 0x0000 + +/* bit definitions for fragment flags */ +#define IP_FRAG_MORE_BIT 13 +#define IP_FRAG_DF_BIT 14 +#define IP_FRAG_UNDEF_BIT 15 + +/* + * IPv4 header - TTL field + */ +#define TTL_DEFAULT 255 +#define TTL_1 1 +#define TTL_2 2 +#define TTL_255 255 + + +/* + * IPv4 header - protocol field + * + * ICMP_PROT 1 ICMP + * IGMP_PROT 2 group management + * GGP_PROT 3 GGP + * IPINIP_PROT 4 IPv4 in IPv4 encapsulation + * TCP_PROT 6 TCP + * EGP_PROT 8 EGP + * IGRP_PROT 9 IGRP + * UDP_PROT 17 UDP + * HMP_PROT 20 HMP + * RDP_PROT 27 RDP + * IPV6_INIP_PROT 41 IPV6 in IPv4 encapsulation + * RSVP_PROT 46 RSVP + * GRE_PROT 47 GRE + * ESP_PROT 50 ESP + * AHP_PROT 51 AHP + * SDNS0_PROT 53 SNDS + * NHRP_PROT 54 NHRP + * SDNS1_PROT 55 SDNS1 + * HELLO_PROT 63 HELLO + * ND_PROT 77 ND + * EONIP_PROT 80 CLNS over IP + * VINES_PROT 83 Banyan Vines + * NEWIGRP_PROT 88 IGRP + * OSPF_PROT 89 OSPF + * FST_RSRB_PROT 90 RSRB + * FST_DLSW_PROT 91 DLSW + * NOSIP_PROT 94 KA9Q/NOS compatible IP over IP + * PIM_PROT 103 PIMv2 + * PCP_PROT 108 PCP + * PGM_PROT 113 PGM + * MAX_PROT 113 maximum protocol number in the above list, + * used in creating case registry + */ +#define ICMP_PROT 1 +#define IGMP_PROT 2 +#define GGP_PROT 3 +#define IPINIP_PROT 4 +#define TCP_PROT 6 +#define EGP_PROT 8 +#define IGRP_PROT 9 +#define UDP_PROT 17 +#define HMP_PROT 20 +#define RDP_PROT 27 +#define IPV6_INIP_PROT 41 +#define RSVP_PROT 46 +#define GRE_PROT 47 +#define ESP_PROT 50 +#define AHP_PROT 51 +#define SDNS0_PROT 53 +#define NHRP_PROT 54 +#define SDNS1_PROT 55 +#define HELLO_PROT 63 +#define ND_PROT 77 +#define EONIP_PROT 80 +#define VINES_PROT 83 +#define NEWIGRP_PROT 88 +#define OSPF_PROT 89 +#define FST_RSRB_PROT 90 +#define FST_DLSW_PROT 91 +#define NOSIP_PROT 94 +#define PIM_PROT 103 +#define PCP_PROT 108 +#define PGM_PROT 113 +#define MAX_PROT 113 + +/*Well Known Application ports */ +#define FTP_PORT 21 /* For control connection */ +/* + * TCP header + */ +typedef struct tcp_hdr_type { + u16 src_port; + u16 dest_port; + u32 seq_num; + u32 ack_num; + u8 hdr_len; + u8 flags; + u16 window_size; + u16 tcp_checksum; + u16 urgent_pointer; + u8 option_data[0]; +} tcp_hdr_type; + +#define TCP_FLAG_FIN 0x01 +#define TCP_FLAG_SYN 0x02 +#define TCP_FLAG_RST 0x04 +#define TCP_FLAG_PUSH 0x08 +#define TCP_FLAG_ACK 0x10 +#define TCP_FLAG_URG 0x20 +#define TCP_FLAG_ECE 0x40 +#define TCP_FLAG_CWR 0x80 + +/* + * TCP Option + */ +typedef struct tcp_option_s { + u8 kind; + u8 length; + u8 data[0]; +} tcp_option_t; + +#define TCP_END_OPTIONS_LIST 0 +#define TCP_OPTION_NOP 1 +#define TCP_OPTION_MSS 2 +#define TCP_OPTION_WINDOW_SCALE 3 +#define TCP_OPTION_SACK_PERMITTED 4 +#define TCP_OPTION_SACK_DATA 5 +#define TCP_OPTION_ECHO 6 +#define TCP_OPTION_ECHO_REPLY 7 +#define TCP_OPTION_TSOPT 8 +/* + 9 2 Partial Order Connection Permitted. RFC 1693 + 10 3 Partial Order Service Profile. RFC 1693 + 11 6 CC, Connection Count. RFC 1644 + 12 6 CC.NEW RFC 1644 + 13 6 CC.ECHO RFC 1644 + 14 3 TCP Alternate Checksum Request. RFC 1146 + 15 Variable. TCP Alternate Checksum Data. RFC 1146 + 16 Skeeter. + 17 Bubba. + 18 3 Trailer Checksum Option. +*/ +#define TCP_OPTION_MD5_SIGNATURE 19 +/* + 20 SCPS Capabilities. + 21 Selective Negative Acknowledgements. + 22 Record Boundaries. + 23 Corruption experienced. + 24 SNAP. + 25 + 26 TCP Compression Filter. +*/ +#define TCP_OPTION_QUICK_START 27 + +#define TCP_OPTION_NUM_MAX 27 + +#ifdef TARGET_CISCO +#define tcp_printf(format_str, params...) //printf(format_str, ## params) +#else +#define tcp_printf(format_str, params...) printf(format_str, ## params) +#endif + +typedef struct udp_hdr_type { + u16 src_port; + u16 dest_port; + u16 udp_length; + u16 udp_checksum; +} udp_hdr_type_t; + +#define TYPE_IPV6 0x86dd +#define TYPE_IPV4 0x0800 + +/* + * version_trafficclass_flowlabel [31:28] IP Header Version, + [27:20] traffic_class, + [19:0] flow_label[20] + * payload_length Length of packet in bytes excluding header size(s) + * next_header Identifies the type of header following the IPv6 header + * hop_limit Decremented by 1 by each forwarding node, packet discarded when zero + * src_addr IPv6 Source Address + * dst_addr IPv6 Destination Address + */ +typedef struct ipv6_header { + u32 version_trafficclass_flowlabel; + u16 payload_length; + u8 next_header; + u8 hop_limit; + u32 src_addr[4]; + u32 dst_addr[4]; + u8 data[0]; +} ipv6_header_t; + +#define IPV6_HDR_LEN 40 +#define IPV6_HDR_LEN_WORDS 10 +#define IPV6_FLABLE_MASK 0x000FFFFF +#define IPV6_MIN_PATH_MTU (1280) + +#define IPV6_GET_IP_VER(ih) ((clib_net_to_host_u32((ih) \ + ->version_trafficclass_flowlabel) >> 28) & 0xf) +#define IPV6_GET_TOS(ih) ((clib_net_to_host_u32((ih) \ + ->version_trafficclass_flowlabel) >> 20) & 0xff) +#define IPV6_GET_FLOW_LABEL(ih) ((clib_net_to_host_u32((ih) \ + ->version_trafficclass_flowlabel)) & 0xfffff) + +#define IPV6_VERSION_VALUE (6) +#define IPV6_VERSION_VALUE_SHIFT (28) +#define IPV6_TRAFFIC_CLASS_VALUE_SHIFT (20) +#define IPV6_TRAFFIC_CLASS_VALUE_MASK (0xff) + +#define IPV6_PROTO_HOPOPTS 0 +#define IPV6_PROTO_TCP 6 +#define IPV6_PROTO_UDP 17 +#define IPV6_PROTO_IPV6 41 +#define IPV6_PROTO_ROUTING 43 +#define IPV6_PROTO_FRAGMENT 44 +#define IPV6_PROTO_DESTOPTS 60 +#define IPV6_PROTO_ESP 50 +#define IPV6_PROTO_AH 51 +#define IPV6_PROTO_ICMPV6 58 +#define IPV6_PROTO_NONE 59 + +/* standard v6 extension header are 2 tytes + * one byte next header + * one byte header length + */ + +typedef struct ipv6_frag_header { + u8 next_header; + u8 reserved; + u16 frag_offset_res_m; + u32 identification; +} ipv6_frag_header_t; + +#define IPV6_FRAG_HDR_LEN (sizeof(ipv6_frag_header_t)) + +#define IPV6_FRAG_OFFSET_MASK (0xFFF8) +#define IPV6_FRAG_OFFSET_SHIFT (3) +#define IPV6_FRAG_MORE_FRAG_MASK (0x0001) + +#define IPV6_TOS_SHIFT 20 +#define IPV6_TOS_SHIFT_HLF_WD 4 +#define IPV6_NEXT_HDR_SHIFT 8 + +typedef struct ipv6_routing_header { + u8 next_header; + u8 hdr_ext_len; + u8 routing_type; + u8 segments_left; + u8 data[0]; +} ipv6_routing_header_t; +#define IPV6_ROUTING_HDR_LEN (sizeof(ipv6_routing_header_t)) + +typedef struct ipv6_hop_header { + u8 next_header; + u8 hdr_ext_len; + u8 options[0]; +} ipv6_hop_header_t; +#define IPV6_HOP_LEN (sizeof(ipv6_hop_header_t)) + +typedef struct ipv6_dest_opt_header { + u8 next_header; + u8 hdr_ext_len; + u8 options[0]; +} ipv6_dest_opt_header_t; +#define IPV6_DESTOPT_LEN (sizeof(ipv6_dest_opt_header_t)) + + +/* Definition of ICMP header */ +typedef struct icmp_v4_s { + u8 type; + u8 code; + u16 checksum; + u16 identifier; + u16 sequence; +} icmp_v4_t; + +#define ICMPV4_HDR_SIZE (sizeof(icmp_v4_t)) +#define ICMPV4_ECHOREPLY 0 /* Type: echo reply */ +#define ICMPV4_ECHO 8 /* Type: echo request */ + +#define ICMPV4_UNREACHABLE 3 /* Type: destination unreachable */ +#define ICMPV4_UNRNET 0 /* Code: Net unreachable */ +#define ICMPV4_UNRHOST 1 /* Code: host unreachable */ +#define ICMPV4_UNRPROT 2 /* Code: protocol unreachable */ +#define ICMPV4_UNRPORT 3 /* Code: port unreachable */ +#define ICMPV4_UNRFRAG 4 /* Code: frag req DF set */ +#define ICMPV4_UNRADMIN 13 /* Code: administratively prohib. */ +#define ICMPV4_SOURCEROUTE_FAILED 5 /* Code: administratively prohib. */ + +#define ICMPV4_SRC_ROUTE_FAIL 5 /* Code: Source Route Failed */ +#define ICMPV4_NO_ROUTE_DESTN_8 8 /* Code: No Route to Destn */ +#define ICMPV4_NO_ROUTE_DESTN_11 11 /* Code: No Route to Destn */ +#define ICMPV4_NO_ROUTE_DESTN_12 12 /* Code: No Route to Destn */ + +#define ICMPV4_ADMIN_PROH_9 9 /* Code: Administratively Prohibited */ +#define ICMPV4_ADMIN_PROH_10 10 /* Code: Administratively Prohibited */ +#define ICMPV4_PREC_CUTOFF 15 /* Code: Precedence Cutoff */ + + +#define ICMPV4_TIMEEXCEEDED 11 /* Type: time exceeded */ +#define ICMPV4_TIMTTL 0 /* Code: ttl in transit code */ + +#define ICMPV4_PARAMETER_PROBLEM 12 /* Type: Parameter Problem */ +#define ICMPV4_PARAM_ERROR 0 /* Code: Pointer to Error */ +#define ICMPV4_MISSING_OPTION_CODE 1 /* Code: Mission option */ +#define ICMPV4_PARAM_BAD_LEN 2 /* Code: Bad Length */ + +#define ICMPV4_CONVERSION_ERROR 31 +#define ICMPV4_SOURCE_QUENCH 4 +#define ICMPV4_REDIRECT 5 +#define ICMPV4_TIMESTAMP 13 +#define ICMPV4_TIMESTAMP_REPLY 14 +#define ICMPV4_INFO_REQUEST 15 +#define ICMPV4_INFO_REPLY 16 +#define ICMPV4_ADDR_MASK_REQUEST 17 +#define ICMPV4_ADDR_MASK_REPLY 18 + +typedef struct icmp_v6_s { + + u8 type; + u8 code; + u16 checksum; + + u32 data[0]; +} icmp_v6_t; + +typedef struct pseudo_v6_header { + u32 src_addr[4]; + u32 dst_addr[4]; + u16 payload_length; + u16 next_header; +} pseudo_v6_header_t; + + +#define ICMPV6_ECHO 128 +#define ICMPV6_ECHO_REPLY 129 +#define ICMPV6_PKT_TOO_BIG 2 +#define ICMPV6_TIMEEXCEEDED 3 +#define ICMPV6_TIMTTL 0 +#define ICMPV6_PARAMETER_PROBLEM 4 +#define ICMPV6_UNREACHABLE 1 +#define ICMPV6_NEIGHBOR_SOLICITAION 135 +#define ICMPV6_NEIGHBOR_ADVT 136 +/* ICMP V6 generated packet size */ +#define ICMPV6_ERR_SIZE 48 +#define ICMPV6_HDR_SIZE (sizeof(icmp_v6_t) +sizeof(u32)) + +/* Code for Type 1 */ +#define ICMPV6_UNRDESTN 0 /* Code: No route to Desnt */ +#define ICMPV6_ADM_PROH 1 /* Code: Adminitrative Prohibited */ +#define ICMPV6_SRC_ADD_SCOPE 2 /* Code: Source Address beyond scope */ +#define ICMPV6_UNRHOST 3 /* Code: Host Unreachable */ +#define ICMPV6_UNRPORT 4 /* Code: Port UnReachable */ + +#define ICMPV6_UNRPROT 1 /* type 4 - Code: No route to Desnt */ + +#define ICMPV6_PTB_CODE 0 /* Code: For PTB */ +#define ICMPV6_PARAM_CODE 0 /* Code: For Parameter Problem */ +#define ICMPV6_UNREC_HDR 1 /* Code: For Parameter Problem */ +#define ICMPV6_SRC_ADD_FAIL 5 /* Code: For Source address failed */ +#define ICMP_ECHO_REPLY_CODE 0 +#define DEFAULT_TTL_HOPLIMIT_VAL 64 + +typedef struct pptp_hdr_type { + + u16 flags_ver; + u16 proto_type; /* PPP = 0x880B */ + u16 payload_len; + u16 call_id; + u32 seq_no; + u32 ack_no; + +} pptp_hdr_type_t; + +/* + * NAME + * + * tcp_findoption + * + * SYNOPSIS + * u8* tcp_findoption (tcp_hdr_t *tcp, uchar option) + * + * PARAMETERS + * tcp - pointer to TCP header + * option - TCP option + * + * RETURNS + * This function returns a pointer to the option found, + * otherwise returns null. + * + * + * DESCRIPTION + * This function searches the option and returns a pointer to the + * matched option field containing option kind/length/data sub-fields. + * + */ +static inline u8* tcp_findoption (tcp_hdr_type *tcp, u8 option) +{ + u8*data; + u8 len, optlen; + + data = tcp->option_data; + len = ((tcp->hdr_len>>4) << 2) - sizeof(tcp_hdr_type); + +#define MAXTCPOPTIONBYTES 40 +#define MINTCPOPTIONLENGTH 2 + + while (len) { + if (PREDICT_TRUE(option == data[0])) { + return (data); + } else { + switch (data[0]) { + case TCP_END_OPTIONS_LIST: + return (NULL); + case TCP_OPTION_NOP: + len -= 1; + data += 1; + break; + default: + /* Sanity check the length. */ + optlen = data[1]; + if ((optlen < MINTCPOPTIONLENGTH) || + (optlen > MAXTCPOPTIONBYTES) || + (optlen > len)) { + return (NULL); + } + len -= optlen; + data += optlen; + break; + } + } + } + + return (NULL); +} + + +static inline u32 crc_calc (ipv4_header *ipv4) +{ + u16 *ipv4_word_ptr = (u16 *) ipv4; + u32 crc32; + /* + * Add all fields except the checksum field + */ + crc32 = (u32)clib_net_to_host_u16(*ipv4_word_ptr) + + (u32)clib_net_to_host_u16(*(ipv4_word_ptr + 1)) + + (u32)clib_net_to_host_u16(*(ipv4_word_ptr + 2)) + + (u32)clib_net_to_host_u16(*(ipv4_word_ptr + 3)) + + (u32)clib_net_to_host_u16(*(ipv4_word_ptr + 4)) + + (u32)clib_net_to_host_u16(*(ipv4_word_ptr + 6)) + + (u32)clib_net_to_host_u16(*(ipv4_word_ptr + 7)) + + (u32)clib_net_to_host_u16(*(ipv4_word_ptr + 8)) + + (u32)clib_net_to_host_u16(*(ipv4_word_ptr + 9)); + + /* Add in the carry of the original sum */ + crc32 = (crc32 & 0xFFFF) + (crc32 >> 16); + /* Add in the carry of the final sum */ + crc32 = (crc32 & 0xFFFF) + (crc32 >> 16); + + return crc32; +} + +#endif /* __TCP_HEADER_DEFINITIONS_H__ */ diff --git a/plugins/vcgn-plugin/vcgn/vcgn_classify.c b/plugins/vcgn-plugin/vcgn/vcgn_classify.c new file mode 100644 index 00000000..18cc4ba0 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/vcgn_classify.c @@ -0,0 +1,1508 @@ +/* + * Copyright (c) 2015 Cisco and/or its affiliates. + * 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 +#include +#include +#include +#include +#include + +#include +#include + +#include "cnat_db.h" +#include "cnat_global.h" +#include "cnat_cli.h" +#include "cnat_config.h" +#include "cnat_logging.h" +#include "cnat_config_api.h" +#include "cnat_show_api.h" +#include "cnat_show_response.h" +#include "cnat_ipv4_udp.h" +#include "cnat_common_api.h" + +#include + +typedef struct { + u32 cached_next_index; + + /* inside, outside interface handles */ + u32 * inside_sw_if_index_table; + u32 * outside_sw_if_index_table; + + /* convenience variables */ + vlib_main_t * vlib_main; + vnet_main_t * vnet_main; + u8 cnat_db_initalized; +} vcgn_classify_main_t; + +typedef struct { + /* $$$$ fill in with per-pkt trace data */ + u32 next_index; + u32 sw_if_index; + u32 orig_dst_address; + u16 orig_dst_port; +} vcgn_classify_trace_t; + +#define FIND_MY_VRF_USING_I_VRF_ID \ + my_vrfmap_found = 0; \ + pool_foreach (my_vrfmap, cnat_map_by_vrf, ({ \ + if (my_vrfmap->i_vrf_id == i_vrf_id) { \ + my_vrfmap_found = 1; \ + my_vrfmap_temp = my_vrfmap; \ + break; \ + } \ + })); + + +/* packet trace format function */ +static u8 * format_swap_trace (u8 * s, va_list * args) +{ + CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); + CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); + vcgn_classify_trace_t * t = va_arg (*args, vcgn_classify_trace_t *); + + s = format (s, "VCGN_CLASSIFY: dst %U dst_port %d sw_if_index %d next %d", + format_ip4_address, (ip4_header_t *) &t->orig_dst_address, + clib_net_to_host_u16(t->orig_dst_port), + t->sw_if_index, t->next_index); + return s; +} + +vcgn_classify_main_t vcgn_classify_main; + +vlib_node_registration_t vcgn_classify_node; + +#define foreach_vcgn_classify_error \ +_(PACKETS_RECEIVED, "total packets received") \ +_(V4_PACKETS_PROCESSED, "ipv4 packets processed for vCGN") \ +_(V4_PACKETS_PUNTED, "ipv4 packets punted") \ +_(V6_PACKETS_PUNTED, "ipv6 packets punted") \ +_(MPLS_PACKETS_PUNTED, "mpls unicast packets punted") \ +_(ETH_PACKETS_PUNTED, "ethernet packets punted") + + +typedef enum { +#define _(sym,str) VCGN_CLASSIFY_ERROR_##sym, + foreach_vcgn_classify_error +#undef _ + VCGN_CLASSIFY_N_ERROR, +} vcgn_classify_error_t; + +static char * vcgn_classify_error_strings[] = { +#define _(sym,string) string, + foreach_vcgn_classify_error +#undef _ +}; + +/* + * To drop a pkt and increment one of the previous counters: + * + * set b0->error = error_node->errors[VCGN_CLASSIFY_ERROR_EXAMPLE]; + * set next0 to a disposition index bound to "error-drop". + * + * To manually increment the specific counter VCGN_CLASSIFY_ERROR_EXAMPLE: + * + * vlib_node_t *n = vlib_get_node (vm, vcgn_classify.index); + * u32 node_counter_base_index = n->error_heap_index; + * vlib_error_main_t * em = &vm->error_main; + * em->counters[node_counter_base_index + VCGN_CLASSIFY_ERROR_EXAMPLE] += 1; + * + */ + +typedef enum { + VCGN_CLASSIFY_NEXT_IP4_INPUT, + VCGN_CLASSIFY_NEXT_IP6_INPUT, + VCGN_CLASSIFY_NEXT_MPLS_INPUT, + VCGN_CLASSIFY_NEXT_ETHERNET_INPUT, + VCGN_CLASSIFY_NEXT_UDP_INSIDE, + VCGN_CLASSIFY_NEXT_UDP_OUTSIDE, + VCGN_CLASSIFY_NEXT_TCP_INSIDE, + VCGN_CLASSIFY_NEXT_TCP_OUTSIDE, + VCGN_CLASSIFY_NEXT_ICMP_Q_INSIDE, + VCGN_CLASSIFY_NEXT_ICMP_Q_OUTSIDE, + VCGN_CLASSIFY_NEXT_ICMP_E_INSIDE, + VCGN_CLASSIFY_NEXT_ICMP_E_OUTSIDE, + VCGN_CLASSIFY_N_NEXT, +} vcgn_classify_next_t; + +static uword +vcgn_classify_node_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + u32 n_left_from, * from, * to_next; + vcgn_classify_next_t next_index; + vcgn_classify_main_t * vcm = &vcgn_classify_main; + vlib_node_t *n = vlib_get_node (vm, vcgn_classify_node.index); + u32 node_counter_base_index = n->error_heap_index; + vlib_error_main_t * em = &vm->error_main; + u16 *l3_type; + int counter; + + from = vlib_frame_vector_args (frame); + n_left_from = frame->n_vectors; + next_index = node->cached_next_index; + + while (n_left_from > 0) + { + u32 n_left_to_next; + + vlib_get_next_frame (vm, node, next_index, + to_next, n_left_to_next); + + #if 0 + while (n_left_from >= 4 && n_left_to_next >= 2) + { + u32 bi0, bi1; + vlib_buffer_t * b0, * b1; + u32 next0, next1; + u32 sw_if_index0, sw_if_index1; + + /* Prefetch next iteration. */ + { + vlib_buffer_t * p2, * p3; + + p2 = vlib_get_buffer (vm, from[2]); + p3 = vlib_get_buffer (vm, from[3]); + + vlib_prefetch_buffer_header (p2, LOAD); + vlib_prefetch_buffer_header (p3, LOAD); + + CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, STORE); + CLIB_PREFETCH (p3->data, CLIB_CACHE_LINE_BYTES, STORE); + } + + /* speculatively enqueue b0 and b1 to the current next frame */ + to_next[0] = bi0 = from[0]; + to_next[1] = bi1 = from[1]; + from += 2; + to_next += 2; + n_left_from -= 2; + n_left_to_next -= 2; + + b0 = vlib_get_buffer (vm, bi0); + b1 = vlib_get_buffer (vm, bi1); + + sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX]; + next0 = vcm->cached_next_index; + sw_if_index1 = vnet_buffer(b1)->sw_if_index[VLIB_RX]; + next1 = vcm->cached_next_index; + + /* $$$$ your message in this space. Process 2 x pkts */ + em->counters[node_counter_base_index + VCGN_CLASSIFY_ERROR_PACKETS_RECEIVED] += 2; + + if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE))) + { + if (b0->flags & VLIB_BUFFER_IS_TRACED) + { + vcgn_classify_trace_t *t = + vlib_add_trace (vm, node, b0, sizeof (*t)); + t->sw_if_index = sw_if_index0; + t->next_index = next0; + } + if (b1->flags & VLIB_BUFFER_IS_TRACED) + { + vcgn_classify_trace_t *t = + vlib_add_trace (vm, node, b1, sizeof (*t)); + t->sw_if_index = sw_if_index1; + t->next_index = next1; + } + } + + /* verify speculative enqueues, maybe switch current next frame */ + vlib_validate_buffer_enqueue_x2 (vm, node, next_index, + to_next, n_left_to_next, + bi0, bi1, next0, next1); + } + #endif /* if 0 */ + + while (n_left_from > 0 && n_left_to_next > 0) + { + u32 bi0; + vlib_buffer_t * b0; + u32 next0; + u32 sw_if_index0; + ip4_header_t * h0; + //ipv4_header *h0; + ethernet_header_t *eth0; + icmp_v4_t *icmp; + u8 icmp_type; + u8 ipv4_hdr_len; + + /* speculatively enqueue b0 to the current next frame */ + bi0 = from[0]; + to_next[0] = bi0; + from += 1; + to_next += 1; + n_left_from -= 1; + n_left_to_next -= 1; + + b0 = vlib_get_buffer (vm, bi0); + + eth0 = (ethernet_header_t *) vlib_buffer_get_current(b0); + u16 *etype = ð0->type; + + /* vlan tag 0x8100 */ + if (*etype == clib_host_to_net_u16(ETHERNET_TYPE_VLAN)) { + l3_type = (etype + 1); /* Skip 2 bytes of vlan id */ + vlib_buffer_advance(b0, 18); + } else { + l3_type = etype; + vlib_buffer_advance(b0, 14); + } + /* Handling v4 pkts 0x800 */ + if (*l3_type == clib_host_to_net_u16(ETHERNET_TYPE_IP4)) { + + h0 = vlib_buffer_get_current (b0); + + u8 protocol_type = h0->protocol; + + sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX]; + next0 = VCGN_CLASSIFY_NEXT_IP4_INPUT; + counter = VCGN_CLASSIFY_ERROR_V4_PACKETS_PROCESSED; + + if (protocol_type == 0x11) { /* UDP# 17 */ + next0 = (sw_if_index0 < vec_len(vcm->inside_sw_if_index_table) && + vcm->inside_sw_if_index_table[sw_if_index0] != EMPTY) ? + VCGN_CLASSIFY_NEXT_UDP_INSIDE : next0; + + next0 = (sw_if_index0 < vec_len(vcm->outside_sw_if_index_table) && + vcm->outside_sw_if_index_table[sw_if_index0] != EMPTY) ? + VCGN_CLASSIFY_NEXT_UDP_OUTSIDE : next0; + + } else if (protocol_type == 0x06) { /* TCP# 6 */ + next0 = (sw_if_index0 < vec_len(vcm->inside_sw_if_index_table) && + vcm->inside_sw_if_index_table[sw_if_index0] != EMPTY) ? + VCGN_CLASSIFY_NEXT_TCP_INSIDE : next0; + + next0 = (sw_if_index0 < vec_len(vcm->outside_sw_if_index_table) && + vcm->outside_sw_if_index_table[sw_if_index0] != EMPTY) ? + VCGN_CLASSIFY_NEXT_TCP_OUTSIDE : next0; + + } else if (protocol_type == 0x01) { /* ICMP # 1 */ + + ipv4_hdr_len = (h0->ip_version_and_header_length & 0xf) << 2; + icmp = (icmp_v4_t *)((u8*)h0 + ipv4_hdr_len); + icmp_type = icmp->type; + + if ((icmp_type == ICMPV4_ECHO) || + (icmp_type == ICMPV4_ECHOREPLY)) { + next0 = (sw_if_index0 < vec_len(vcm->inside_sw_if_index_table) && + vcm->inside_sw_if_index_table[sw_if_index0] != EMPTY) ? + VCGN_CLASSIFY_NEXT_ICMP_Q_INSIDE : next0; + + next0 = (sw_if_index0 < vec_len(vcm->outside_sw_if_index_table) && + vcm->outside_sw_if_index_table[sw_if_index0] != EMPTY) ? + VCGN_CLASSIFY_NEXT_ICMP_Q_OUTSIDE : next0; + + } else { + next0 = (sw_if_index0 < vec_len(vcm->inside_sw_if_index_table) && + vcm->inside_sw_if_index_table[sw_if_index0] != EMPTY) ? + VCGN_CLASSIFY_NEXT_ICMP_E_INSIDE : next0; + + next0 = (sw_if_index0 < vec_len(vcm->outside_sw_if_index_table) && + vcm->outside_sw_if_index_table[sw_if_index0] != EMPTY) ? + VCGN_CLASSIFY_NEXT_ICMP_E_OUTSIDE : next0; + } + } else { + /* cannot do NATting with this L4 protocol */ + counter = VCGN_CLASSIFY_ERROR_V4_PACKETS_PUNTED; + } + + if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE) + && (b0->flags & VLIB_BUFFER_IS_TRACED))) { + udp_header_t * u0 = (udp_header_t *)(h0+1); + vcgn_classify_trace_t *t = + vlib_add_trace (vm, node, b0, sizeof (*t)); + t->sw_if_index = sw_if_index0; + t->next_index = next0; + t->orig_dst_address = h0->dst_address.as_u32; + t->orig_dst_port = u0->dst_port; + } + + } else if (*l3_type == clib_host_to_net_u16(ETHERNET_TYPE_IP6)) { + + /* IPv6 0x86DD */ + next0 = VCGN_CLASSIFY_NEXT_IP6_INPUT; + counter = VCGN_CLASSIFY_ERROR_V6_PACKETS_PUNTED; + + } else if (*l3_type == + clib_host_to_net_u16(ETHERNET_TYPE_MPLS_UNICAST)) { + + /* MPLS unicast 0x8847 */ + next0 = VCGN_CLASSIFY_NEXT_MPLS_INPUT; + counter = VCGN_CLASSIFY_ERROR_MPLS_PACKETS_PUNTED; + } else { /* Remaining all should be pushed to "ethernet-input" */ + + next0 = VCGN_CLASSIFY_NEXT_ETHERNET_INPUT; + counter = VCGN_CLASSIFY_ERROR_ETH_PACKETS_PUNTED; + } + + em->counters[node_counter_base_index + counter] += 1; + em->counters[node_counter_base_index + + VCGN_CLASSIFY_ERROR_PACKETS_RECEIVED] += 1; + + /* verify speculative enqueue, maybe switch current next frame */ + vlib_validate_buffer_enqueue_x1 (vm, node, next_index, + to_next, n_left_to_next, + bi0, next0); + } + + vlib_put_next_frame (vm, node, next_index, n_left_to_next); + } + + return frame->n_vectors; +} + +VLIB_REGISTER_NODE (vcgn_classify_node) = { + .function = vcgn_classify_node_fn, + .name = "vcgn-classify", + .vector_size = sizeof (u32), + .format_trace = format_swap_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + + .n_errors = ARRAY_LEN(vcgn_classify_error_strings), + .error_strings = vcgn_classify_error_strings, + + .n_next_nodes = VCGN_CLASSIFY_N_NEXT, + + /* edit / add dispositions here */ + .next_nodes = { + [VCGN_CLASSIFY_NEXT_IP4_INPUT] = "ip4-input", + [VCGN_CLASSIFY_NEXT_IP6_INPUT] = "ip6-input", + [VCGN_CLASSIFY_NEXT_MPLS_INPUT] = "mpls-gre-input", + [VCGN_CLASSIFY_NEXT_ETHERNET_INPUT] = "ethernet-input", + [VCGN_CLASSIFY_NEXT_UDP_INSIDE] = "vcgn-v4-udp-i2o", + [VCGN_CLASSIFY_NEXT_UDP_OUTSIDE] = "vcgn-v4-udp-o2i", + [VCGN_CLASSIFY_NEXT_TCP_INSIDE] = "vcgn-v4-tcp-i2o", + [VCGN_CLASSIFY_NEXT_TCP_OUTSIDE] = "vcgn-v4-tcp-o2i", + [VCGN_CLASSIFY_NEXT_ICMP_Q_INSIDE] = "vcgn-v4-icmp-q-i2o", + [VCGN_CLASSIFY_NEXT_ICMP_Q_OUTSIDE] = "vcgn-v4-icmp-q-o2i", + [VCGN_CLASSIFY_NEXT_ICMP_E_INSIDE] = "vcgn-v4-icmp-e-i2o", + [VCGN_CLASSIFY_NEXT_ICMP_E_OUTSIDE] = "vcgn-v4-icmp-e-o2i" + }, +}; + + +/* A test function to init the vrf map */ + +clib_error_t *vcgn_classify_init (vlib_main_t *vm) +{ + vcgn_classify_main_t * mp = &vcgn_classify_main; + + mp->vlib_main = vm; + mp->vnet_main = vnet_get_main(); + u32 inside_sw_if_index = 1; + u32 outside_sw_if_index = 0; + + vec_validate_init_empty (mp->inside_sw_if_index_table, + inside_sw_if_index + 1, EMPTY); + vec_validate_init_empty (mp->outside_sw_if_index_table, + outside_sw_if_index + 1, EMPTY); + + /* + * inside_sw_if_index cell of the table stores outside_sw_if_index + * and vice versa. This is ensurs pair of indices being remembered + * using one mem-location. + */ + mp->inside_sw_if_index_table[inside_sw_if_index] = outside_sw_if_index; + mp->outside_sw_if_index_table[outside_sw_if_index] = inside_sw_if_index; + +#if DPDK==1 + dpdk_set_next_node (DPDK_RX_NEXT_IP4_INPUT, "vcgn-classify"); +#endif + + { + pg_node_t * pn; + pn = pg_get_node (vcgn_classify_node.index); + pn->unformat_edit = unformat_pg_ip4_header; + } + return 0; +} + +VLIB_INIT_FUNCTION (vcgn_classify_init); + +/* Show command handlers */ +static clib_error_t * +show_vcgn_stats_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + if (cnat_db_init_done) { + cnat_nat44_handle_show_stats(vm); + } else { + vlib_cli_output(vm, "vCGN is not configured !!\n"); + } + return 0; +} + + +static clib_error_t * +show_vcgn_config_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + cnat_nat44_handle_show_config(vm); + return 0; +} + +static clib_error_t * +show_vcgn_inside_translation_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + vnet_main_t * vnm = vnet_get_main(); + vcgn_classify_main_t * vcm = &vcgn_classify_main; + spp_api_cnat_v4_show_inside_entry_req_t inside_req; + u8 *proto; + ip4_address_t inside_addr; + u32 start_port = 1; + u32 end_port = 65535; + u32 inside_sw_if_index = EMPTY; + + inside_req.start_port = start_port; + inside_req.end_port = end_port; + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { + if (unformat(input, "protocol %s", &proto)) { + if (!strncmp((char *) proto, "udp", 3)) { + inside_req.protocol = 1; + } else if (!strncmp((char *) proto, "tcp", 3)) { + inside_req.protocol = 2; + } else { + inside_req.protocol = 3; + } + } else if (unformat (input, "interface %U", + unformat_vnet_sw_interface, vnm, &inside_sw_if_index)) { + if (inside_sw_if_index > vec_len(vcm->inside_sw_if_index_table) || + vcm->inside_sw_if_index_table[inside_sw_if_index] == EMPTY) { + return clib_error_return (0, "Could not find the inside interface"); + } + } else if (unformat (input, "inside-addr %U", + unformat_ip4_address, &inside_addr)) { + inside_req.ipv4_addr = clib_net_to_host_u32(inside_addr.as_u32); + } else if (unformat(input, "start-port %u", &start_port)) { + inside_req.start_port = start_port; + } else if (unformat(input, "end-port %u", &end_port)) { + inside_req.end_port = end_port; + } else { break;} + } + inside_req.vrf_id = inside_sw_if_index; + inside_req.flags |= CNAT_TRANSLATION_ENTRY_DYNAMIC; /* as of now only dynamic */ + inside_req.all_entries = 0; /* we can see it later */ +#if DEBUG + vlib_cli_output(vm, "proto %d, inside-addr 0x%x, start_port %u, " + "end_port %u, vrf 0x%x\n", + inside_req.protocol, + inside_req.ipv4_addr, + inside_req.start_port, + inside_req.end_port, + inside_sw_if_index); +#endif + if (cnat_db_init_done) { + cnat_v4_show_inside_entry_req_t_handler(&inside_req, vm); + } else { + vlib_cli_output(vm, "vCGN is not configured !!\n"); + } + return 0; +} + + +static clib_error_t * +show_vcgn_outside_translation_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + void cnat_v4_show_outside_entry_req_t_handler + (spp_api_cnat_v4_show_outside_entry_req_t *mp, vlib_main_t *vm); + vnet_main_t * vnm = vnet_get_main(); + vcgn_classify_main_t * vcm = &vcgn_classify_main; + spp_api_cnat_v4_show_outside_entry_req_t outside_req; + u8 *proto; + ip4_address_t outside_addr; + u32 start_port = 1; + u32 end_port = 65535; + u32 outside_sw_if_index = EMPTY; + + + outside_req.start_port = start_port; + outside_req.end_port = end_port; + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { + if (unformat(input, "protocol %s", &proto)) { + if (!strncmp((char *) proto, "udp", 3)) { + outside_req.protocol = 1; + } else if (!strncmp((char *) proto, "tcp", 3)) { + outside_req.protocol = 2; + } else { + outside_req.protocol = 3; + } + } else if (unformat (input, "interface %U", + unformat_vnet_sw_interface, vnm, &outside_sw_if_index)) { + if (outside_sw_if_index > vec_len(vcm->outside_sw_if_index_table) || + vcm->outside_sw_if_index_table[outside_sw_if_index] == EMPTY) { + return clib_error_return (0, "Could not find the outside interface"); + } + } else if (unformat (input, "outside-addr %U", + unformat_ip4_address, &outside_addr)) { + outside_req.ipv4_addr = clib_net_to_host_u32(outside_addr.as_u32); + } else if (unformat(input, "start-port %u", &start_port)) { + outside_req.start_port = start_port; + } else if (unformat(input, "end-port %u", &end_port)) { + outside_req.end_port = end_port; + } else { break;} + } + outside_req.vrf_id = outside_sw_if_index; + outside_req.flags |= CNAT_TRANSLATION_ENTRY_DYNAMIC; /* as of now only dynamic */ +#if DEBUG + vlib_cli_output(vm, "proto %d, outside-addr 0x%x, start_port %u, " + "end_port %u, vrf 0x%x\n", + outside_req.protocol, + outside_req.ipv4_addr, + outside_req.start_port, + outside_req.end_port, + outside_sw_if_index); +#endif + if (cnat_db_init_done) { + cnat_v4_show_outside_entry_req_t_handler(&outside_req, vm); + } else { + vlib_cli_output(vm, "vCGN is not configured !!\n"); + } + return 0; +} + + +/* Config command handlers */ +static clib_error_t * +set_vcgn_inside_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + vnet_main_t * vnm = vnet_get_main(); + vcgn_classify_main_t * vcm = &vcgn_classify_main; + u32 inside_sw_if_index = 1; + u32 outside_sw_if_index = ~0; + void cnat_db_v2_init (void ); + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { + if (unformat(input, "%U", + unformat_vnet_sw_interface, vnm, &inside_sw_if_index)) + ; + else if (unformat(input, "outside %U", + unformat_vnet_sw_interface, vnm, &outside_sw_if_index)) + ; + else break; + } + if (inside_sw_if_index == ~0 || + outside_sw_if_index == ~0) + return clib_error_return (0, "unknown input `%U'", + format_unformat_error, input); + + if (inside_sw_if_index == outside_sw_if_index) + return clib_error_return (0, "inside and outside interfaces can't be the same..."); + + /* + * Initialize in/out sw_if_index table. Could use + * non-indexed table to reduce memory. However, this + * is consulted in vcgn_classify for every packet. + * Therefore, table is indexed by sw_if_index. + */ + vec_validate_init_empty (vcm->inside_sw_if_index_table, + inside_sw_if_index + 1, EMPTY); + vec_validate_init_empty (vcm->outside_sw_if_index_table, + outside_sw_if_index + 1, EMPTY); + + /* + * inside_sw_if_index cell of the table stores outside_sw_if_index + * and vice versa. This is ensurs pair of indices being remembered + * using one mem-location. + */ + vcm->inside_sw_if_index_table[inside_sw_if_index] = outside_sw_if_index; + vcm->outside_sw_if_index_table[outside_sw_if_index] = inside_sw_if_index; + + if (! vcm->cnat_db_initalized) { + int i; + cnat_db_v2_init(); + + for (i = 0; i < CNAT_MAX_VRFMAP_ENTRIES; i++) { + vrf_map_array[i] = VRF_MAP_ENTRY_EMPTY; + } + /* Turn on the db scanner process */ + cnat_scanner_db_process_turn_on(vm); + vcm->cnat_db_initalized = 1; + } + return 0; +} + +static clib_error_t * +set_vcgn_map_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + vnet_main_t * vnm = vnet_get_main(); + vcgn_classify_main_t * vcm = &vcgn_classify_main; + ip4_address_t lo, hi; + spp_api_cnat_v4_add_vrf_map_t map; + u32 inside_sw_if_index = EMPTY; + u32 outside_sw_if_index; + + vnet_hw_interface_t *inside_hw_if_index = NULL; + vnet_hw_interface_t *outside_hw_if_index = NULL; + + if (! unformat(input, "inside %U", + unformat_vnet_sw_interface, vnm, &inside_sw_if_index)) + return clib_error_return (0, "unknown input `%U'", + format_unformat_error, input); + + if (!unformat (input, "%U", unformat_ip4_address, &lo)) + return clib_error_return (0, "unknown input `%U'", + format_unformat_error, input); + + if (unformat (input, "- %U", unformat_ip4_address, &hi)) + ; + + /* $$$$ remember to set i_vrf, i_vrf_id as needed */ + + /* Fill the structure spp_api_cnat_v4_add_vrf_map_t & let this API handle it */ + /* i_vrf_id & o_vrf_id are 32-bit & i_vrf, o_vrf are 16 bit */ + + if (inside_sw_if_index > vec_len(vcm->inside_sw_if_index_table) || + vcm->inside_sw_if_index_table[inside_sw_if_index] == EMPTY) { + return clib_error_return (0, "Could not find the inside interface"); + } + outside_sw_if_index = vcm->inside_sw_if_index_table[inside_sw_if_index]; + + map.i_vrf_id = inside_sw_if_index; + map.o_vrf_id = outside_sw_if_index; + map.i_vrf = inside_sw_if_index; + map.o_vrf = outside_sw_if_index; + + map.start_addr[0] = clib_net_to_host_u32(lo.as_u32); + map.end_addr[0] = clib_net_to_host_u32(hi.as_u32); + + cnat_nat44_add_vrf_map_t_handler(&map, vm); + +#if 1 + inside_hw_if_index = vnet_get_sup_hw_interface(vcm->vnet_main, inside_sw_if_index); + if (inside_hw_if_index) { + vnet_hw_interface_rx_redirect_to_node(vcm->vnet_main, + inside_hw_if_index->hw_if_index, vcgn_classify_node.index); + } + outside_hw_if_index = vnet_get_sup_hw_interface(vcm->vnet_main, outside_sw_if_index); + if (outside_hw_if_index) { + vnet_hw_interface_rx_redirect_to_node(vcm->vnet_main, + outside_hw_if_index->hw_if_index, vcgn_classify_node.index); + } +#endif + return 0; +} + +static clib_error_t * +set_vcgn_tcp_timeout_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + /* + vnet_main_t * vnm = vnet_get_main(); + vcgn_classify_main_t * vcm = &vcgn_classify_main; + */ + u32 act_timeout = 0; + u32 init_timeout = 0; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { + if (unformat(input, "active %u", &act_timeout)) + tcp_active_timeout = act_timeout; + else if (unformat(input, "init %u", &init_timeout)) + tcp_initial_setup_timeout = init_timeout; + else break; + } + return 0; +} + +static clib_error_t * +set_vcgn_udp_timeout_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + /* + vnet_main_t * vnm = vnet_get_main(); + vcgn_classify_main_t * vcm = &vcgn_classify_main; + */ + u32 act_timeout = 0; + u32 init_timeout = 0; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { + if (unformat(input, "active %u", &act_timeout)) + udp_act_session_timeout = act_timeout; + else if (unformat(input, "init %u", &init_timeout)) + udp_init_session_timeout = init_timeout; + else break; + } + return 0; +} + + +static clib_error_t * +set_vcgn_icmp_timeout_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + /* + * vnet_main_t * vnm = vnet_get_main(); + * vcgn_classify_main_t * vcm = &vcgn_classify_main; + */ + u32 timeout = 0; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { + if (unformat(input, "%u", &timeout)) + ; + else break; + } + icmp_session_timeout = timeout; + return 0; +} + + +static clib_error_t * +set_vcgn_protocol_default_timeout_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + /* + vnet_main_t * vnm = vnet_get_main(); + vcgn_classify_main_t * vcm = &vcgn_classify_main; + */ + u8 *protocol; + u8 reset = 1; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { + if (unformat(input, "%s", &protocol)) + ; + else break; + } + cnat_nat44_set_protocol_timeout_value(0, 0, protocol, reset, vm); + return 0; +} + +static clib_error_t * +set_vcgn_dynamic_port_start_range_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + /* + vnet_main_t * vnm = vnet_get_main(); + vcgn_classify_main_t * vcm = &vcgn_classify_main; + */ + u32 port = 0; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { + if (unformat(input, "%u", &port)) + ; + else break; + } + if (port != 0 && port > 65535) { + vlib_cli_output(vm, "Error !! Invalid port\n"); + } else { + cnat_static_port_range = port; + vlib_cli_output(vm, "Dynamic Port Range Config Successful !!\n"); + } + return 0; +} + +static clib_error_t * +set_vcgn_port_limit_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + /* + vnet_main_t * vnm = vnet_get_main(); + vcgn_classify_main_t * vcm = &vcgn_classify_main; + */ + u32 port = 0; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { + if (unformat(input, "%u", &port)) + ; + else break; + } + if (port != 0 && port > 65535) { + vlib_cli_output(vm, "Error !! Invalid port\n"); + } else { + cnat_main_db_max_ports_per_user = port; + vlib_cli_output(vm, "Port Limit Config Successful !!\n"); + } + return 0; +} + +static inline void nfv9_init_pkt_sent_data(cnat_nfv9_logging_info_t *nfv9_info) +{ + nfv9_server_info_t *server = nfv9_server_info_pool + + nfv9_info->server_index; + + /* + * Reset the pkts_since_last_template and sent_time + * so that template will be sent next time + */ + server->last_template_sent_time = 0; + server->pkts_since_last_template = 0xffffffff; +} + +static inline u16 nfv9_get_max_length_minus_max_record_size(u16 path_mtu) +{ + u16 max_length_minus_max_record_size; + if(!path_mtu) /* Use default */ + path_mtu = NFV9_DEF_PATH_MTU; + + max_length_minus_max_record_size = path_mtu - + CNAT_NFV9_DATAFLOW_RECORD_HEADER_LENGTH - + NFV9_PAD_VALUE - + CNAT_NFV9_MAX_SINGLE_RECORD_LENGTH; /* Note.. as of now this record + * requires max number of bytes. If you add more records, + * this needs to be re-checked */ + if (max_length_minus_max_record_size < CNAT_NFV9_MIN_RECORD_SIZE) { + max_length_minus_max_record_size = CNAT_NFV9_MIN_RECORD_SIZE; + } + return max_length_minus_max_record_size; +} + +/* This function finds if the netflow server indicated by + * new_server_info is already configured for some other instance + * if yes, it returns the same pointer so that, info sent to the + * server is consistent. If the server is not found, a new instance + * is created and returned. If an existing server is used, its refernce + * count is incrimented (indicating the number of instances using the + * same server + */ + /* #define DEBUG_NF_SERVER_CONFIG 1 */ +static u16 nfv9_get_server_instance( + cnat_nfv9_logging_info_t *nfv9_info, nfv9_server_info_t *new_server_info) +{ + + /* Check if the instance has a server already and if yes, does it match */ + nfv9_server_info_t *server; + if(nfv9_info->server_index != EMPTY) { + server = nfv9_server_info_pool + nfv9_info->server_index; + + if((server->ipv4_address == new_server_info->ipv4_address) && + (server->port == new_server_info->port)) { + /* Same server.. just check if refresh rate/timeouts are reduced */ +#ifdef DEBUG_NF_SERVER_CONFIG + if(my_instance_number == 1) { + printf("\n Server match for %x and port %d\n", + new_server_info->ipv4_address, new_server_info->port); + } +#endif /* #ifdef DEBUG_NF_SERVER_CONFIG */ + goto adjust_refresh_rate; + } else { /* The server is being changed */ + server->ref_count--; +#ifdef DEBUG_NF_SERVER_CONFIG + if(my_instance_number == 1) { + printf("\n Server change from %x, %d to %x, %d" + "Ref count %d\n", + server->ipv4_address, + server->port, + new_server_info->ipv4_address, new_server_info->port, + server->ref_count); + } +#endif /* #ifdef DEBUG_NF_SERVER_CONFIG */ + if(!server->ref_count) { + /* Return this server to pool */ +#ifdef DEBUG_NF_SERVER_CONFIG + if(my_instance_number == 1) { + PLATFORM_DEBUG_PRINT("Deleting Server %x, %d at %d\n", + server->ipv4_address, + server->port, + nfv9_info->server_index); + } +#endif /* #ifdef DEBUG_NF_SERVER_CONFIG */ + pool_put(nfv9_server_info_pool, server); + } + } + } + + /* Now check if the server is already present in the pool */ + u8 found = 0; + server = 0; + pool_foreach (server, nfv9_server_info_pool, ({ + if ((server->ipv4_address == new_server_info->ipv4_address) && + (server->port == new_server_info->port)) { + server->ref_count++; + nfv9_info->server_index = server - nfv9_server_info_pool; + found = 1; +#ifdef DEBUG_NF_SERVER_CONFIG + if(my_instance_number == 1) { + printf("Re-using server %x, %d Ref count %d\n", + server->ipv4_address, server->port, server->ref_count); + } +#endif /* #ifdef DEBUG_NF_SERVER_CONFIG */ + break; + } + })); + + if(!found) { + /* Create a new one, initialize and return */ + server = 0; + pool_get(nfv9_server_info_pool, server); + clib_memcpy(server, new_server_info, sizeof(nfv9_server_info_t)); + server->ref_count = 1; + nfv9_info->server_index = server - nfv9_server_info_pool; +#ifdef DEBUG_NF_SERVER_CONFIG + if(my_instance_number == 1) { + printf("Create new server for at %d %x and port %d\n", + nfv9_info->server_index, + new_server_info->ipv4_address, new_server_info->port); + } +#endif /* #ifdef DEBUG_NF_SERVER_CONFIG */ + return CNAT_SUCCESS; + } + +adjust_refresh_rate: + if(server->refresh_rate > + new_server_info->refresh_rate) { + server->refresh_rate = + new_server_info->refresh_rate; +#ifdef DEBUG_NF_SERVER_CONFIG + if(my_instance_number == 1) { + printf("Reset refresh rate to %d\n", + server->refresh_rate); + } +#endif /* #ifdef DEBUG_NF_SERVER_CONFIG */ + } + + if(server->timeout_rate > + new_server_info->timeout_rate) { + server->timeout_rate = + new_server_info->timeout_rate; +#ifdef DEBUG_NF_SERVER_CONFIG + if(my_instance_number == 1) { + printf("Reset timeout rate to %d\n", + server->timeout_rate); + } +#endif /* #ifdef DEBUG_NF_SERVER_CONFIG */ + } + + return CNAT_SUCCESS; +} +static clib_error_t * +set_vcgn_nfv9_logging_cofig_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + vcgn_classify_main_t * vcm = &vcgn_classify_main; + spp_api_cnat_v4_config_nfv9_logging_t nfv9_conf; + ip4_address_t server_addr; + u32 ip_addr = 0; + u32 port; + u32 refresh_rate = 0; + u32 timeout = 0; + u32 pmtu = 0; + u8 enable = 1; +/* vcgn changes start*/ + cnat_nfv9_logging_info_t *my_nfv9_logging_info = NULL; + cnat_nfv9_logging_info_t *my_nfv9_logging_info_tmp = NULL; + cnat_vrfmap_t *my_vrfmap = 0, *my_vrfmap_temp = 0; + u16 i_vrf = ~0; + u32 i_vrf_id = ~0; + u8 found; + u32 inside_sw_if_index = EMPTY; + /* + * Init NFv9 logging info as needed, this will be done only once + */ + cnat_nfv9_logging_init(); + + found = 0; + +/* vcgn changes end*/ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { + if (unformat (input, "inside %U", + unformat_vnet_sw_interface, &inside_sw_if_index)) { + /* Do nothing */ + } else if (unformat (input, "server %U", unformat_ip4_address, &server_addr)) + ip_addr = clib_net_to_host_u32(server_addr.as_u32); + else if (unformat(input, "port %u", &port)) + ; + else if (unformat(input, "refresh-rate %u", &refresh_rate)) + ; + else if (unformat(input, "timeout %u", &timeout)) + ; + else if (unformat(input, "pmtu %u", &pmtu)) + ; + else if (unformat(input, "del")) + enable = 0; + else break; + } + + if (inside_sw_if_index > vec_len(vcm->inside_sw_if_index_table) || + vcm->inside_sw_if_index_table[inside_sw_if_index] == EMPTY) { + return clib_error_return (0, "Could not find the inside interface"); + } + i_vrf = inside_sw_if_index; + i_vrf_id = inside_sw_if_index; + + #if 0 + vlib_cli_output(vm, "ip 0x%x, port %u, refresh %u, " + "timeout %u, pmtu %u enable %u\n", + ip_addr, port, refresh_rate, + timeout, pmtu, enable); + #endif + if (refresh_rate == 0) refresh_rate = 500; /* num of pkts */ + if (timeout == 0) timeout = 30; /* in mins */ + + nfv9_conf.enable = enable; + nfv9_conf.ipv4_address = ip_addr; + nfv9_conf.i_vrf_id = inside_sw_if_index; + nfv9_conf.i_vrf = inside_sw_if_index; + nfv9_conf.port = port; + nfv9_conf.refresh_rate = refresh_rate; + nfv9_conf.timeout_rate = timeout; + nfv9_conf.path_mtu = pmtu; + nfv9_conf.nfv9_global_collector = 0; + nfv9_conf.session_logging = 0; + + /* + * At this point the NFv9 global information should already be + * inited as we have called cnat_nfv9_logging_init() + */ + + if (nfv9_conf.nfv9_global_collector) { + if (cnat_nfv9_global_info.cnat_nfv9_global_collector_index != EMPTY) { + found = 1; + my_nfv9_logging_info = cnat_nfv9_logging_info_pool + + cnat_nfv9_global_info.cnat_nfv9_global_collector_index; + } + } else { + /* Do we already have a map for this VRF? */ + pool_foreach (my_nfv9_logging_info, cnat_nfv9_logging_info_pool, ({ + if (my_nfv9_logging_info->i_vrf_id == i_vrf_id) { + nfv9_server_info_t *server = nfv9_server_info_pool + + my_nfv9_logging_info->server_index; + if((server->ipv4_address == (nfv9_conf.ipv4_address)) && (server->port == (nfv9_conf.port))) { + found = 1; + my_nfv9_logging_info_tmp = my_nfv9_logging_info; + break; + } + } + })); + } + + if ((nfv9_conf.ipv4_address == 0) || + (nfv9_conf.port == 0)) { + vlib_cli_output(vm, + "Add NFv9 ivrf %d Logging Invalid values [IPv4 0x%x, PORT %d]\n", + i_vrf, + (nfv9_conf.ipv4_address), + (nfv9_conf.port)); + goto done; + } + + if (nfv9_conf.enable) { + if ((nfv9_conf.ipv4_address == 0) || + (nfv9_conf.port == 0)) { + nfv9_conf.rc = CNAT_ERR_PARSER; + vlib_cli_output(vm, + "NFV9_logging i_vrf %d, Invalid [v4_addr 0x%x port %d]\n", + i_vrf, + (nfv9_conf.ipv4_address), + (nfv9_conf.port)); + goto done; + } + + nfv9_server_info_t new_server_info; + memset(&new_server_info, 0, sizeof(nfv9_server_info_t)); + new_server_info.ipv4_address = + nfv9_conf.ipv4_address; + new_server_info.port = + (nfv9_conf.port); + new_server_info.refresh_rate = + (nfv9_conf.refresh_rate); + /* + * Store the timeout in seconds. User configures it in minutes + */ + new_server_info.timeout_rate = + 60*(nfv9_conf.timeout_rate); + if (found && my_nfv9_logging_info) { + /* + * Entry already present, change it + */ + my_nfv9_logging_info->max_length_minus_max_record_size = + nfv9_get_max_length_minus_max_record_size( + ((nfv9_conf.path_mtu))); + } else { + pool_get(cnat_nfv9_logging_info_pool, my_nfv9_logging_info); + memset(my_nfv9_logging_info, 0, sizeof(*my_nfv9_logging_info)); + my_nfv9_logging_info->server_index = EMPTY; + my_nfv9_logging_info->nfv9_logging_next_index = EMPTY; + /* + * Make the current and head logging context indeices as EMPTY. + * When first logging happens, these get set correctly + */ + my_nfv9_logging_info->current_logging_context = NULL; + my_nfv9_logging_info->queued_logging_context = NULL; +#if 0 + my_nfv9_logging_info->f = NULL; + my_nfv9_logging_info->to_next = NULL; + output_node = vlib_get_node_by_name (vm, (u8 *) "ip4-input"); + my_nfv9_logging_info->ip4_input_node_index = output_node->index; + printf("ip4_input_node_index %d\n", my_nfv9_logging_info->ip4_input_node_index); +#endif + my_nfv9_logging_info->i_vrf = i_vrf; + my_nfv9_logging_info->i_vrf_id = i_vrf_id; + my_nfv9_logging_info->max_length_minus_max_record_size = + nfv9_get_max_length_minus_max_record_size( + nfv9_conf.path_mtu); + + /* my_nfv9_logging_info will have a copy of logging_policy + * because, it is quite possible that nfv9 config arrives before + * the corresponding vrfmap is initialized. In such cases + * this copy will be used to update the vrfmap entry + */ + my_nfv9_logging_info->logging_policy = nfv9_conf.session_logging; + + if (nfv9_conf.nfv9_global_collector) { + cnat_nfv9_global_info.cnat_nfv9_global_collector_index = + my_nfv9_logging_info - cnat_nfv9_logging_info_pool; + + pool_foreach (my_vrfmap, cnat_map_by_vrf, ({ + if (my_vrfmap->nfv9_logging_index == EMPTY) { + my_vrfmap->nfv9_logging_index = + cnat_nfv9_global_info.cnat_nfv9_global_collector_index; + } + })); + } else { + u32 my_vrfmap_found = 0; + + FIND_MY_VRF_USING_I_VRF_ID + my_vrfmap = my_vrfmap_temp; + if (my_vrfmap_found) { + if(my_vrfmap->nfv9_logging_index == EMPTY) { + my_vrfmap->nfv9_logging_index = + my_nfv9_logging_info - cnat_nfv9_logging_info_pool; + // my_vrfmap->nf_logging_policy = mp->session_logging; + } else { + cnat_nfv9_logging_info_t *my_nfv9_logging_info_temp = cnat_nfv9_logging_info_pool + my_vrfmap->nfv9_logging_index; + while(my_nfv9_logging_info_temp->nfv9_logging_next_index != EMPTY){ + my_nfv9_logging_info_temp = cnat_nfv9_logging_info_pool + my_nfv9_logging_info_temp->nfv9_logging_next_index; + } + my_nfv9_logging_info_temp->nfv9_logging_next_index = my_nfv9_logging_info - cnat_nfv9_logging_info_pool; + } + } + } + } + + /* Update logging policy */ + my_nfv9_logging_info->logging_policy = nfv9_conf.session_logging; + if (nfv9_conf.nfv9_global_collector) { + if(PLATFORM_DBL_SUPPORT) { + pool_foreach (my_vrfmap, cnat_map_by_vrf, ({ + if (my_vrfmap->nfv9_logging_index == + cnat_nfv9_global_info.cnat_nfv9_global_collector_index) { + my_vrfmap->nf_logging_policy = nfv9_conf.session_logging; + } + })); + } else { + nfv9_conf.rc = CNAT_ERR_NO_SESSION_DB; + } + } else { + if(PLATFORM_DBL_SUPPORT) { + u32 my_vrfmap_found = 0; + my_vrfmap_temp = NULL; + FIND_MY_VRF_USING_I_VRF_ID + my_vrfmap = my_vrfmap_temp; + if (my_vrfmap_found) { + // my_vrfmap->nf_logging_policy = mp->session_logging; + } + } else { + nfv9_conf.rc = CNAT_ERR_NO_SESSION_DB; + } + } + u8 nfv9_logging_policy = 0; + u32 my_vrfmap_found = 0; + my_vrfmap_temp = NULL; + FIND_MY_VRF_USING_I_VRF_ID + my_vrfmap = my_vrfmap_temp; + if (my_vrfmap_found) { + u32 index_curr = my_vrfmap->nfv9_logging_index; + cnat_nfv9_logging_info_t *my_nfv9_logging_info_temp; + while(index_curr != EMPTY) { + my_nfv9_logging_info_temp = cnat_nfv9_logging_info_pool + index_curr; + nfv9_logging_policy = nfv9_logging_policy || my_nfv9_logging_info_temp->logging_policy; + index_curr = (cnat_nfv9_logging_info_pool + index_curr)->nfv9_logging_next_index; + } + my_vrfmap->nf_logging_policy = nfv9_logging_policy; + } + //vlib_cli_output(vm,"Netflow logging policy = %d\n", my_vrfmap->nf_logging_policy); + if(nfv9_get_server_instance(my_nfv9_logging_info, &new_server_info) + != CNAT_SUCCESS) { + vlib_cli_output(vm, "Error to get server instance"); + nfv9_conf.rc = CNAT_ERR_PARSER; + goto done; + } + nfv9_init_pkt_sent_data(my_nfv9_logging_info); + + vlib_cli_output(vm,"Adding NFv9 Logging Succeeded\n"); + nfv9_configured = 1; + + } else { + /*Delete path*/ + if (found) { + /* if found entry then we need to overwrite the my_nfv9_logging_info_tmp + * to my_nfv9_logging_info + */ + my_nfv9_logging_info = my_nfv9_logging_info_tmp; + if (i_vrf == INVALID_UIDX) { + /* + * We are deleting a global collector. Mark the collectors + * in those VRFs using the global collector + */ + pool_foreach (my_vrfmap, cnat_map_by_vrf, ({ + if (my_vrfmap->nfv9_logging_index == + cnat_nfv9_global_info.cnat_nfv9_global_collector_index) { + my_vrfmap->nfv9_logging_index = EMPTY; + } + })); + + cnat_nfv9_global_info.cnat_nfv9_global_collector_index = EMPTY; + } else { + u32 my_vrfmap_found = 0; + my_vrfmap_temp = NULL; + FIND_MY_VRF_USING_I_VRF_ID + my_vrfmap = my_vrfmap_temp; + if (my_vrfmap_found) { + // my_vrfmap->nfv9_logging_index = cnat_nfv9_global_info.cnat_nfv9_global_collector_index; + } + } + if (my_nfv9_logging_info->queued_logging_context || + my_nfv9_logging_info->current_logging_context) { + /* + * If there is a pending context: + * Set the deleted flag to 1. This will ensure + * that the logging info structure gets freed after any + * pending packet get sent + */ + my_nfv9_logging_info->deleted = 1; + } else { + /* + * No pending context, just free the logging info structure + */ + u32 index = my_nfv9_logging_info - cnat_nfv9_logging_info_pool; + if(index == my_vrfmap->nfv9_logging_index) { + /* Deleting the first sever */ + my_vrfmap->nfv9_logging_index = my_nfv9_logging_info->nfv9_logging_next_index; + /* if(my_nfv9_logging_info->nfv9_logging_next_index != EMPTY){ + my_vrfmap->nf_logging_policy = (cnat_nfv9_logging_info_pool + my_nfv9_logging_info->nfv9_logging_next_index)->logging_policy; + } else { + my_vrfmap->nf_logging_policy = EMPTY; + }*/ + } else { + u32 index_curr = my_vrfmap->nfv9_logging_index; + u32 index_prev = EMPTY; + while(index_curr != EMPTY) { + index_prev = index_curr; + index_curr = (cnat_nfv9_logging_info_pool + index_curr)->nfv9_logging_next_index; + if(index == index_curr) + { + (cnat_nfv9_logging_info_pool + index_prev)->nfv9_logging_next_index = (cnat_nfv9_logging_info_pool + index_curr)->nfv9_logging_next_index; + break; + } + } + } + nfv9_delete_server_info(my_nfv9_logging_info); + pool_put(cnat_nfv9_logging_info_pool, my_nfv9_logging_info); + } + + vlib_cli_output(vm, "Deleting NFv9 Logging Succeeded\n"); + /* + * Search across all vrf and check if nfv9 logging is configured. + */ + nfv9_configured = 0; + pool_foreach (my_nfv9_logging_info, cnat_nfv9_logging_info_pool, ({ + nfv9_configured = 1; + break; + })); + } else { + nfv9_conf.rc = CNAT_NO_CONFIG; + vlib_cli_output(vm, "Add NFv9 Logging Failed (2) Non Existent vrf %d\n", + i_vrf); + + } + u8 nfv9_logging_policy = 0; + u32 my_vrfmap_found = 0; + my_vrfmap_temp = NULL; + FIND_MY_VRF_USING_I_VRF_ID + my_vrfmap = my_vrfmap_temp; + if (my_vrfmap_found) { + u32 index_curr = my_vrfmap->nfv9_logging_index; + cnat_nfv9_logging_info_t *my_nfv9_logging_info_temp; + while(index_curr != EMPTY) { + my_nfv9_logging_info_temp = cnat_nfv9_logging_info_pool + index_curr; + nfv9_logging_policy = nfv9_logging_policy || my_nfv9_logging_info_temp->logging_policy; + index_curr = (cnat_nfv9_logging_info_pool + index_curr)->nfv9_logging_next_index; + } + my_vrfmap->nf_logging_policy = nfv9_logging_policy; + } + } + +done: + return 0; +} + +/* config CLIs */ +VLIB_CLI_COMMAND (set_vcgn_map_command) = { + .path = "set vcgn map", + .short_help = "set vcgn map [- ]", + .function = set_vcgn_map_command_fn, +}; + +VLIB_CLI_COMMAND (set_vcgn_inside_command) = { + .path = "set vcgn inside", + .short_help = "set vcgn inside outside ", + .function = set_vcgn_inside_command_fn, +}; + +VLIB_CLI_COMMAND (set_vcgn_tcp_timeout_command) = { + .path = "set vcgn tcp timeout", + .short_help = "set vcgn tcp timeout active <1-65535> init <1-65535>", + .function = set_vcgn_tcp_timeout_command_fn, +}; + +VLIB_CLI_COMMAND (set_vcgn_udp_timeout_command) = { + .path = "set vcgn udp timeout", + .short_help = "set vcgn udp timeout active <1-65535> init <1-65535>", + .function = set_vcgn_udp_timeout_command_fn, +}; + +VLIB_CLI_COMMAND (set_vcgn_icmp_timeout_command) = { + .path = "set vcgn icmp timeout", + .short_help = "set vcgn icmp timeout <1-65535>", + .function = set_vcgn_icmp_timeout_command_fn, +}; + +VLIB_CLI_COMMAND (set_vcgn_protocol_default_timeout_command) = { + .path = "set vcgn default timeout", + .short_help = "set vcgn default timeout protocol ", + .function = set_vcgn_protocol_default_timeout_command_fn, +}; + +VLIB_CLI_COMMAND (set_vcgn_dynamic_port_start_range_command) = { + .path = "set vcgn dynamic port start", + .short_help = "set vcgn dynamic port start <1-65535>", + .function = set_vcgn_dynamic_port_start_range_command_fn, +}; + +VLIB_CLI_COMMAND (set_vcgn_port_limit_command) = { + .path = "set vcgn port limit", + .short_help = "set vcgn port limit <1-65535>", + .function = set_vcgn_port_limit_command_fn, +}; + +VLIB_CLI_COMMAND (set_vcgn_nfv9_logging_cofig_command) = { + .path = "set vcgn nfv9", + .short_help = "set vcgn nfv9 [del] inside " + "server port [refresh-rate ] " + "[timeout ] [pmtu ]", + .function = set_vcgn_nfv9_logging_cofig_command_fn, +}; + + +/* show CLIs */ +VLIB_CLI_COMMAND (show_vcgn_config_command) = { + .path = "show vcgn config", + .short_help = "show vcgn config", + .function = show_vcgn_config_command_fn, +}; + +VLIB_CLI_COMMAND (show_vcgn_stat_command) = { + .path = "show vcgn statistics", + .short_help = "show vcgn statistics", + .function = show_vcgn_stats_command_fn, +}; + +VLIB_CLI_COMMAND (show_vcgn_inside_translation_command) = { + .path = "show vcgn inside-translation", + .short_help = "show vcgn inside-translation protocol " + "interface inside-addr " + "[start-port ] [end-port ]", + .function = show_vcgn_inside_translation_command_fn, +}; + +VLIB_CLI_COMMAND (show_vcgn_outside_translation_command) = { + .path = "show vcgn outside-translation", + .short_help = "show vcgn outside-translation protocol " + "interface outside-addr " + "[start-port ] [end-port ]", + .function = show_vcgn_outside_translation_command_fn, +}; + +static clib_error_t * +vcgn_init (vlib_main_t * vm) +{ + clib_error_t * error = 0; + + if ((error = vlib_call_init_function + (vm, vcgn_classify_init))) + return error; + if ((error = vlib_call_init_function + (vm, cnat_ipv4_udp_inside_input_init))) + return error; + if ((error = vlib_call_init_function + (vm, cnat_ipv4_udp_outside_input_init))) + return error; + if ((error = vlib_call_init_function + (vm, cnat_ipv4_udp_inside_input_exc_init))) + return error; + if ((error = vlib_call_init_function + (vm, cnat_db_scanner_init))) + return error; + if ((error = vlib_call_init_function + (vm, cnat_ipv4_tcp_inside_input_init))) + return error; + if ((error = vlib_call_init_function + (vm, cnat_ipv4_tcp_inside_input_exc_init))) + return error; + if ((error = vlib_call_init_function + (vm, cnat_ipv4_tcp_outside_input_init))) + return error; + if ((error = vlib_call_init_function + (vm, cnat_ipv4_icmp_q_inside_input_init))) + return error; + if ((error = vlib_call_init_function + (vm, cnat_ipv4_icmp_q_inside_input_exc_init))) + return error; + if ((error = vlib_call_init_function + (vm, cnat_ipv4_icmp_q_outside_input_init))) + return error; + if ((error = vlib_call_init_function + (vm, cnat_ipv4_icmp_e_inside_input_init))) + return error; + if ((error = vlib_call_init_function + (vm, cnat_ipv4_icmp_e_outside_input_init))) + return error; + + return error; +} + +/* + * This routine exists to convince the vlib plugin framework that + * we haven't accidentally copied a random .dll into the plugin + * directory. This is used in lieu of VLIB_INIT_FUNCTION(vcgn_init). + * + * Also collects global variable pointers passed from the vpp engine + */ +clib_error_t * +vlib_plugin_register (vlib_main_t * vm, vnet_plugin_handoff_t * h, + int from_early_init) +{ + return vcgn_init(vm); +} diff --git a/plugins/vcgn-plugin/vcgn/vcgn_db.h b/plugins/vcgn-plugin/vcgn/vcgn_db.h new file mode 100644 index 00000000..cd7d835c --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/vcgn_db.h @@ -0,0 +1,117 @@ +/* + *------------------------------------------------------------------ + * vcgn_db.h - translation database definitions + * + * Copyright (c) 2007-2014 Cisco and/or its affiliates. + * 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 __VCGN_DB_H__ +#define __VCGN_DB_H__ + +#include "index_list.h" + +/* + * The key structure. All fields are in NETWORK byte order! + */ +typedef struct { + u32 ipv4; + u16 port; + u16 vrf; //bit0-12:vrf, bit13:unused, bit14-15:protocol +} cnat_db_key_t; + +/* bit14-15:protocol in cnat_db_key_t */ +#define CNAT_INVALID_PROTO 0x0000 +#define CNAT_UDP 0x4000 +#define CNAT_TCP 0x8000 +#define CNAT_ICMP 0xc000 +#define CNAT_VRF_MASK 0x3fff +#define CNAT_PRO_MASK 0xc000 +#define CNAT_PRO_SHIFT 14 + +/* + * Maximum number of VRF entries supported + */ +#define CNAT_MAX_VRFMAP_ENTRIES (CNAT_VRF_MASK + 1) +/* + * for hashing purposes, fetch the key in one instr. + */ +typedef union { + cnat_db_key_t k; + u64 key64; +} cnat_key_t; + +/* + * Main translation database entries. Currently 0x50 = 80 bytes in length. + * Given 20,000,000 entries, it saves nearly 1gb of SDRAM to pack the entries + * and pay the extra prefetch. So, that's what we do. + */ + +typedef struct { + /* 0x00 */ + index_slist_t out2in_hash; /* hash-and-chain, x2 */ + index_slist_t in2out_hash; + + /* 0x08 */ + cnat_key_t out2in_key; /* network-to-user, outside-to-inside key */ + + /* 0x10 */ + cnat_key_t in2out_key; /* user-to-network, inside-to-outside key */ + + /* 0x18 */ + index_dlist_t user_ports; /* per-user translation list */ + + /* 0x20 */ + u32 user_index; /* index of user that owns this entry */ + + /* 0x24 */ + u16 vrfmap_index; /* index of vrfmap */ + + /* 0x26 */ + u16 flags; /* Always need flags... */ +#define CNAT_DB_FLAG_PORT_PAIR (1<<0) +#define CNAT_DB_FLAG_TCP_ACTIVE (1<<1) +#define CNAT_DB_FLAG_ENTRY_FREE (1<<2) +#define CNAT_DB_FLAG_UDP_ACTIVE (1<<3) +#define CNAT_DB_FLAG_STATIC_PORT (1<<4) +#define CNAT_DB_FLAG_ALG_ENTRY (1<<5) + + /* 0x28 */ + u32 dst_ipv4; /* pointer to ipv4 dst list, used in evil mode */ + + /* 0x2C */ + u32 out2in_pkts; /* pkt counters */ + + /* 0x30 */ + u32 in2out_pkts; + + /* 0x34 */ + u32 entry_expires; /* timestamp used to expire translations */ + + /* 0x38 */ + union { /* used by FTP ALG, pkt len delta due to FTP PORT cmd */ + u16 delta; + i8 alg_dlt[2]; /* two delta values, 0 for previous, 1 for current */ + u16 il; /* Used to indicate if interleaved mode is used + in case of RTSP ALG */ + } alg; + + /* 0x 48 */ + u32 tcp_seq_num; /* last tcp (FTP) seq # that has pkt len change due to PORT */ + + cnat_timeout_t destn_key; + + /* 0x4C... last byte -- 72 total */ +} cnat_main_db_entry_t; +#endif -- cgit 1.2.3-korg From 3f0cb9efadb7f85e5ae435a83b55a7e7a331dafd Mon Sep 17 00:00:00 2001 From: Sachin Date: Tue, 9 Aug 2016 14:37:05 +0530 Subject: VPP: NXP dpaa2 platform porting to dpdk-16.07 This patch will temporary add the "dpaa2" driver support in VPP in-built DPDK v16.07 Change-Id: Ieb7005c73bdb72e5eac88e17c21474479ad087f0 Signed-off-by: Sachin --- build-data/platforms/dpaa2.mk | 14 +- ...DPAA2-Poll-Mode-Driver-Support-dpdk-16.07.patch | 40106 +++++++++++++++++++ 2 files changed, 40113 insertions(+), 7 deletions(-) create mode 100644 dpdk/dpdk-16.07_patches/0005-NXP-DPAA2-Poll-Mode-Driver-Support-dpdk-16.07.patch (limited to 'build-data/platforms/dpaa2.mk') diff --git a/build-data/platforms/dpaa2.mk b/build-data/platforms/dpaa2.mk index 7f25d212..0ec627a4 100644 --- a/build-data/platforms/dpaa2.mk +++ b/build-data/platforms/dpaa2.mk @@ -38,7 +38,7 @@ else # compile using internal DPDK + NXP DPAA2 Driver patch dpaa2_dpdk_arch = "armv8a" dpaa2_dpdk_target = "arm64-dpaa2-linuxapp-gcc" -dpaa2_dpdk_make_extra_args = "CROSS=$(dpaa2_target)-" +dpaa2_dpdk_make_extra_args = "CROSS=$(dpaa2_target)- DPDK_PKTMBUF_HEADROOM=256" endif endif @@ -47,20 +47,20 @@ vpp_configure_args_dpaa2 = --with-dpdk --without-ipsec \ vnet_configure_args_dpaa2 = --with-dpdk --without-ipsec \ --without-ipv6sr --with-sysroot=$(SYSROOT) -# Set these parameters carefully. The vlib_buffer_t is 128 bytes, i.e. -vlib_configure_args_dpaa2 = --with-pre-data=128 +# Set these parameters carefully. The vlib_buffer_t is 256 bytes, i.e. +vlib_configure_args_dpaa2 = --with-pre-data=256 dpaa2_debug_TAG_CFLAGS = -g -O2 -DCLIB_DEBUG -fPIC -fstack-protector-all \ - -march=$(MARCH) -Werror + -march=$(MARCH) -Werror -DCLIB_LOG2_CACHE_LINE_BYTES=6 dpaa2_debug_TAG_LDFLAGS = -g -O2 -DCLIB_DEBUG -fstack-protector-all \ - -march=$(MARCH) -Werror + -march=$(MARCH) -Werror -DCLIB_LOG2_CACHE_LINE_BYTES=6 # Use -rdynamic is for stack tracing, O0 for debugging....default is O2 # Use -DCLIB_LOG2_CACHE_LINE_BYTES to change cache line size dpaa2_TAG_CFLAGS = -g -O2 -fPIC -march=$(MARCH) -mcpu=$(dpaa2_mtune) \ - -mtune=$(dpaa2_mtune) -funroll-all-loops -Werror + -mtune=$(dpaa2_mtune) -funroll-all-loops -Werror -DCLIB_LOG2_CACHE_LINE_BYTES=6 dpaa2_TAG_LDFLAGS = -g -O2 -fPIC -march=$(MARCH) -mcpu=$(dpaa2_mtune) \ - -mtune=$(dpaa2_mtune) -funroll-all-loops -Werror + -mtune=$(dpaa2_mtune) -funroll-all-loops -Werror -DCLIB_LOG2_CACHE_LINE_BYTES=6 diff --git a/dpdk/dpdk-16.07_patches/0005-NXP-DPAA2-Poll-Mode-Driver-Support-dpdk-16.07.patch b/dpdk/dpdk-16.07_patches/0005-NXP-DPAA2-Poll-Mode-Driver-Support-dpdk-16.07.patch new file mode 100644 index 00000000..9bd3b2a5 --- /dev/null +++ b/dpdk/dpdk-16.07_patches/0005-NXP-DPAA2-Poll-Mode-Driver-Support-dpdk-16.07.patch @@ -0,0 +1,40106 @@ +From 5a2069b38e85771f3857af390e407360d66cd6ed Mon Sep 17 00:00:00 2001 +From: Sachin Saxena +Date: Fri, 5 Aug 2016 14:06:11 +0530 +Subject: [PATCH 5/5] NXP DPAA2 Poll Mode Driver Support (dpdk-16.07) + + Upstreaming of DPAA2 driver changes is in progress.This patch will + temporary add the support in VPP in-built DPDK. + + Two types of changes: + 1. Driver specfic independent files. No impact on any other functionality. + 2. Changes in common EAL framework. These changes are done in compile time DPAA2 + specific flag, so no impact is expected on other existing features if not + compiling for DPAA2. + +Signed-off-by: Sachin Saxena +--- + config/defconfig_arm64-dpaa2-linuxapp-gcc | 18 +- + drivers/net/Makefile | 1 + + drivers/net/dpaa2/Makefile | 102 + + drivers/net/dpaa2/dpaa2_logs.h | 78 + + drivers/net/dpaa2/mc/dpaiop.c | 457 ++++ + drivers/net/dpaa2/mc/dpbp.c | 432 ++++ + drivers/net/dpaa2/mc/dpci.c | 501 ++++ + drivers/net/dpaa2/mc/dpcon.c | 400 +++ + drivers/net/dpaa2/mc/dpdbg.c | 547 +++++ + drivers/net/dpaa2/mc/dpdcei.c | 449 ++++ + drivers/net/dpaa2/mc/dpdmai.c | 452 ++++ + drivers/net/dpaa2/mc/dpdmux.c | 567 +++++ + drivers/net/dpaa2/mc/dpio.c | 468 ++++ + drivers/net/dpaa2/mc/dpmac.c | 422 ++++ + drivers/net/dpaa2/mc/dpmcp.c | 312 +++ + drivers/net/dpaa2/mc/dpmng.c | 58 + + drivers/net/dpaa2/mc/dpni.c | 1907 +++++++++++++++ + drivers/net/dpaa2/mc/dprc.c | 786 ++++++ + drivers/net/dpaa2/mc/dprtc.c | 509 ++++ + drivers/net/dpaa2/mc/dpseci.c | 502 ++++ + drivers/net/dpaa2/mc/dpsw.c | 1639 +++++++++++++ + drivers/net/dpaa2/mc/fsl_dpaiop.h | 494 ++++ + drivers/net/dpaa2/mc/fsl_dpaiop_cmd.h | 190 ++ + drivers/net/dpaa2/mc/fsl_dpbp.h | 438 ++++ + drivers/net/dpaa2/mc/fsl_dpbp_cmd.h | 172 ++ + drivers/net/dpaa2/mc/fsl_dpci.h | 594 +++++ + drivers/net/dpaa2/mc/fsl_dpci_cmd.h | 200 ++ + drivers/net/dpaa2/mc/fsl_dpcon.h | 407 +++ + drivers/net/dpaa2/mc/fsl_dpcon_cmd.h | 162 ++ + drivers/net/dpaa2/mc/fsl_dpdbg.h | 635 +++++ + drivers/net/dpaa2/mc/fsl_dpdbg_cmd.h | 249 ++ + drivers/net/dpaa2/mc/fsl_dpdcei.h | 515 ++++ + drivers/net/dpaa2/mc/fsl_dpdcei_cmd.h | 182 ++ + drivers/net/dpaa2/mc/fsl_dpdmai.h | 521 ++++ + drivers/net/dpaa2/mc/fsl_dpdmai_cmd.h | 191 ++ + drivers/net/dpaa2/mc/fsl_dpdmux.h | 724 ++++++ + drivers/net/dpaa2/mc/fsl_dpdmux_cmd.h | 256 ++ + drivers/net/dpaa2/mc/fsl_dpio.h | 460 ++++ + drivers/net/dpaa2/mc/fsl_dpio_cmd.h | 184 ++ + drivers/net/dpaa2/mc/fsl_dpkg.h | 174 ++ + drivers/net/dpaa2/mc/fsl_dpmac.h | 593 +++++ + drivers/net/dpaa2/mc/fsl_dpmac_cmd.h | 195 ++ + drivers/net/dpaa2/mc/fsl_dpmcp.h | 332 +++ + drivers/net/dpaa2/mc/fsl_dpmcp_cmd.h | 135 + + drivers/net/dpaa2/mc/fsl_dpmng.h | 74 + + drivers/net/dpaa2/mc/fsl_dpmng_cmd.h | 46 + + drivers/net/dpaa2/mc/fsl_dpni.h | 2581 ++++++++++++++++++++ + drivers/net/dpaa2/mc/fsl_dpni_cmd.h | 1058 ++++++++ + drivers/net/dpaa2/mc/fsl_dprc.h | 1032 ++++++++ + drivers/net/dpaa2/mc/fsl_dprc_cmd.h | 755 ++++++ + drivers/net/dpaa2/mc/fsl_dprtc.h | 434 ++++ + drivers/net/dpaa2/mc/fsl_dprtc_cmd.h | 181 ++ + drivers/net/dpaa2/mc/fsl_dpseci.h | 647 +++++ + drivers/net/dpaa2/mc/fsl_dpseci_cmd.h | 241 ++ + drivers/net/dpaa2/mc/fsl_dpsw.h | 2164 ++++++++++++++++ + drivers/net/dpaa2/mc/fsl_dpsw_cmd.h | 916 +++++++ + drivers/net/dpaa2/mc/fsl_mc_cmd.h | 221 ++ + drivers/net/dpaa2/mc/fsl_mc_sys.h | 98 + + drivers/net/dpaa2/mc/fsl_net.h | 480 ++++ + drivers/net/dpaa2/mc/mc_sys.c | 127 + + drivers/net/dpaa2/qbman/driver/qbman_debug.c | 929 +++++++ + drivers/net/dpaa2/qbman/driver/qbman_debug.h | 140 ++ + drivers/net/dpaa2/qbman/driver/qbman_portal.c | 1441 +++++++++++ + drivers/net/dpaa2/qbman/driver/qbman_portal.h | 270 ++ + drivers/net/dpaa2/qbman/driver/qbman_private.h | 168 ++ + drivers/net/dpaa2/qbman/driver/qbman_sys.h | 373 +++ + drivers/net/dpaa2/qbman/driver/qbman_sys_decl.h | 69 + + drivers/net/dpaa2/qbman/include/compat.h | 637 +++++ + .../dpaa2/qbman/include/drivers/fsl_qbman_base.h | 151 ++ + .../dpaa2/qbman/include/drivers/fsl_qbman_portal.h | 1087 +++++++++ + drivers/net/dpaa2/rte_eth_dpaa2_pvt.h | 330 +++ + drivers/net/dpaa2/rte_eth_dpbp.c | 377 +++ + drivers/net/dpaa2/rte_eth_dpio.c | 336 +++ + drivers/net/dpaa2/rte_eth_dpni.c | 2269 +++++++++++++++++ + drivers/net/dpaa2/rte_eth_dpni_annot.h | 310 +++ + lib/librte_eal/common/eal_private.h | 7 + + lib/librte_eal/linuxapp/eal/Makefile | 4 + + lib/librte_eal/linuxapp/eal/eal.c | 5 + + lib/librte_eal/linuxapp/eal/eal_soc.c | 67 + + lib/librte_eal/linuxapp/eal/eal_vfio_fsl_mc.c | 650 +++++ + lib/librte_eal/linuxapp/eal/eal_vfio_fsl_mc.h | 98 + + lib/librte_mempool/rte_mempool.h | 8 + + mk/rte.app.mk | 1 + + 83 files changed, 39391 insertions(+), 1 deletion(-) + create mode 100644 drivers/net/dpaa2/Makefile + create mode 100644 drivers/net/dpaa2/dpaa2_logs.h + create mode 100644 drivers/net/dpaa2/mc/dpaiop.c + create mode 100644 drivers/net/dpaa2/mc/dpbp.c + create mode 100644 drivers/net/dpaa2/mc/dpci.c + create mode 100644 drivers/net/dpaa2/mc/dpcon.c + create mode 100644 drivers/net/dpaa2/mc/dpdbg.c + create mode 100644 drivers/net/dpaa2/mc/dpdcei.c + create mode 100644 drivers/net/dpaa2/mc/dpdmai.c + create mode 100644 drivers/net/dpaa2/mc/dpdmux.c + create mode 100644 drivers/net/dpaa2/mc/dpio.c + create mode 100644 drivers/net/dpaa2/mc/dpmac.c + create mode 100644 drivers/net/dpaa2/mc/dpmcp.c + create mode 100644 drivers/net/dpaa2/mc/dpmng.c + create mode 100644 drivers/net/dpaa2/mc/dpni.c + create mode 100644 drivers/net/dpaa2/mc/dprc.c + create mode 100644 drivers/net/dpaa2/mc/dprtc.c + create mode 100644 drivers/net/dpaa2/mc/dpseci.c + create mode 100644 drivers/net/dpaa2/mc/dpsw.c + create mode 100644 drivers/net/dpaa2/mc/fsl_dpaiop.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpaiop_cmd.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpbp.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpbp_cmd.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpci.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpci_cmd.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpcon.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpcon_cmd.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpdbg.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpdbg_cmd.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpdcei.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpdcei_cmd.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpdmai.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpdmai_cmd.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpdmux.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpdmux_cmd.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpio.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpio_cmd.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpkg.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpmac.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpmac_cmd.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpmcp.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpmcp_cmd.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpmng.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpmng_cmd.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpni.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpni_cmd.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dprc.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dprc_cmd.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dprtc.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dprtc_cmd.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpseci.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpseci_cmd.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpsw.h + create mode 100644 drivers/net/dpaa2/mc/fsl_dpsw_cmd.h + create mode 100644 drivers/net/dpaa2/mc/fsl_mc_cmd.h + create mode 100644 drivers/net/dpaa2/mc/fsl_mc_sys.h + create mode 100644 drivers/net/dpaa2/mc/fsl_net.h + create mode 100644 drivers/net/dpaa2/mc/mc_sys.c + create mode 100644 drivers/net/dpaa2/qbman/driver/qbman_debug.c + create mode 100644 drivers/net/dpaa2/qbman/driver/qbman_debug.h + create mode 100644 drivers/net/dpaa2/qbman/driver/qbman_portal.c + create mode 100644 drivers/net/dpaa2/qbman/driver/qbman_portal.h + create mode 100644 drivers/net/dpaa2/qbman/driver/qbman_private.h + create mode 100644 drivers/net/dpaa2/qbman/driver/qbman_sys.h + create mode 100644 drivers/net/dpaa2/qbman/driver/qbman_sys_decl.h + create mode 100644 drivers/net/dpaa2/qbman/include/compat.h + create mode 100644 drivers/net/dpaa2/qbman/include/drivers/fsl_qbman_base.h + create mode 100644 drivers/net/dpaa2/qbman/include/drivers/fsl_qbman_portal.h + create mode 100644 drivers/net/dpaa2/rte_eth_dpaa2_pvt.h + create mode 100644 drivers/net/dpaa2/rte_eth_dpbp.c + create mode 100644 drivers/net/dpaa2/rte_eth_dpio.c + create mode 100644 drivers/net/dpaa2/rte_eth_dpni.c + create mode 100644 drivers/net/dpaa2/rte_eth_dpni_annot.h + create mode 100644 lib/librte_eal/linuxapp/eal/eal_soc.c + create mode 100644 lib/librte_eal/linuxapp/eal/eal_vfio_fsl_mc.c + create mode 100644 lib/librte_eal/linuxapp/eal/eal_vfio_fsl_mc.h + +diff --git a/config/defconfig_arm64-dpaa2-linuxapp-gcc b/config/defconfig_arm64-dpaa2-linuxapp-gcc +index 66df54c..e42fa90 100644 +--- a/config/defconfig_arm64-dpaa2-linuxapp-gcc ++++ b/config/defconfig_arm64-dpaa2-linuxapp-gcc +@@ -1,6 +1,6 @@ + # BSD LICENSE + # +-# Copyright(c) 2016 Freescale Semiconductor, Inc. All rights reserved. ++# Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. + # + # Redistribution and use in source and binary forms, with or without + # modification, are permitted provided that the following conditions +@@ -40,3 +40,19 @@ CONFIG_RTE_ARCH_ARM_TUNE="cortex-a57+fp+simd" + # + CONFIG_RTE_MAX_LCORE=8 + CONFIG_RTE_MAX_NUMA_NODES=1 ++ ++CONFIG_RTE_PKTMBUF_HEADROOM=256 ++# ++#Kernel KNI component - disable by default to avoid kernel ++#code dependency ++# ++CONFIG_RTE_KNI_KMOD=n ++ ++# Compile software PMD backed by FSL DPAA2 files ++# ++CONFIG_RTE_LIBRTE_DPAA2_PMD=y ++CONFIG_RTE_LIBRTE_DPAA2_USE_PHYS_IOVA=n ++CONFIG_RTE_LIBRTE_DPAA2_DEBUG_INIT=n ++CONFIG_RTE_LIBRTE_DPAA2_DEBUG_DRIVER=n ++CONFIG_RTE_LIBRTE_ETHDEV_DEBUG=n ++CONFIG_RTE_MBUF_DEFAULT_MEMPOOL_OPS="dpaa2" +diff --git a/drivers/net/Makefile b/drivers/net/Makefile +index bc93230..a71c14a 100644 +--- a/drivers/net/Makefile ++++ b/drivers/net/Makefile +@@ -55,6 +55,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_THUNDERX_NICVF_PMD) += thunderx + DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtio + DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += vmxnet3 + DIRS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += xenvirt ++DIRS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD) += dpaa2 + + ifeq ($(CONFIG_RTE_LIBRTE_VHOST),y) + DIRS-$(CONFIG_RTE_LIBRTE_PMD_VHOST) += vhost +diff --git a/drivers/net/dpaa2/Makefile b/drivers/net/dpaa2/Makefile +new file mode 100644 +index 0000000..3cf1782 +--- /dev/null ++++ b/drivers/net/dpaa2/Makefile +@@ -0,0 +1,102 @@ ++# BSD LICENSE ++# ++# Copyright (c) 2014 Freescale Semiconductor, Inc. All rights reserved. ++# ++# Redistribution and use in source and binary forms, with or without ++# modification, are permitted provided that the following conditions ++# are met: ++# ++# * Redistributions of source code must retain the above copyright ++# notice, this list of conditions and the following disclaimer. ++# * Redistributions in binary form must reproduce the above copyright ++# notice, this list of conditions and the following disclaimer in ++# the documentation and/or other materials provided with the ++# distribution. ++# * Neither the name of Freescale Semiconductor nor the names of its ++# contributors may be used to endorse or promote products derived ++# from this software without specific prior written permission. ++# ++# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ ++include $(RTE_SDK)/mk/rte.vars.mk ++ ++# ++# library name ++# ++LIB = librte_pmd_dpaa2.a ++ ++ifeq ($(CONFIG_RTE_LIBRTE_DPAA2_DEBUG_INIT),y) ++CFLAGS += -O0 -g ++CFLAGS += "-Wno-error" ++else ++CFLAGS += -O3 -g ++CFLAGS += $(WERROR_FLAGS) ++endif ++CFLAGS +=-Wno-strict-aliasing ++CFLAGS +=-Wno-missing-prototypes ++CFLAGS +=-Wno-missing-declarations ++CFLAGS +=-Wno-unused-function ++ ++CFLAGS += -I$(RTE_SDK)/drivers/net/dpaa2/mc ++CFLAGS += -I$(RTE_SDK)/drivers/net/dpaa2/qbman/include ++CFLAGS += -I$(RTE_SDK)/drivers/net/dpaa2/qbman/include/drivers ++CFLAGS += -I$(RTE_SDK)/drivers/net/dpaa2/driver/ ++CFLAGS += -I$(RTE_SDK)/lib/librte_eal/common/include ++CFLAGS += -I$(RTE_SDK)/lib/librte_ether ++CFLAGS += -I$(RTE_SDK)/lib/librte_eal/linuxapp/eal ++ ++EXPORT_MAP := rte_pmd_dpaa2_version.map ++ ++LIBABIVER := 1 ++# ++# all source are stored in SRCS-y ++# ++SRCS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD) += \ ++ mc/dprc.c \ ++ mc/dprtc.o \ ++ mc/dpaiop.c \ ++ mc/dpdbg.o \ ++ mc/dpdcei.c \ ++ mc/dpdmai.c \ ++ mc/dpmac.c \ ++ mc/dpmcp.c \ ++ mc/dpbp.c \ ++ mc/dpio.c \ ++ mc/dpni.c \ ++ mc/dpsw.c \ ++ mc/dpci.c \ ++ mc/dpcon.c \ ++ mc/dpseci.c \ ++ mc/dpmng.c \ ++ mc/dpdmux.c \ ++ mc/mc_sys.c ++ ++# ++# all source are stored in SRCS-y ++# ++SRCS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD) += \ ++ qbman/driver/qbman_portal.c \ ++ qbman/driver/qbman_debug.c ++ ++SRCS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD) += rte_eth_dpni.c ++SRCS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD) += rte_eth_dpio.c ++SRCS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD) += rte_eth_dpbp.c ++ ++# ++# Export include files ++# ++SYMLINK-y-include += ++ ++# this lib depends upon: ++DEPDIRS-y += lib/librte_eal ++include $(RTE_SDK)/mk/rte.lib.mk +diff --git a/drivers/net/dpaa2/dpaa2_logs.h b/drivers/net/dpaa2/dpaa2_logs.h +new file mode 100644 +index 0000000..534d4b5 +--- /dev/null ++++ b/drivers/net/dpaa2/dpaa2_logs.h +@@ -0,0 +1,78 @@ ++/*- ++ * BSD LICENSE ++ * ++ * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * * Neither the name of Freescale Semiconductor, Inc nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#ifndef _DPAA2_LOGS_H_ ++#define _DPAA2_LOGS_H_ ++ ++#define PMD_INIT_LOG(level, fmt, args...) \ ++ RTE_LOG(level, PMD, "%s(): " fmt "\n", __func__, ##args) ++ ++#ifdef RTE_LIBRTE_DPAA2_DEBUG_INIT ++#define PMD_INIT_FUNC_TRACE() PMD_INIT_LOG(DEBUG, " >>") ++#else ++#define PMD_INIT_FUNC_TRACE() do { } while (0) ++#endif ++ ++#ifdef RTE_LIBRTE_DPAA2_DEBUG_RX ++#define PMD_RX_LOG(level, fmt, args...) \ ++ RTE_LOG(level, PMD, "%s(): " fmt "\n", __func__, ## args) ++#else ++#define PMD_RX_LOG(level, fmt, args...) do { } while (0) ++#endif ++ ++#ifdef RTE_LIBRTE_DPAA2_DEBUG_TX ++#define PMD_TX_LOG(level, fmt, args...) \ ++ RTE_LOG(level, PMD, "%s(): " fmt "\n", __func__, ## args) ++#else ++#define PMD_TX_LOG(level, fmt, args...) do { } while (0) ++#endif ++ ++#ifdef RTE_LIBRTE_DPAA2_DEBUG_TX_FREE ++#define PMD_TX_FREE_LOG(level, fmt, args...) \ ++ RTE_LOG(level, PMD, "%s(): " fmt "\n", __func__, ## args) ++#else ++#define PMD_TX_FREE_LOG(level, fmt, args...) do { } while (0) ++#endif ++ ++#ifdef RTE_LIBRTE_DPAA2_DEBUG_DRIVER ++#define PMD_DRV_LOG_RAW(level, fmt, args...) \ ++ RTE_LOG(level, PMD, "%s(): " fmt, __func__, ## args) ++#else ++#define PMD_DRV_LOG_RAW(level, fmt, args...) do { } while (0) ++#endif ++ ++#define PMD_DRV_LOG2(level, fmt, args...) do { } while (0) ++ ++#define PMD_DRV_LOG(level, fmt, args...) \ ++ PMD_DRV_LOG_RAW(level, fmt "\n", ## args) ++ ++#endif /* _DPAA2_LOGS_H_ */ +diff --git a/drivers/net/dpaa2/mc/dpaiop.c b/drivers/net/dpaa2/mc/dpaiop.c +new file mode 100644 +index 0000000..7c1ecff +--- /dev/null ++++ b/drivers/net/dpaa2/mc/dpaiop.c +@@ -0,0 +1,457 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++#include ++#include ++ ++int dpaiop_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpaiop_id, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_OPEN, ++ cmd_flags, ++ 0); ++ DPAIOP_CMD_OPEN(cmd, dpaiop_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return err; ++} ++ ++int dpaiop_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_CLOSE, cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpaiop_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpaiop_cfg *cfg, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ (void)(cfg); /* unused */ ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_CREATE, ++ cmd_flags, ++ 0); ++ DPAIOP_CMD_CREATE(cmd, cfg); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpaiop_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_DESTROY, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpaiop_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_RESET, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpaiop_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpaiop_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_SET_IRQ, ++ cmd_flags, ++ token); ++ ++ DPAIOP_CMD_SET_IRQ(cmd, irq_index, irq_cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpaiop_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpaiop_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_GET_IRQ, ++ cmd_flags, ++ token); ++ ++ DPAIOP_CMD_GET_IRQ(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPAIOP_RSP_GET_IRQ(cmd, *type, irq_cfg); ++ ++ return 0; ++} ++ ++int dpaiop_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_SET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ ++ DPAIOP_CMD_SET_IRQ_ENABLE(cmd, irq_index, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpaiop_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_GET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ ++ DPAIOP_CMD_GET_IRQ_ENABLE(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPAIOP_RSP_GET_IRQ_ENABLE(cmd, *en); ++ ++ return 0; ++} ++ ++int dpaiop_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_SET_IRQ_MASK, ++ cmd_flags, ++ token); ++ ++ DPAIOP_CMD_SET_IRQ_MASK(cmd, irq_index, mask); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpaiop_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_GET_IRQ_MASK, ++ cmd_flags, ++ token); ++ ++ DPAIOP_CMD_GET_IRQ_MASK(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPAIOP_RSP_GET_IRQ_MASK(cmd, *mask); ++ ++ return 0; ++} ++ ++int dpaiop_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_GET_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPAIOP_CMD_GET_IRQ_STATUS(cmd, irq_index, *status); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPAIOP_RSP_GET_IRQ_STATUS(cmd, *status); ++ ++ return 0; ++} ++ ++int dpaiop_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_CLEAR_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPAIOP_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpaiop_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpaiop_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_GET_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPAIOP_RSP_GET_ATTRIBUTES(cmd, attr); ++ ++ return 0; ++} ++ ++int dpaiop_load(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpaiop_load_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_LOAD, ++ cmd_flags, ++ token); ++ DPAIOP_CMD_LOAD(cmd, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpaiop_run(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpaiop_run_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_RUN, ++ cmd_flags, ++ token); ++ DPAIOP_CMD_RUN(cmd, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpaiop_get_sl_version(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpaiop_sl_version *version) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_GET_SL_VERSION, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPAIOP_RSP_GET_SL_VERSION(cmd, version); ++ ++ return 0; ++} ++ ++int dpaiop_get_state(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint32_t *state) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_GET_STATE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPAIOP_RSP_GET_STATE(cmd, *state); ++ ++ return 0; ++} ++ ++int dpaiop_set_time_of_day(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint64_t time_of_day) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_SET_TIME_OF_DAY, ++ cmd_flags, ++ token); ++ ++ DPAIOP_CMD_SET_TIME_OF_DAY(cmd, time_of_day); ++ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpaiop_get_time_of_day(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint64_t *time_of_day) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ cmd.header = mc_encode_cmd_header(DPAIOP_CMDID_GET_TIME_OF_DAY, ++ cmd_flags, ++ token); ++ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ DPAIOP_RSP_GET_TIME_OF_DAY(cmd, *time_of_day); ++ ++ return 0; ++} +diff --git a/drivers/net/dpaa2/mc/dpbp.c b/drivers/net/dpaa2/mc/dpbp.c +new file mode 100644 +index 0000000..87899b8 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/dpbp.c +@@ -0,0 +1,432 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++#include ++#include ++ ++int dpbp_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpbp_id, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_OPEN, ++ cmd_flags, ++ 0); ++ DPBP_CMD_OPEN(cmd, dpbp_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return err; ++} ++ ++int dpbp_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_CLOSE, cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpbp_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpbp_cfg *cfg, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ (void)(cfg); /* unused */ ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_CREATE, ++ cmd_flags, ++ 0); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpbp_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_DESTROY, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpbp_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_ENABLE, cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpbp_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_DISABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpbp_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_IS_ENABLED, cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPBP_RSP_IS_ENABLED(cmd, *en); ++ ++ return 0; ++} ++ ++int dpbp_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_RESET, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpbp_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpbp_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_SET_IRQ, ++ cmd_flags, ++ token); ++ ++ DPBP_CMD_SET_IRQ(cmd, irq_index, irq_cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpbp_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpbp_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_IRQ, ++ cmd_flags, ++ token); ++ ++ DPBP_CMD_GET_IRQ(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPBP_RSP_GET_IRQ(cmd, *type, irq_cfg); ++ ++ return 0; ++} ++ ++int dpbp_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_SET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ ++ DPBP_CMD_SET_IRQ_ENABLE(cmd, irq_index, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpbp_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ ++ DPBP_CMD_GET_IRQ_ENABLE(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPBP_RSP_GET_IRQ_ENABLE(cmd, *en); ++ ++ return 0; ++} ++ ++int dpbp_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_SET_IRQ_MASK, ++ cmd_flags, ++ token); ++ ++ DPBP_CMD_SET_IRQ_MASK(cmd, irq_index, mask); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpbp_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_IRQ_MASK, ++ cmd_flags, ++ token); ++ ++ DPBP_CMD_GET_IRQ_MASK(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPBP_RSP_GET_IRQ_MASK(cmd, *mask); ++ ++ return 0; ++} ++ ++int dpbp_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_IRQ_STATUS, ++ cmd_flags, ++ token); ++ ++ DPBP_CMD_GET_IRQ_STATUS(cmd, irq_index, *status); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPBP_RSP_GET_IRQ_STATUS(cmd, *status); ++ ++ return 0; ++} ++ ++int dpbp_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_CLEAR_IRQ_STATUS, ++ cmd_flags, ++ token); ++ ++ DPBP_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpbp_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpbp_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPBP_RSP_GET_ATTRIBUTES(cmd, attr); ++ ++ return 0; ++} ++ ++int dpbp_set_notifications(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpbp_notification_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_SET_NOTIFICATIONS, ++ cmd_flags, ++ token); ++ ++ DPBP_CMD_SET_NOTIFICATIONS(cmd, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpbp_get_notifications(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpbp_notification_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_NOTIFICATIONS, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPBP_CMD_GET_NOTIFICATIONS(cmd, cfg); ++ ++ return 0; ++} +diff --git a/drivers/net/dpaa2/mc/dpci.c b/drivers/net/dpaa2/mc/dpci.c +new file mode 100644 +index 0000000..2ec02a1 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/dpci.c +@@ -0,0 +1,501 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++#include ++#include ++ ++int dpci_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpci_id, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_OPEN, ++ cmd_flags, ++ 0); ++ DPCI_CMD_OPEN(cmd, dpci_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpci_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_CLOSE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpci_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpci_cfg *cfg, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_CREATE, ++ cmd_flags, ++ 0); ++ DPCI_CMD_CREATE(cmd, cfg); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpci_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_DESTROY, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpci_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_ENABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpci_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_DISABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpci_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_IS_ENABLED, cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPCI_RSP_IS_ENABLED(cmd, *en); ++ ++ return 0; ++} ++ ++int dpci_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_RESET, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpci_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpci_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_SET_IRQ, ++ cmd_flags, ++ token); ++ DPCI_CMD_SET_IRQ(cmd, irq_index, irq_cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpci_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpci_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_GET_IRQ, ++ cmd_flags, ++ token); ++ DPCI_CMD_GET_IRQ(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPCI_RSP_GET_IRQ(cmd, *type, irq_cfg); ++ ++ return 0; ++} ++ ++int dpci_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_SET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPCI_CMD_SET_IRQ_ENABLE(cmd, irq_index, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpci_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_GET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPCI_CMD_GET_IRQ_ENABLE(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPCI_RSP_GET_IRQ_ENABLE(cmd, *en); ++ ++ return 0; ++} ++ ++int dpci_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_SET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPCI_CMD_SET_IRQ_MASK(cmd, irq_index, mask); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpci_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_GET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPCI_CMD_GET_IRQ_MASK(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPCI_RSP_GET_IRQ_MASK(cmd, *mask); ++ ++ return 0; ++} ++ ++int dpci_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_GET_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPCI_CMD_GET_IRQ_STATUS(cmd, irq_index, *status); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPCI_RSP_GET_IRQ_STATUS(cmd, *status); ++ ++ return 0; ++} ++ ++int dpci_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_CLEAR_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPCI_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpci_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpci_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_GET_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPCI_RSP_GET_ATTR(cmd, attr); ++ ++ return 0; ++} ++ ++int dpci_get_peer_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpci_peer_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_GET_PEER_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPCI_RSP_GET_PEER_ATTR(cmd, attr); ++ ++ return 0; ++} ++ ++int dpci_get_link_state(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *up) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_GET_LINK_STATE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPCI_RSP_GET_LINK_STATE(cmd, *up); ++ ++ return 0; ++} ++ ++int dpci_set_rx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t priority, ++ const struct dpci_rx_queue_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_SET_RX_QUEUE, ++ cmd_flags, ++ token); ++ DPCI_CMD_SET_RX_QUEUE(cmd, priority, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpci_get_rx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t priority, ++ struct dpci_rx_queue_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_GET_RX_QUEUE, ++ cmd_flags, ++ token); ++ DPCI_CMD_GET_RX_QUEUE(cmd, priority); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPCI_RSP_GET_RX_QUEUE(cmd, attr); ++ ++ return 0; ++} ++ ++int dpci_get_tx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t priority, ++ struct dpci_tx_queue_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCI_CMDID_GET_TX_QUEUE, ++ cmd_flags, ++ token); ++ DPCI_CMD_GET_TX_QUEUE(cmd, priority); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPCI_RSP_GET_TX_QUEUE(cmd, attr); ++ ++ return 0; ++} +diff --git a/drivers/net/dpaa2/mc/dpcon.c b/drivers/net/dpaa2/mc/dpcon.c +new file mode 100644 +index 0000000..56dbcf7 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/dpcon.c +@@ -0,0 +1,400 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++#include ++#include ++ ++int dpcon_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpcon_id, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_OPEN, ++ cmd_flags, ++ 0); ++ DPCON_CMD_OPEN(cmd, dpcon_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpcon_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_CLOSE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpcon_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpcon_cfg *cfg, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_CREATE, ++ cmd_flags, ++ 0); ++ DPCON_CMD_CREATE(cmd, cfg); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpcon_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_DESTROY, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpcon_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_ENABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpcon_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_DISABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpcon_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_IS_ENABLED, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPCON_RSP_IS_ENABLED(cmd, *en); ++ ++ return 0; ++} ++ ++int dpcon_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_RESET, ++ cmd_flags, token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpcon_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpcon_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_SET_IRQ, ++ cmd_flags, ++ token); ++ DPCON_CMD_SET_IRQ(cmd, irq_index, irq_cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpcon_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpcon_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_GET_IRQ, ++ cmd_flags, ++ token); ++ DPCON_CMD_GET_IRQ(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPCON_RSP_GET_IRQ(cmd, *type, irq_cfg); ++ ++ return 0; ++} ++ ++int dpcon_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_SET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPCON_CMD_SET_IRQ_ENABLE(cmd, irq_index, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpcon_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_GET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPCON_CMD_GET_IRQ_ENABLE(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPCON_RSP_GET_IRQ_ENABLE(cmd, *en); ++ ++ return 0; ++} ++ ++int dpcon_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_SET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPCON_CMD_SET_IRQ_MASK(cmd, irq_index, mask); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpcon_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_GET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPCON_CMD_GET_IRQ_MASK(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPCON_RSP_GET_IRQ_MASK(cmd, *mask); ++ ++ return 0; ++} ++ ++int dpcon_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_GET_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPCON_CMD_GET_IRQ_STATUS(cmd, irq_index, *status); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPCON_RSP_GET_IRQ_STATUS(cmd, *status); ++ ++ return 0; ++} ++ ++int dpcon_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_CLEAR_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPCON_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpcon_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpcon_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_GET_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPCON_RSP_GET_ATTR(cmd, attr); ++ ++ return 0; ++} ++ ++int dpcon_set_notification(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpcon_notification_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPCON_CMDID_SET_NOTIFICATION, ++ cmd_flags, ++ token); ++ DPCON_CMD_SET_NOTIFICATION(cmd, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} +diff --git a/drivers/net/dpaa2/mc/dpdbg.c b/drivers/net/dpaa2/mc/dpdbg.c +new file mode 100644 +index 0000000..6f2a08d +--- /dev/null ++++ b/drivers/net/dpaa2/mc/dpdbg.c +@@ -0,0 +1,547 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++#include ++#include ++ ++int dpdbg_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpdbg_id, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_OPEN, ++ cmd_flags, ++ 0); ++ DPDBG_CMD_OPEN(cmd, dpdbg_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return err; ++} ++ ++int dpdbg_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_CLOSE, cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdbg_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpdbg_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_GET_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDBG_RSP_GET_ATTRIBUTES(cmd, attr); ++ ++ return 0; ++} ++ ++int dpdbg_get_dpni_info(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpni_id, ++ struct dpdbg_dpni_info *info) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_GET_DPNI_INFO, ++ cmd_flags, ++ token); ++ DPDBG_CMD_GET_DPNI_INFO(cmd, dpni_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDBG_RSP_GET_DPNI_INFO(cmd, info); ++ ++ return 0; ++} ++ ++int dpdbg_get_dpni_priv_tx_conf_fqid(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpni_id, ++ uint8_t sender_id, ++ uint32_t *fqid) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header( ++ DPDBG_CMDID_GET_DPNI_PRIV_TX_CONF_FQID, ++ cmd_flags, ++ token); ++ DPDBG_CMD_GET_DPNI_PRIV_TX_CONF_FQID(cmd, dpni_id, sender_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDBG_RSP_GET_DPNI_PRIV_TX_CONF_FQID(cmd, *fqid); ++ ++ return 0; ++} ++ ++int dpdbg_get_dpcon_info(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpcon_id, ++ struct dpdbg_dpcon_info *info) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_GET_DPCON_INFO, ++ cmd_flags, ++ token); ++ DPDBG_CMD_GET_DPCON_INFO(cmd, dpcon_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDBG_RSP_GET_DPCON_INFO(cmd, info); ++ ++ return 0; ++} ++ ++int dpdbg_get_dpbp_info(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpbp_id, ++ struct dpdbg_dpbp_info *info) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_GET_DPBP_INFO, ++ cmd_flags, ++ token); ++ DPDBG_CMD_GET_DPBP_INFO(cmd, dpbp_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDBG_RSP_GET_DPBP_INFO(cmd, info); ++ ++ return 0; ++} ++ ++int dpdbg_get_dpci_fqid(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpci_id, ++ uint8_t priority, ++ uint32_t *fqid) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_GET_DPBP_INFO, ++ cmd_flags, ++ token); ++ DPDBG_CMD_GET_DPCI_FQID(cmd, dpci_id, priority); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDBG_RSP_GET_DPCI_FQID(cmd, *fqid); ++ ++ return 0; ++} ++ ++int dpdbg_prepare_ctlu_global_rule(struct dpkg_profile_cfg *dpkg_rule, ++ uint8_t *rule_buf) ++{ ++ int i, j; ++ int offset = 0; ++ int param = 1; ++ uint64_t *params = (uint64_t *)rule_buf; ++ ++ if (!rule_buf || !dpkg_rule) ++ return -EINVAL; ++ ++ params[0] |= mc_enc(0, 8, dpkg_rule->num_extracts); ++ params[0] = cpu_to_le64(params[0]); ++ ++ if (dpkg_rule->num_extracts >= DPKG_MAX_NUM_OF_EXTRACTS) ++ return -EINVAL; ++ ++ for (i = 0; i < dpkg_rule->num_extracts; i++) { ++ switch (dpkg_rule->extracts[i].type) { ++ case DPKG_EXTRACT_FROM_HDR: ++ params[param] |= mc_enc(0, 8, ++ dpkg_rule->extracts[i].extract.from_hdr.prot); ++ params[param] |= mc_enc(8, 4, ++ dpkg_rule->extracts[i].extract.from_hdr.type); ++ params[param] |= mc_enc(16, 8, ++ dpkg_rule->extracts[i].extract.from_hdr.size); ++ params[param] |= mc_enc(24, 8, ++ dpkg_rule->extracts[i].extract.from_hdr.offset); ++ params[param] |= mc_enc(32, 32, ++ dpkg_rule->extracts[i].extract.from_hdr.field); ++ params[param] = cpu_to_le64(params[param]); ++ param++; ++ params[param] |= mc_enc(0, 8, ++ dpkg_rule->extracts[i].extract. ++ from_hdr.hdr_index); ++ break; ++ case DPKG_EXTRACT_FROM_DATA: ++ params[param] |= mc_enc(16, 8, ++ dpkg_rule->extracts[i].extract.from_data.size); ++ params[param] |= mc_enc(24, 8, ++ dpkg_rule->extracts[i].extract. ++ from_data.offset); ++ params[param] = cpu_to_le64(params[param]); ++ param++; ++ break; ++ case DPKG_EXTRACT_FROM_PARSE: ++ params[param] |= mc_enc(16, 8, ++ dpkg_rule->extracts[i].extract.from_parse.size); ++ params[param] |= mc_enc(24, 8, ++ dpkg_rule->extracts[i].extract. ++ from_parse.offset); ++ params[param] = cpu_to_le64(params[param]); ++ param++; ++ break; ++ default: ++ return -EINVAL; ++ } ++ params[param] |= mc_enc( ++ 24, 8, dpkg_rule->extracts[i].num_of_byte_masks); ++ params[param] |= mc_enc(32, 4, dpkg_rule->extracts[i].type); ++ params[param] = cpu_to_le64(params[param]); ++ param++; ++ for (offset = 0, j = 0; ++ j < DPKG_NUM_OF_MASKS; ++ offset += 16, j++) { ++ params[param] |= mc_enc( ++ (offset), 8, ++ dpkg_rule->extracts[i].masks[j].mask); ++ params[param] |= mc_enc( ++ (offset + 8), 8, ++ dpkg_rule->extracts[i].masks[j].offset); ++ } ++ params[param] = cpu_to_le64(params[param]); ++ param++; ++ } ++ return 0; ++} ++ ++int dpdbg_set_ctlu_global_marking(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t marking, ++ struct dpdbg_rule_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_SET_CTLU_GLOBAL_MARKING, ++ cmd_flags, ++ token); ++ DPDBG_CMD_SET_CTLU_GLOBAL_MARKING(cmd, marking, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdbg_set_dpni_rx_marking(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpni_id, ++ struct dpdbg_dpni_rx_marking_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_SET_DPNI_RX_MARKING, ++ cmd_flags, ++ token); ++ DPDBG_CMD_SET_DPNI_RX_MARKING(cmd, dpni_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdbg_set_dpni_tx_conf_marking(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpni_id, ++ uint16_t sender_id, ++ uint8_t marking) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_SET_DPNI_TX_CONF_MARKING, ++ cmd_flags, ++ token); ++ DPDBG_CMD_SET_DPNI_TX_CONF_MARKING(cmd, dpni_id, sender_id, marking); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdbg_set_dpio_marking(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpio_id, ++ uint8_t marking) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_SET_DPIO_MARKING, ++ cmd_flags, ++ token); ++ DPDBG_CMD_SET_DPIO_MARKING(cmd, dpio_id, marking); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdbg_set_ctlu_global_trace(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpdbg_rule_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_SET_CTLU_GLOBAL_TRACE, ++ cmd_flags, ++ token); ++ DPDBG_CMD_SET_CTLU_GLOBAL_TRACE(cmd, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdbg_set_dpio_trace(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpio_id, ++ struct dpdbg_dpio_trace_cfg ++ trace_point[DPDBG_NUM_OF_DPIO_TRACE_POINTS]) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_SET_DPIO_TRACE, ++ cmd_flags, ++ token); ++ DPDBG_CMD_SET_DPIO_TRACE(cmd, dpio_id, trace_point); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdbg_set_dpni_rx_trace(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpni_id, ++ struct dpdbg_dpni_rx_trace_cfg *trace_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_SET_DPNI_RX_TRACE, ++ cmd_flags, ++ token); ++ DPDBG_CMD_SET_DPNI_RX_TRACE(cmd, dpni_id, trace_cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdbg_set_dpni_tx_trace(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpni_id, ++ uint16_t sender_id, ++ struct dpdbg_dpni_tx_trace_cfg *trace_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_SET_DPNI_TX_TRACE, ++ cmd_flags, ++ token); ++ DPDBG_CMD_SET_DPNI_TX_TRACE(cmd, dpni_id, sender_id, trace_cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdbg_set_dpcon_trace(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpcon_id, ++ struct dpdbg_dpcon_trace_cfg ++ trace_point[DPDBG_NUM_OF_DPCON_TRACE_POINTS]) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_SET_DPCON_TRACE, ++ cmd_flags, ++ token); ++ DPDBG_CMD_SET_DPCON_TRACE(cmd, dpcon_id, trace_point); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdbg_set_dpseci_trace(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpseci_id, ++ struct dpdbg_dpseci_trace_cfg ++ trace_point[DPDBG_NUM_OF_DPSECI_TRACE_POINTS]) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_SET_DPSECI_TRACE, ++ cmd_flags, ++ token); ++ DPDBG_CMD_SET_DPSECI_TRACE(cmd, dpseci_id, trace_point); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdbg_get_dpmac_counter(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpmac_id, ++ enum dpmac_counter counter_type, ++ uint64_t *counter) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_GET_DPMAC_COUNTER, ++ cmd_flags, ++ token); ++ DPDBG_CMD_GET_DPMAC_COUNTER(cmd, dpmac_id, counter_type); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDBG_RSP_GET_DPMAC_COUNTER(cmd, *counter); ++ ++ return 0; ++} ++ ++int dpdbg_get_dpni_counter(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpni_id, ++ enum dpni_counter counter_type, ++ uint64_t *counter) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDBG_CMDID_GET_DPNI_COUNTER, ++ cmd_flags, ++ token); ++ DPDBG_CMD_GET_DPMAC_COUNTER(cmd, dpni_id, counter_type); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDBG_RSP_GET_DPNI_COUNTER(cmd, *counter); ++ ++ return 0; ++} +diff --git a/drivers/net/dpaa2/mc/dpdcei.c b/drivers/net/dpaa2/mc/dpdcei.c +new file mode 100644 +index 0000000..a5c4c47 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/dpdcei.c +@@ -0,0 +1,449 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++#include ++#include ++ ++int dpdcei_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpdcei_id, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_OPEN, ++ cmd_flags, ++ 0); ++ DPDCEI_CMD_OPEN(cmd, dpdcei_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpdcei_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_CLOSE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdcei_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpdcei_cfg *cfg, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_CREATE, ++ cmd_flags, ++ 0); ++ DPDCEI_CMD_CREATE(cmd, cfg); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpdcei_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_DESTROY, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdcei_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_ENABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdcei_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_DISABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdcei_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_IS_ENABLED, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDCEI_RSP_IS_ENABLED(cmd, *en); ++ ++ return 0; ++} ++ ++int dpdcei_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_RESET, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdcei_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpdcei_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_GET_IRQ, ++ cmd_flags, ++ token); ++ DPDCEI_CMD_GET_IRQ(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDCEI_RSP_GET_IRQ(cmd, *type, irq_cfg); ++ ++ return 0; ++} ++ ++int dpdcei_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpdcei_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_SET_IRQ, ++ cmd_flags, ++ token); ++ DPDCEI_CMD_SET_IRQ(cmd, irq_index, irq_cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdcei_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_GET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPDCEI_CMD_GET_IRQ_ENABLE(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDCEI_RSP_GET_IRQ_ENABLE(cmd, *en); ++ ++ return 0; ++} ++ ++int dpdcei_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_SET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPDCEI_CMD_SET_IRQ_ENABLE(cmd, irq_index, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdcei_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_GET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPDCEI_CMD_GET_IRQ_MASK(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDCEI_RSP_GET_IRQ_MASK(cmd, *mask); ++ ++ return 0; ++} ++ ++int dpdcei_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_SET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPDCEI_CMD_SET_IRQ_MASK(cmd, irq_index, mask); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdcei_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_GET_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPDCEI_CMD_GET_IRQ_STATUS(cmd, irq_index, *status); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDCEI_RSP_GET_IRQ_STATUS(cmd, *status); ++ ++ return 0; ++} ++ ++int dpdcei_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_CLEAR_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPDCEI_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdcei_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpdcei_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_GET_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDCEI_RSP_GET_ATTR(cmd, attr); ++ ++ return 0; ++} ++ ++int dpdcei_set_rx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpdcei_rx_queue_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_SET_RX_QUEUE, ++ cmd_flags, ++ token); ++ DPDCEI_CMD_SET_RX_QUEUE(cmd, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdcei_get_rx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpdcei_rx_queue_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_GET_RX_QUEUE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDCEI_RSP_GET_RX_QUEUE(cmd, attr); ++ ++ return 0; ++} ++ ++int dpdcei_get_tx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpdcei_tx_queue_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDCEI_CMDID_GET_TX_QUEUE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDCEI_RSP_GET_TX_QUEUE(cmd, attr); ++ ++ return 0; ++} +diff --git a/drivers/net/dpaa2/mc/dpdmai.c b/drivers/net/dpaa2/mc/dpdmai.c +new file mode 100644 +index 0000000..154d2c6 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/dpdmai.c +@@ -0,0 +1,452 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++#include ++#include ++ ++int dpdmai_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpdmai_id, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_OPEN, ++ cmd_flags, ++ 0); ++ DPDMAI_CMD_OPEN(cmd, dpdmai_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpdmai_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_CLOSE, ++ cmd_flags, token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmai_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpdmai_cfg *cfg, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_CREATE, ++ cmd_flags, ++ 0); ++ DPDMAI_CMD_CREATE(cmd, cfg); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpdmai_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_DESTROY, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmai_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_ENABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmai_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_DISABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmai_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_IS_ENABLED, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDMAI_RSP_IS_ENABLED(cmd, *en); ++ ++ return 0; ++} ++ ++int dpdmai_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_RESET, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmai_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpdmai_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_GET_IRQ, ++ cmd_flags, ++ token); ++ DPDMAI_CMD_GET_IRQ(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDMAI_RSP_GET_IRQ(cmd, *type, irq_cfg); ++ ++ return 0; ++} ++ ++int dpdmai_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpdmai_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_SET_IRQ, ++ cmd_flags, ++ token); ++ DPDMAI_CMD_SET_IRQ(cmd, irq_index, irq_cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmai_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_GET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPDMAI_CMD_GET_IRQ_ENABLE(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDMAI_RSP_GET_IRQ_ENABLE(cmd, *en); ++ ++ return 0; ++} ++ ++int dpdmai_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_SET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPDMAI_CMD_SET_IRQ_ENABLE(cmd, irq_index, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmai_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_GET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPDMAI_CMD_GET_IRQ_MASK(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDMAI_RSP_GET_IRQ_MASK(cmd, *mask); ++ ++ return 0; ++} ++ ++int dpdmai_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_SET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPDMAI_CMD_SET_IRQ_MASK(cmd, irq_index, mask); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmai_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_GET_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPDMAI_CMD_GET_IRQ_STATUS(cmd, irq_index, *status); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDMAI_RSP_GET_IRQ_STATUS(cmd, *status); ++ ++ return 0; ++} ++ ++int dpdmai_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_CLEAR_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPDMAI_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmai_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpdmai_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_GET_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDMAI_RSP_GET_ATTR(cmd, attr); ++ ++ return 0; ++} ++ ++int dpdmai_set_rx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t priority, ++ const struct dpdmai_rx_queue_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_SET_RX_QUEUE, ++ cmd_flags, ++ token); ++ DPDMAI_CMD_SET_RX_QUEUE(cmd, priority, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmai_get_rx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t priority, struct dpdmai_rx_queue_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_GET_RX_QUEUE, ++ cmd_flags, ++ token); ++ DPDMAI_CMD_GET_RX_QUEUE(cmd, priority); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDMAI_RSP_GET_RX_QUEUE(cmd, attr); ++ ++ return 0; ++} ++ ++int dpdmai_get_tx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t priority, ++ struct dpdmai_tx_queue_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMAI_CMDID_GET_TX_QUEUE, ++ cmd_flags, ++ token); ++ DPDMAI_CMD_GET_TX_QUEUE(cmd, priority); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDMAI_RSP_GET_TX_QUEUE(cmd, attr); ++ ++ return 0; ++} +diff --git a/drivers/net/dpaa2/mc/dpdmux.c b/drivers/net/dpaa2/mc/dpdmux.c +new file mode 100644 +index 0000000..dc07608 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/dpdmux.c +@@ -0,0 +1,567 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++#include ++#include ++ ++int dpdmux_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpdmux_id, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_OPEN, ++ cmd_flags, ++ 0); ++ DPDMUX_CMD_OPEN(cmd, dpdmux_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpdmux_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_CLOSE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmux_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpdmux_cfg *cfg, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_CREATE, ++ cmd_flags, ++ 0); ++ DPDMUX_CMD_CREATE(cmd, cfg); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpdmux_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_DESTROY, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmux_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_ENABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmux_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_DISABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmux_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IS_ENABLED, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDMUX_RSP_IS_ENABLED(cmd, *en); ++ ++ return 0; ++} ++ ++int dpdmux_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_RESET, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmux_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpdmux_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_SET_IRQ, ++ cmd_flags, ++ token); ++ DPDMUX_CMD_SET_IRQ(cmd, irq_index, irq_cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmux_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpdmux_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_GET_IRQ, ++ cmd_flags, ++ token); ++ DPDMUX_CMD_GET_IRQ(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDMUX_RSP_GET_IRQ(cmd, *type, irq_cfg); ++ ++ return 0; ++} ++ ++int dpdmux_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_SET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPDMUX_CMD_SET_IRQ_ENABLE(cmd, irq_index, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmux_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_GET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPDMUX_CMD_GET_IRQ_ENABLE(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDMUX_RSP_GET_IRQ_ENABLE(cmd, *en); ++ ++ return 0; ++} ++ ++int dpdmux_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_SET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPDMUX_CMD_SET_IRQ_MASK(cmd, irq_index, mask); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmux_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_GET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPDMUX_CMD_GET_IRQ_MASK(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDMUX_RSP_GET_IRQ_MASK(cmd, *mask); ++ ++ return 0; ++} ++ ++int dpdmux_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_GET_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPDMUX_CMD_GET_IRQ_STATUS(cmd, irq_index, *status); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDMUX_RSP_GET_IRQ_STATUS(cmd, *status); ++ ++ return 0; ++} ++ ++int dpdmux_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_CLEAR_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPDMUX_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmux_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpdmux_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_GET_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDMUX_RSP_GET_ATTR(cmd, attr); ++ ++ return 0; ++} ++ ++int dpdmux_ul_set_max_frame_length(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t max_frame_length) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_UL_SET_MAX_FRAME_LENGTH, ++ cmd_flags, ++ token); ++ DPDMUX_CMD_UL_SET_MAX_FRAME_LENGTH(cmd, max_frame_length); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmux_ul_reset_counters(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_UL_RESET_COUNTERS, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmux_if_set_accepted_frames(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpdmux_accepted_frames *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_SET_ACCEPTED_FRAMES, ++ cmd_flags, ++ token); ++ DPDMUX_CMD_IF_SET_ACCEPTED_FRAMES(cmd, if_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmux_if_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ struct dpdmux_if_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_GET_ATTR, ++ cmd_flags, ++ token); ++ DPDMUX_CMD_IF_GET_ATTR(cmd, if_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDMUX_RSP_IF_GET_ATTR(cmd, attr); ++ ++ return 0; ++} ++ ++int dpdmux_if_remove_l2_rule(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpdmux_l2_rule *rule) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_REMOVE_L2_RULE, ++ cmd_flags, ++ token); ++ DPDMUX_CMD_IF_REMOVE_L2_RULE(cmd, if_id, rule); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmux_if_add_l2_rule(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpdmux_l2_rule *rule) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_ADD_L2_RULE, ++ cmd_flags, ++ token); ++ DPDMUX_CMD_IF_ADD_L2_RULE(cmd, if_id, rule); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmux_if_get_counter(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ enum dpdmux_counter_type counter_type, ++ uint64_t *counter) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_GET_COUNTER, ++ cmd_flags, ++ token); ++ DPDMUX_CMD_IF_GET_COUNTER(cmd, if_id, counter_type); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDMUX_RSP_IF_GET_COUNTER(cmd, *counter); ++ ++ return 0; ++} ++ ++int dpdmux_if_set_link_cfg(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ struct dpdmux_link_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_SET_LINK_CFG, ++ cmd_flags, ++ token); ++ DPDMUX_CMD_IF_SET_LINK_CFG(cmd, if_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpdmux_if_get_link_state(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ struct dpdmux_link_state *state) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_GET_LINK_STATE, ++ cmd_flags, ++ token); ++ DPDMUX_CMD_IF_GET_LINK_STATE(cmd, if_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPDMUX_RSP_IF_GET_LINK_STATE(cmd, state); ++ ++ return 0; ++} +diff --git a/drivers/net/dpaa2/mc/dpio.c b/drivers/net/dpaa2/mc/dpio.c +new file mode 100644 +index 0000000..f511e29 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/dpio.c +@@ -0,0 +1,468 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++#include ++#include ++ ++int dpio_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpio_id, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_OPEN, ++ cmd_flags, ++ 0); ++ DPIO_CMD_OPEN(cmd, dpio_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpio_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_CLOSE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpio_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpio_cfg *cfg, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_CREATE, ++ cmd_flags, ++ 0); ++ DPIO_CMD_CREATE(cmd, cfg); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpio_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_DESTROY, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpio_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_ENABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpio_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_DISABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpio_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_IS_ENABLED, cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPIO_RSP_IS_ENABLED(cmd, *en); ++ ++ return 0; ++} ++ ++int dpio_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_RESET, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpio_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpio_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_SET_IRQ, ++ cmd_flags, ++ token); ++ DPIO_CMD_SET_IRQ(cmd, irq_index, irq_cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpio_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpio_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_GET_IRQ, ++ cmd_flags, ++ token); ++ DPIO_CMD_GET_IRQ(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPIO_RSP_GET_IRQ(cmd, *type, irq_cfg); ++ ++ return 0; ++} ++ ++int dpio_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_SET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPIO_CMD_SET_IRQ_ENABLE(cmd, irq_index, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpio_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_GET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPIO_CMD_GET_IRQ_ENABLE(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPIO_RSP_GET_IRQ_ENABLE(cmd, *en); ++ ++ return 0; ++} ++ ++int dpio_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_SET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPIO_CMD_SET_IRQ_MASK(cmd, irq_index, mask); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpio_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_GET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPIO_CMD_GET_IRQ_MASK(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPIO_RSP_GET_IRQ_MASK(cmd, *mask); ++ ++ return 0; ++} ++ ++int dpio_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_GET_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPIO_CMD_GET_IRQ_STATUS(cmd, irq_index, *status); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPIO_RSP_GET_IRQ_STATUS(cmd, *status); ++ ++ return 0; ++} ++ ++int dpio_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_CLEAR_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPIO_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpio_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpio_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_GET_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPIO_RSP_GET_ATTR(cmd, attr); ++ ++ return 0; ++} ++ ++int dpio_set_stashing_destination(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t sdest) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_SET_STASHING_DEST, ++ cmd_flags, ++ token); ++ DPIO_CMD_SET_STASHING_DEST(cmd, sdest); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpio_get_stashing_destination(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t *sdest) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_GET_STASHING_DEST, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPIO_RSP_GET_STASHING_DEST(cmd, *sdest); ++ ++ return 0; ++} ++ ++int dpio_add_static_dequeue_channel(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpcon_id, ++ uint8_t *channel_index) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPIO_CMDID_ADD_STATIC_DEQUEUE_CHANNEL, ++ cmd_flags, ++ token); ++ DPIO_CMD_ADD_STATIC_DEQUEUE_CHANNEL(cmd, dpcon_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPIO_RSP_ADD_STATIC_DEQUEUE_CHANNEL(cmd, *channel_index); ++ ++ return 0; ++} ++ ++int dpio_remove_static_dequeue_channel(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpcon_id) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header( ++ DPIO_CMDID_REMOVE_STATIC_DEQUEUE_CHANNEL, ++ cmd_flags, ++ token); ++ DPIO_CMD_REMOVE_STATIC_DEQUEUE_CHANNEL(cmd, dpcon_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} +diff --git a/drivers/net/dpaa2/mc/dpmac.c b/drivers/net/dpaa2/mc/dpmac.c +new file mode 100644 +index 0000000..f31d949 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/dpmac.c +@@ -0,0 +1,422 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++#include ++#include ++ ++int dpmac_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpmac_id, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_OPEN, ++ cmd_flags, ++ 0); ++ DPMAC_CMD_OPEN(cmd, dpmac_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return err; ++} ++ ++int dpmac_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CLOSE, cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpmac_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpmac_cfg *cfg, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CREATE, ++ cmd_flags, ++ 0); ++ DPMAC_CMD_CREATE(cmd, cfg); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpmac_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_DESTROY, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpmac_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpmac_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_IRQ, ++ cmd_flags, ++ token); ++ DPMAC_CMD_SET_IRQ(cmd, irq_index, irq_cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpmac_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpmac_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_IRQ, ++ cmd_flags, ++ token); ++ DPMAC_CMD_GET_IRQ(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPMAC_RSP_GET_IRQ(cmd, *type, irq_cfg); ++ ++ return 0; ++} ++ ++int dpmac_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPMAC_CMD_SET_IRQ_ENABLE(cmd, irq_index, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpmac_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPMAC_CMD_GET_IRQ_ENABLE(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPMAC_RSP_GET_IRQ_ENABLE(cmd, *en); ++ ++ return 0; ++} ++ ++int dpmac_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPMAC_CMD_SET_IRQ_MASK(cmd, irq_index, mask); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpmac_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPMAC_CMD_GET_IRQ_MASK(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPMAC_RSP_GET_IRQ_MASK(cmd, *mask); ++ ++ return 0; ++} ++ ++int dpmac_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPMAC_CMD_GET_IRQ_STATUS(cmd, irq_index, *status); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPMAC_RSP_GET_IRQ_STATUS(cmd, *status); ++ ++ return 0; ++} ++ ++int dpmac_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CLEAR_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPMAC_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpmac_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpmac_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPMAC_RSP_GET_ATTRIBUTES(cmd, attr); ++ ++ return 0; ++} ++ ++int dpmac_mdio_read(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpmac_mdio_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_MDIO_READ, ++ cmd_flags, ++ token); ++ DPMAC_CMD_MDIO_READ(cmd, cfg); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPMAC_RSP_MDIO_READ(cmd, cfg->data); ++ ++ return 0; ++} ++ ++int dpmac_mdio_write(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpmac_mdio_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_MDIO_WRITE, ++ cmd_flags, ++ token); ++ DPMAC_CMD_MDIO_WRITE(cmd, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpmac_get_link_cfg(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpmac_link_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err = 0; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_LINK_CFG, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ DPMAC_RSP_GET_LINK_CFG(cmd, cfg); ++ ++ return 0; ++} ++ ++int dpmac_set_link_state(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpmac_link_state *link_state) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_LINK_STATE, ++ cmd_flags, ++ token); ++ DPMAC_CMD_SET_LINK_STATE(cmd, link_state); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpmac_get_counter(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ enum dpmac_counter type, ++ uint64_t *counter) ++{ ++ struct mc_command cmd = { 0 }; ++ int err = 0; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_COUNTER, ++ cmd_flags, ++ token); ++ DPMAC_CMD_GET_COUNTER(cmd, type); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ DPMAC_RSP_GET_COUNTER(cmd, *counter); ++ ++ return 0; ++} +diff --git a/drivers/net/dpaa2/mc/dpmcp.c b/drivers/net/dpaa2/mc/dpmcp.c +new file mode 100644 +index 0000000..dfd84b8 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/dpmcp.c +@@ -0,0 +1,312 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++#include ++#include ++ ++int dpmcp_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpmcp_id, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_OPEN, ++ cmd_flags, ++ 0); ++ DPMCP_CMD_OPEN(cmd, dpmcp_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return err; ++} ++ ++int dpmcp_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_CLOSE, cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpmcp_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpmcp_cfg *cfg, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_CREATE, ++ cmd_flags, ++ 0); ++ DPMCP_CMD_CREATE(cmd, cfg); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpmcp_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_DESTROY, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpmcp_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_RESET, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpmcp_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpmcp_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_SET_IRQ, ++ cmd_flags, ++ token); ++ DPMCP_CMD_SET_IRQ(cmd, irq_index, irq_cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpmcp_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpmcp_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_IRQ, ++ cmd_flags, ++ token); ++ DPMCP_CMD_GET_IRQ(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPMCP_RSP_GET_IRQ(cmd, *type, irq_cfg); ++ ++ return 0; ++} ++ ++int dpmcp_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_SET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPMCP_CMD_SET_IRQ_ENABLE(cmd, irq_index, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpmcp_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPMCP_CMD_GET_IRQ_ENABLE(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPMCP_RSP_GET_IRQ_ENABLE(cmd, *en); ++ ++ return 0; ++} ++ ++int dpmcp_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_SET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPMCP_CMD_SET_IRQ_MASK(cmd, irq_index, mask); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpmcp_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPMCP_CMD_GET_IRQ_MASK(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPMCP_RSP_GET_IRQ_MASK(cmd, *mask); ++ ++ return 0; ++} ++ ++int dpmcp_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPMCP_CMD_GET_IRQ_STATUS(cmd, irq_index, *status); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPMCP_RSP_GET_IRQ_STATUS(cmd, *status); ++ ++ return 0; ++} ++ ++int dpmcp_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpmcp_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPMCP_RSP_GET_ATTRIBUTES(cmd, attr); ++ ++ return 0; ++} +diff --git a/drivers/net/dpaa2/mc/dpmng.c b/drivers/net/dpaa2/mc/dpmng.c +new file mode 100644 +index 0000000..cac5ba5 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/dpmng.c +@@ -0,0 +1,58 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++#include ++#include ++ ++int mc_get_version(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ struct mc_version *mc_ver_info) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPMNG_CMDID_GET_VERSION, ++ cmd_flags, ++ 0); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPMNG_RSP_GET_VERSION(cmd, mc_ver_info); ++ ++ return 0; ++} +diff --git a/drivers/net/dpaa2/mc/dpni.c b/drivers/net/dpaa2/mc/dpni.c +new file mode 100644 +index 0000000..cdd2f37 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/dpni.c +@@ -0,0 +1,1907 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++#include ++#include ++ ++int dpni_prepare_key_cfg(const struct dpkg_profile_cfg *cfg, ++ uint8_t *key_cfg_buf) ++{ ++ int i, j; ++ int offset = 0; ++ int param = 1; ++ uint64_t *params = (uint64_t *)key_cfg_buf; ++ ++ if (!key_cfg_buf || !cfg) ++ return -EINVAL; ++ ++ params[0] |= mc_enc(0, 8, cfg->num_extracts); ++ params[0] = cpu_to_le64(params[0]); ++ ++ if (cfg->num_extracts >= DPKG_MAX_NUM_OF_EXTRACTS) ++ return -EINVAL; ++ ++ for (i = 0; i < cfg->num_extracts; i++) { ++ switch (cfg->extracts[i].type) { ++ case DPKG_EXTRACT_FROM_HDR: ++ params[param] |= mc_enc(0, 8, ++ cfg->extracts[i].extract.from_hdr.prot); ++ params[param] |= mc_enc(8, 4, ++ cfg->extracts[i].extract.from_hdr.type); ++ params[param] |= mc_enc(16, 8, ++ cfg->extracts[i].extract.from_hdr.size); ++ params[param] |= mc_enc(24, 8, ++ cfg->extracts[i].extract. ++ from_hdr.offset); ++ params[param] |= mc_enc(32, 32, ++ cfg->extracts[i].extract. ++ from_hdr.field); ++ params[param] = cpu_to_le64(params[param]); ++ param++; ++ params[param] |= mc_enc(0, 8, ++ cfg->extracts[i].extract. ++ from_hdr.hdr_index); ++ break; ++ case DPKG_EXTRACT_FROM_DATA: ++ params[param] |= mc_enc(16, 8, ++ cfg->extracts[i].extract. ++ from_data.size); ++ params[param] |= mc_enc(24, 8, ++ cfg->extracts[i].extract. ++ from_data.offset); ++ params[param] = cpu_to_le64(params[param]); ++ param++; ++ break; ++ case DPKG_EXTRACT_FROM_PARSE: ++ params[param] |= mc_enc(16, 8, ++ cfg->extracts[i].extract. ++ from_parse.size); ++ params[param] |= mc_enc(24, 8, ++ cfg->extracts[i].extract. ++ from_parse.offset); ++ params[param] = cpu_to_le64(params[param]); ++ param++; ++ break; ++ default: ++ return -EINVAL; ++ } ++ params[param] |= mc_enc( ++ 24, 8, cfg->extracts[i].num_of_byte_masks); ++ params[param] |= mc_enc(32, 4, cfg->extracts[i].type); ++ params[param] = cpu_to_le64(params[param]); ++ param++; ++ for (offset = 0, j = 0; ++ j < DPKG_NUM_OF_MASKS; ++ offset += 16, j++) { ++ params[param] |= mc_enc( ++ (offset), 8, cfg->extracts[i].masks[j].mask); ++ params[param] |= mc_enc( ++ (offset + 8), 8, ++ cfg->extracts[i].masks[j].offset); ++ } ++ params[param] = cpu_to_le64(params[param]); ++ param++; ++ } ++ return 0; ++} ++ ++int dpni_prepare_extended_cfg(const struct dpni_extended_cfg *cfg, ++ uint8_t *ext_cfg_buf) ++{ ++ uint64_t *ext_params = (uint64_t *)ext_cfg_buf; ++ ++ DPNI_PREP_EXTENDED_CFG(ext_params, cfg); ++ ++ return 0; ++} ++ ++int dpni_extract_extended_cfg(struct dpni_extended_cfg *cfg, ++ const uint8_t *ext_cfg_buf) ++{ ++ const uint64_t *ext_params = (const uint64_t *)ext_cfg_buf; ++ ++ DPNI_EXT_EXTENDED_CFG(ext_params, cfg); ++ ++ return 0; ++} ++ ++int dpni_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpni_id, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_OPEN, ++ cmd_flags, ++ 0); ++ DPNI_CMD_OPEN(cmd, dpni_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpni_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_CLOSE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpni_cfg *cfg, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_CREATE, ++ cmd_flags, ++ 0); ++ DPNI_CMD_CREATE(cmd, cfg); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpni_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_DESTROY, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_set_pools(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_pools_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_POOLS, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_POOLS(cmd, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_ENABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_DISABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_IS_ENABLED, cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_IS_ENABLED(cmd, *en); ++ ++ return 0; ++} ++ ++int dpni_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_RESET, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpni_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_IRQ, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_IRQ(cmd, irq_index, irq_cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpni_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_IRQ, ++ cmd_flags, ++ token); ++ DPNI_CMD_GET_IRQ(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_IRQ(cmd, *type, irq_cfg); ++ ++ return 0; ++} ++ ++int dpni_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_IRQ_ENABLE(cmd, irq_index, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPNI_CMD_GET_IRQ_ENABLE(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_IRQ_ENABLE(cmd, *en); ++ ++ return 0; ++} ++ ++int dpni_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_IRQ_MASK(cmd, irq_index, mask); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPNI_CMD_GET_IRQ_MASK(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_IRQ_MASK(cmd, *mask); ++ ++ return 0; ++} ++ ++int dpni_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPNI_CMD_GET_IRQ_STATUS(cmd, irq_index, *status); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_IRQ_STATUS(cmd, *status); ++ ++ return 0; ++} ++ ++int dpni_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_CLEAR_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPNI_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpni_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_ATTR, ++ cmd_flags, ++ token); ++ DPNI_CMD_GET_ATTR(cmd, attr); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_ATTR(cmd, attr); ++ ++ return 0; ++} ++ ++int dpni_set_errors_behavior(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpni_error_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_ERRORS_BEHAVIOR, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_ERRORS_BEHAVIOR(cmd, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_rx_buffer_layout(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpni_buffer_layout *layout) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_RX_BUFFER_LAYOUT, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_RX_BUFFER_LAYOUT(cmd, layout); ++ ++ return 0; ++} ++ ++int dpni_set_rx_buffer_layout(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_buffer_layout *layout) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_RX_BUFFER_LAYOUT, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_RX_BUFFER_LAYOUT(cmd, layout); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_tx_buffer_layout(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpni_buffer_layout *layout) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_BUFFER_LAYOUT, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_TX_BUFFER_LAYOUT(cmd, layout); ++ ++ return 0; ++} ++ ++int dpni_set_tx_buffer_layout(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_buffer_layout *layout) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_BUFFER_LAYOUT, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_TX_BUFFER_LAYOUT(cmd, layout); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_tx_conf_buffer_layout(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpni_buffer_layout *layout) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_CONF_BUFFER_LAYOUT, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_TX_CONF_BUFFER_LAYOUT(cmd, layout); ++ ++ return 0; ++} ++ ++int dpni_set_tx_conf_buffer_layout(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_buffer_layout *layout) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_CONF_BUFFER_LAYOUT, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_TX_CONF_BUFFER_LAYOUT(cmd, layout); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_l3_chksum_validation(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_L3_CHKSUM_VALIDATION, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_L3_CHKSUM_VALIDATION(cmd, *en); ++ ++ return 0; ++} ++ ++int dpni_set_l3_chksum_validation(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_L3_CHKSUM_VALIDATION, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_L3_CHKSUM_VALIDATION(cmd, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_l4_chksum_validation(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_L4_CHKSUM_VALIDATION, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_L4_CHKSUM_VALIDATION(cmd, *en); ++ ++ return 0; ++} ++ ++int dpni_set_l4_chksum_validation(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_L4_CHKSUM_VALIDATION, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_L4_CHKSUM_VALIDATION(cmd, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_qdid(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t *qdid) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_QDID, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_QDID(cmd, *qdid); ++ ++ return 0; ++} ++ ++int dpni_get_sp_info(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpni_sp_info *sp_info) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_SP_INFO, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_SP_INFO(cmd, sp_info); ++ ++ return 0; ++} ++ ++int dpni_get_tx_data_offset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t *data_offset) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_DATA_OFFSET, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_TX_DATA_OFFSET(cmd, *data_offset); ++ ++ return 0; ++} ++ ++int dpni_get_counter(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ enum dpni_counter counter, ++ uint64_t *value) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_COUNTER, ++ cmd_flags, ++ token); ++ DPNI_CMD_GET_COUNTER(cmd, counter); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_COUNTER(cmd, *value); ++ ++ return 0; ++} ++ ++int dpni_set_counter(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ enum dpni_counter counter, ++ uint64_t value) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_COUNTER, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_COUNTER(cmd, counter, value); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_set_link_cfg(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_link_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_LINK_CFG, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_LINK_CFG(cmd, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_link_state(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpni_link_state *state) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_LINK_STATE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_LINK_STATE(cmd, state); ++ ++ return 0; ++} ++ ++int dpni_set_tx_shaping(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_tx_shaping_cfg *tx_shaper) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_SHAPING, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_TX_SHAPING(cmd, tx_shaper); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_set_max_frame_length(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t max_frame_length) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_MAX_FRAME_LENGTH, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_MAX_FRAME_LENGTH(cmd, max_frame_length); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_max_frame_length(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t *max_frame_length) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_MAX_FRAME_LENGTH, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_MAX_FRAME_LENGTH(cmd, *max_frame_length); ++ ++ return 0; ++} ++ ++int dpni_set_mtu(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t mtu) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_MTU, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_MTU(cmd, mtu); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_mtu(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t *mtu) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_MTU, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_MTU(cmd, *mtu); ++ ++ return 0; ++} ++ ++int dpni_set_multicast_promisc(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_MCAST_PROMISC, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_MULTICAST_PROMISC(cmd, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_multicast_promisc(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_MCAST_PROMISC, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_MULTICAST_PROMISC(cmd, *en); ++ ++ return 0; ++} ++ ++int dpni_set_unicast_promisc(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_UNICAST_PROMISC, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_UNICAST_PROMISC(cmd, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_unicast_promisc(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_UNICAST_PROMISC, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_UNICAST_PROMISC(cmd, *en); ++ ++ return 0; ++} ++ ++int dpni_set_primary_mac_addr(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const uint8_t mac_addr[6]) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_PRIM_MAC, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_PRIMARY_MAC_ADDR(cmd, mac_addr); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_primary_mac_addr(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t mac_addr[6]) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_PRIM_MAC, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_PRIMARY_MAC_ADDR(cmd, mac_addr); ++ ++ return 0; ++} ++ ++int dpni_add_mac_addr(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const uint8_t mac_addr[6]) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_ADD_MAC_ADDR, ++ cmd_flags, ++ token); ++ DPNI_CMD_ADD_MAC_ADDR(cmd, mac_addr); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_remove_mac_addr(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const uint8_t mac_addr[6]) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_REMOVE_MAC_ADDR, ++ cmd_flags, ++ token); ++ DPNI_CMD_REMOVE_MAC_ADDR(cmd, mac_addr); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_clear_mac_filters(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int unicast, ++ int multicast) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_CLR_MAC_FILTERS, ++ cmd_flags, ++ token); ++ DPNI_CMD_CLEAR_MAC_FILTERS(cmd, unicast, multicast); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_set_vlan_filters(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_VLAN_FILTERS, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_VLAN_FILTERS(cmd, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_add_vlan_id(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_ADD_VLAN_ID, ++ cmd_flags, ++ token); ++ DPNI_CMD_ADD_VLAN_ID(cmd, vlan_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_remove_vlan_id(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_REMOVE_VLAN_ID, ++ cmd_flags, ++ token); ++ DPNI_CMD_REMOVE_VLAN_ID(cmd, vlan_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_clear_vlan_filters(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_CLR_VLAN_FILTERS, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_set_tx_selection(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_tx_selection_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_SELECTION, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_TX_SELECTION(cmd, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_set_rx_tc_dist(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ const struct dpni_rx_tc_dist_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_RX_TC_DIST, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_RX_TC_DIST(cmd, tc_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_set_tx_flow(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t *flow_id, ++ const struct dpni_tx_flow_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_FLOW, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_TX_FLOW(cmd, *flow_id, cfg); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_SET_TX_FLOW(cmd, *flow_id); ++ ++ return 0; ++} ++ ++int dpni_get_tx_flow(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t flow_id, ++ struct dpni_tx_flow_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_FLOW, ++ cmd_flags, ++ token); ++ DPNI_CMD_GET_TX_FLOW(cmd, flow_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_TX_FLOW(cmd, attr); ++ ++ return 0; ++} ++ ++int dpni_set_rx_flow(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ uint16_t flow_id, ++ const struct dpni_queue_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_RX_FLOW, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_RX_FLOW(cmd, tc_id, flow_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_rx_flow(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ uint16_t flow_id, ++ struct dpni_queue_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_RX_FLOW, ++ cmd_flags, ++ token); ++ DPNI_CMD_GET_RX_FLOW(cmd, tc_id, flow_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_RX_FLOW(cmd, attr); ++ ++ return 0; ++} ++ ++int dpni_set_rx_err_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_queue_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_RX_ERR_QUEUE, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_RX_ERR_QUEUE(cmd, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_rx_err_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpni_queue_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_RX_ERR_QUEUE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPNI_RSP_GET_RX_ERR_QUEUE(cmd, attr); ++ ++ return 0; ++} ++ ++int dpni_set_tx_conf_revoke(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int revoke) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_CONF_REVOKE, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_TX_CONF_REVOKE(cmd, revoke); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_set_qos_table(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_qos_tbl_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_QOS_TBL, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_QOS_TABLE(cmd, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_add_qos_entry(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_rule_cfg *cfg, ++ uint8_t tc_id) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_ADD_QOS_ENT, ++ cmd_flags, ++ token); ++ DPNI_CMD_ADD_QOS_ENTRY(cmd, cfg, tc_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_remove_qos_entry(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_rule_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_REMOVE_QOS_ENT, ++ cmd_flags, ++ token); ++ DPNI_CMD_REMOVE_QOS_ENTRY(cmd, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_clear_qos_table(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_CLR_QOS_TBL, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_add_fs_entry(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ const struct dpni_rule_cfg *cfg, ++ uint16_t flow_id) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_ADD_FS_ENT, ++ cmd_flags, ++ token); ++ DPNI_CMD_ADD_FS_ENTRY(cmd, tc_id, cfg, flow_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_remove_fs_entry(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ const struct dpni_rule_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_REMOVE_FS_ENT, ++ cmd_flags, ++ token); ++ DPNI_CMD_REMOVE_FS_ENTRY(cmd, tc_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_clear_fs_entries(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_CLR_FS_ENT, ++ cmd_flags, ++ token); ++ DPNI_CMD_CLEAR_FS_ENTRIES(cmd, tc_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_set_vlan_insertion(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_VLAN_INSERTION, ++ cmd_flags, token); ++ DPNI_CMD_SET_VLAN_INSERTION(cmd, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_set_vlan_removal(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_VLAN_REMOVAL, ++ cmd_flags, token); ++ DPNI_CMD_SET_VLAN_REMOVAL(cmd, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_set_ipr(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_IPR, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_IPR(cmd, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_set_ipf(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_IPF, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_IPF(cmd, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_set_rx_tc_policing(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ const struct dpni_rx_tc_policing_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_RX_TC_POLICING, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_RX_TC_POLICING(cmd, tc_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_rx_tc_policing(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ struct dpni_rx_tc_policing_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_RX_TC_POLICING, ++ cmd_flags, ++ token); ++ DPNI_CMD_GET_RX_TC_POLICING(cmd, tc_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ DPNI_RSP_GET_RX_TC_POLICING(cmd, cfg); ++ ++ return 0; ++} ++ ++void dpni_prepare_early_drop(const struct dpni_early_drop_cfg *cfg, ++ uint8_t *early_drop_buf) ++{ ++ uint64_t *ext_params = (uint64_t *)early_drop_buf; ++ ++ DPNI_PREP_EARLY_DROP(ext_params, cfg); ++} ++ ++void dpni_extract_early_drop(struct dpni_early_drop_cfg *cfg, ++ const uint8_t *early_drop_buf) ++{ ++ const uint64_t *ext_params = (const uint64_t *)early_drop_buf; ++ ++ DPNI_EXT_EARLY_DROP(ext_params, cfg); ++} ++ ++int dpni_set_rx_tc_early_drop(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ uint64_t early_drop_iova) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_RX_TC_EARLY_DROP, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_RX_TC_EARLY_DROP(cmd, tc_id, early_drop_iova); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_rx_tc_early_drop(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ uint64_t early_drop_iova) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_RX_TC_EARLY_DROP, ++ cmd_flags, ++ token); ++ DPNI_CMD_GET_RX_TC_EARLY_DROP(cmd, tc_id, early_drop_iova); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_set_tx_tc_early_drop(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ uint64_t early_drop_iova) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_TC_EARLY_DROP, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_TX_TC_EARLY_DROP(cmd, tc_id, early_drop_iova); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_tx_tc_early_drop(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ uint64_t early_drop_iova) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_TC_EARLY_DROP, ++ cmd_flags, ++ token); ++ DPNI_CMD_GET_TX_TC_EARLY_DROP(cmd, tc_id, early_drop_iova); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_set_rx_tc_congestion_notification(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ const struct dpni_congestion_notification_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header( ++ DPNI_CMDID_SET_RX_TC_CONGESTION_NOTIFICATION, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_RX_TC_CONGESTION_NOTIFICATION(cmd, tc_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_rx_tc_congestion_notification(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ struct dpni_congestion_notification_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header( ++ DPNI_CMDID_GET_RX_TC_CONGESTION_NOTIFICATION, ++ cmd_flags, ++ token); ++ DPNI_CMD_GET_RX_TC_CONGESTION_NOTIFICATION(cmd, tc_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ DPNI_RSP_GET_RX_TC_CONGESTION_NOTIFICATION(cmd, cfg); ++ ++ return 0; ++} ++ ++int dpni_set_tx_tc_congestion_notification(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ const struct dpni_congestion_notification_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header( ++ DPNI_CMDID_SET_TX_TC_CONGESTION_NOTIFICATION, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_TX_TC_CONGESTION_NOTIFICATION(cmd, tc_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_tx_tc_congestion_notification(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ struct dpni_congestion_notification_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header( ++ DPNI_CMDID_GET_TX_TC_CONGESTION_NOTIFICATION, ++ cmd_flags, ++ token); ++ DPNI_CMD_GET_TX_TC_CONGESTION_NOTIFICATION(cmd, tc_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ DPNI_RSP_GET_TX_TC_CONGESTION_NOTIFICATION(cmd, cfg); ++ ++ return 0; ++} ++ ++int dpni_set_tx_conf(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t flow_id, ++ const struct dpni_tx_conf_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_CONF, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_TX_CONF(cmd, flow_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_tx_conf(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t flow_id, ++ struct dpni_tx_conf_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_CONF, ++ cmd_flags, ++ token); ++ DPNI_CMD_GET_TX_CONF(cmd, flow_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ DPNI_RSP_GET_TX_CONF(cmd, attr); ++ ++ return 0; ++} ++ ++int dpni_set_tx_conf_congestion_notification(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t flow_id, ++ const struct dpni_congestion_notification_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header( ++ DPNI_CMDID_SET_TX_CONF_CONGESTION_NOTIFICATION, ++ cmd_flags, ++ token); ++ DPNI_CMD_SET_TX_CONF_CONGESTION_NOTIFICATION(cmd, flow_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpni_get_tx_conf_congestion_notification(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t flow_id, ++ struct dpni_congestion_notification_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header( ++ DPNI_CMDID_GET_TX_CONF_CONGESTION_NOTIFICATION, ++ cmd_flags, ++ token); ++ DPNI_CMD_GET_TX_CONF_CONGESTION_NOTIFICATION(cmd, flow_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ DPNI_RSP_GET_TX_CONF_CONGESTION_NOTIFICATION(cmd, cfg); ++ ++ return 0; ++} +diff --git a/drivers/net/dpaa2/mc/dprc.c b/drivers/net/dpaa2/mc/dprc.c +new file mode 100644 +index 0000000..75c6a68 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/dprc.c +@@ -0,0 +1,786 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++#include ++#include ++ ++int dprc_get_container_id(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int *container_id) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_CONT_ID, ++ cmd_flags, ++ 0); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRC_RSP_GET_CONTAINER_ID(cmd, *container_id); ++ ++ return 0; ++} ++ ++int dprc_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int container_id, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_OPEN, cmd_flags, ++ 0); ++ DPRC_CMD_OPEN(cmd, container_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dprc_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLOSE, cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprc_create_container(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dprc_cfg *cfg, ++ int *child_container_id, ++ uint64_t *child_portal_paddr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ DPRC_CMD_CREATE_CONTAINER(cmd, cfg); ++ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_CREATE_CONT, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRC_RSP_CREATE_CONTAINER(cmd, *child_container_id, ++ *child_portal_paddr); ++ ++ return 0; ++} ++ ++int dprc_destroy_container(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int child_container_id) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_DESTROY_CONT, ++ cmd_flags, ++ token); ++ DPRC_CMD_DESTROY_CONTAINER(cmd, child_container_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprc_reset_container(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int child_container_id) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_RESET_CONT, ++ cmd_flags, ++ token); ++ DPRC_CMD_RESET_CONTAINER(cmd, child_container_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprc_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dprc_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ, ++ cmd_flags, ++ token); ++ DPRC_CMD_GET_IRQ(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRC_RSP_GET_IRQ(cmd, *type, irq_cfg); ++ ++ return 0; ++} ++ ++int dprc_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dprc_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ, ++ cmd_flags, ++ token); ++ DPRC_CMD_SET_IRQ(cmd, irq_index, irq_cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprc_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPRC_CMD_GET_IRQ_ENABLE(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRC_RSP_GET_IRQ_ENABLE(cmd, *en); ++ ++ return 0; ++} ++ ++int dprc_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPRC_CMD_SET_IRQ_ENABLE(cmd, irq_index, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprc_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPRC_CMD_GET_IRQ_MASK(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRC_RSP_GET_IRQ_MASK(cmd, *mask); ++ ++ return 0; ++} ++ ++int dprc_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPRC_CMD_SET_IRQ_MASK(cmd, irq_index, mask); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprc_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPRC_CMD_GET_IRQ_STATUS(cmd, irq_index, *status); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRC_RSP_GET_IRQ_STATUS(cmd, *status); ++ ++ return 0; ++} ++ ++int dprc_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLEAR_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPRC_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprc_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dprc_attributes *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRC_RSP_GET_ATTRIBUTES(cmd, attr); ++ ++ return 0; ++} ++ ++int dprc_set_res_quota(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int child_container_id, ++ char *type, ++ uint16_t quota) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_RES_QUOTA, ++ cmd_flags, ++ token); ++ DPRC_CMD_SET_RES_QUOTA(cmd, child_container_id, type, quota); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprc_get_res_quota(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int child_container_id, ++ char *type, ++ uint16_t *quota) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_RES_QUOTA, ++ cmd_flags, ++ token); ++ DPRC_CMD_GET_RES_QUOTA(cmd, child_container_id, type); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRC_RSP_GET_RES_QUOTA(cmd, *quota); ++ ++ return 0; ++} ++ ++int dprc_assign(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int container_id, ++ struct dprc_res_req *res_req) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_ASSIGN, ++ cmd_flags, ++ token); ++ DPRC_CMD_ASSIGN(cmd, container_id, res_req); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprc_unassign(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int child_container_id, ++ struct dprc_res_req *res_req) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_UNASSIGN, ++ cmd_flags, ++ token); ++ DPRC_CMD_UNASSIGN(cmd, child_container_id, res_req); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprc_get_pool_count(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *pool_count) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_POOL_COUNT, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRC_RSP_GET_POOL_COUNT(cmd, *pool_count); ++ ++ return 0; ++} ++ ++int dprc_get_pool(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int pool_index, ++ char *type) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_POOL, ++ cmd_flags, ++ token); ++ DPRC_CMD_GET_POOL(cmd, pool_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRC_RSP_GET_POOL(cmd, type); ++ ++ return 0; ++} ++ ++int dprc_get_obj_count(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *obj_count) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_COUNT, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRC_RSP_GET_OBJ_COUNT(cmd, *obj_count); ++ ++ return 0; ++} ++ ++int dprc_get_obj(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int obj_index, ++ struct dprc_obj_desc *obj_desc) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ, ++ cmd_flags, ++ token); ++ DPRC_CMD_GET_OBJ(cmd, obj_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRC_RSP_GET_OBJ(cmd, obj_desc); ++ ++ return 0; ++} ++ ++int dprc_get_obj_desc(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ char *obj_type, ++ int obj_id, ++ struct dprc_obj_desc *obj_desc) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_DESC, ++ cmd_flags, ++ token); ++ DPRC_CMD_GET_OBJ_DESC(cmd, obj_type, obj_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRC_RSP_GET_OBJ_DESC(cmd, obj_desc); ++ ++ return 0; ++} ++ ++int dprc_set_obj_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ char *obj_type, ++ int obj_id, ++ uint8_t irq_index, ++ struct dprc_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_OBJ_IRQ, ++ cmd_flags, ++ token); ++ DPRC_CMD_SET_OBJ_IRQ(cmd, ++ obj_type, ++ obj_id, ++ irq_index, ++ irq_cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprc_get_obj_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ char *obj_type, ++ int obj_id, ++ uint8_t irq_index, ++ int *type, ++ struct dprc_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_IRQ, ++ cmd_flags, ++ token); ++ DPRC_CMD_GET_OBJ_IRQ(cmd, obj_type, obj_id, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRC_RSP_GET_OBJ_IRQ(cmd, *type, irq_cfg); ++ ++ return 0; ++} ++ ++int dprc_get_res_count(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ char *type, ++ int *res_count) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ *res_count = 0; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_RES_COUNT, ++ cmd_flags, ++ token); ++ DPRC_CMD_GET_RES_COUNT(cmd, type); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRC_RSP_GET_RES_COUNT(cmd, *res_count); ++ ++ return 0; ++} ++ ++int dprc_get_res_ids(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ char *type, ++ struct dprc_res_ids_range_desc *range_desc) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_RES_IDS, ++ cmd_flags, ++ token); ++ DPRC_CMD_GET_RES_IDS(cmd, range_desc, type); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRC_RSP_GET_RES_IDS(cmd, range_desc); ++ ++ return 0; ++} ++ ++int dprc_get_obj_region(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ char *obj_type, ++ int obj_id, ++ uint8_t region_index, ++ struct dprc_region_desc *region_desc) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_REG, ++ cmd_flags, ++ token); ++ DPRC_CMD_GET_OBJ_REGION(cmd, obj_type, obj_id, region_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRC_RSP_GET_OBJ_REGION(cmd, region_desc); ++ ++ return 0; ++} ++ ++int dprc_set_obj_label(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ char *obj_type, ++ int obj_id, ++ char *label) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_SET_OBJ_LABEL, ++ cmd_flags, ++ token); ++ DPRC_CMD_SET_OBJ_LABEL(cmd, obj_type, obj_id, label); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprc_connect(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dprc_endpoint *endpoint1, ++ const struct dprc_endpoint *endpoint2, ++ const struct dprc_connection_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_CONNECT, ++ cmd_flags, ++ token); ++ DPRC_CMD_CONNECT(cmd, endpoint1, endpoint2, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprc_disconnect(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dprc_endpoint *endpoint) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_DISCONNECT, ++ cmd_flags, ++ token); ++ DPRC_CMD_DISCONNECT(cmd, endpoint); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprc_get_connection(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dprc_endpoint *endpoint1, ++ struct dprc_endpoint *endpoint2, ++ int *state) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_CONNECTION, ++ cmd_flags, ++ token); ++ DPRC_CMD_GET_CONNECTION(cmd, endpoint1); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRC_RSP_GET_CONNECTION(cmd, endpoint2, *state); ++ ++ return 0; ++} +diff --git a/drivers/net/dpaa2/mc/dprtc.c b/drivers/net/dpaa2/mc/dprtc.c +new file mode 100644 +index 0000000..73667af +--- /dev/null ++++ b/drivers/net/dpaa2/mc/dprtc.c +@@ -0,0 +1,509 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++#include ++#include ++ ++int dprtc_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dprtc_id, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_OPEN, ++ cmd_flags, ++ 0); ++ DPRTC_CMD_OPEN(cmd, dprtc_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return err; ++} ++ ++int dprtc_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_CLOSE, cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprtc_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dprtc_cfg *cfg, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ (void)(cfg); /* unused */ ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_CREATE, ++ cmd_flags, ++ 0); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dprtc_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_DESTROY, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprtc_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_ENABLE, cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprtc_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_DISABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprtc_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_IS_ENABLED, cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRTC_RSP_IS_ENABLED(cmd, *en); ++ ++ return 0; ++} ++ ++int dprtc_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_RESET, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprtc_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dprtc_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_SET_IRQ, ++ cmd_flags, ++ token); ++ ++ DPRTC_CMD_SET_IRQ(cmd, irq_index, irq_cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprtc_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dprtc_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_GET_IRQ, ++ cmd_flags, ++ token); ++ ++ DPRTC_CMD_GET_IRQ(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRTC_RSP_GET_IRQ(cmd, *type, irq_cfg); ++ ++ return 0; ++} ++ ++int dprtc_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_SET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ ++ DPRTC_CMD_SET_IRQ_ENABLE(cmd, irq_index, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprtc_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_GET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ ++ DPRTC_CMD_GET_IRQ_ENABLE(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRTC_RSP_GET_IRQ_ENABLE(cmd, *en); ++ ++ return 0; ++} ++ ++int dprtc_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_SET_IRQ_MASK, ++ cmd_flags, ++ token); ++ ++ DPRTC_CMD_SET_IRQ_MASK(cmd, irq_index, mask); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprtc_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_GET_IRQ_MASK, ++ cmd_flags, ++ token); ++ ++ DPRTC_CMD_GET_IRQ_MASK(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRTC_RSP_GET_IRQ_MASK(cmd, *mask); ++ ++ return 0; ++} ++ ++int dprtc_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_GET_IRQ_STATUS, ++ cmd_flags, ++ token); ++ ++ DPRTC_CMD_GET_IRQ_STATUS(cmd, irq_index, *status); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRTC_RSP_GET_IRQ_STATUS(cmd, *status); ++ ++ return 0; ++} ++ ++int dprtc_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_CLEAR_IRQ_STATUS, ++ cmd_flags, ++ token); ++ ++ DPRTC_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprtc_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dprtc_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_GET_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRTC_RSP_GET_ATTRIBUTES(cmd, attr); ++ ++ return 0; ++} ++ ++int dprtc_set_clock_offset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int64_t offset) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_SET_CLOCK_OFFSET, ++ cmd_flags, ++ token); ++ ++ DPRTC_CMD_SET_CLOCK_OFFSET(cmd, offset); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprtc_set_freq_compensation(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint32_t freq_compensation) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_SET_FREQ_COMPENSATION, ++ cmd_flags, ++ token); ++ ++ DPRTC_CMD_SET_FREQ_COMPENSATION(cmd, freq_compensation); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprtc_get_freq_compensation(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint32_t *freq_compensation) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_GET_FREQ_COMPENSATION, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRTC_RSP_GET_FREQ_COMPENSATION(cmd, *freq_compensation); ++ ++ return 0; ++} ++ ++int dprtc_get_time(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint64_t *time) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_GET_TIME, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPRTC_RSP_GET_TIME(cmd, *time); ++ ++ return 0; ++} ++ ++int dprtc_set_time(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint64_t time) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_SET_TIME, ++ cmd_flags, ++ token); ++ ++ DPRTC_CMD_SET_TIME(cmd, time); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dprtc_set_alarm(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, uint64_t time) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPRTC_CMDID_SET_ALARM, ++ cmd_flags, ++ token); ++ ++ DPRTC_CMD_SET_ALARM(cmd, time); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} +diff --git a/drivers/net/dpaa2/mc/dpseci.c b/drivers/net/dpaa2/mc/dpseci.c +new file mode 100644 +index 0000000..a4b932a +--- /dev/null ++++ b/drivers/net/dpaa2/mc/dpseci.c +@@ -0,0 +1,502 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++#include ++#include ++ ++int dpseci_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpseci_id, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_OPEN, ++ cmd_flags, ++ 0); ++ DPSECI_CMD_OPEN(cmd, dpseci_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpseci_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_CLOSE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpseci_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpseci_cfg *cfg, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_CREATE, ++ cmd_flags, ++ 0); ++ DPSECI_CMD_CREATE(cmd, cfg); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpseci_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_DESTROY, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpseci_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_ENABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpseci_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_DISABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpseci_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_IS_ENABLED, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSECI_RSP_IS_ENABLED(cmd, *en); ++ ++ return 0; ++} ++ ++int dpseci_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_RESET, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpseci_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpseci_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_GET_IRQ, ++ cmd_flags, ++ token); ++ DPSECI_CMD_GET_IRQ(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSECI_RSP_GET_IRQ(cmd, *type, irq_cfg); ++ ++ return 0; ++} ++ ++int dpseci_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpseci_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_SET_IRQ, ++ cmd_flags, ++ token); ++ DPSECI_CMD_SET_IRQ(cmd, irq_index, irq_cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpseci_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_GET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPSECI_CMD_GET_IRQ_ENABLE(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSECI_RSP_GET_IRQ_ENABLE(cmd, *en); ++ ++ return 0; ++} ++ ++int dpseci_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_SET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPSECI_CMD_SET_IRQ_ENABLE(cmd, irq_index, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpseci_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_GET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPSECI_CMD_GET_IRQ_MASK(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSECI_RSP_GET_IRQ_MASK(cmd, *mask); ++ ++ return 0; ++} ++ ++int dpseci_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_SET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPSECI_CMD_SET_IRQ_MASK(cmd, irq_index, mask); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpseci_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_GET_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPSECI_CMD_GET_IRQ_STATUS(cmd, irq_index, *status); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSECI_RSP_GET_IRQ_STATUS(cmd, *status); ++ ++ return 0; ++} ++ ++int dpseci_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_CLEAR_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPSECI_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpseci_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpseci_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_GET_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSECI_RSP_GET_ATTR(cmd, attr); ++ ++ return 0; ++} ++ ++int dpseci_set_rx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t queue, ++ const struct dpseci_rx_queue_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_SET_RX_QUEUE, ++ cmd_flags, ++ token); ++ DPSECI_CMD_SET_RX_QUEUE(cmd, queue, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpseci_get_rx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t queue, ++ struct dpseci_rx_queue_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_GET_RX_QUEUE, ++ cmd_flags, ++ token); ++ DPSECI_CMD_GET_RX_QUEUE(cmd, queue); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSECI_RSP_GET_RX_QUEUE(cmd, attr); ++ ++ return 0; ++} ++ ++int dpseci_get_tx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t queue, ++ struct dpseci_tx_queue_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_GET_TX_QUEUE, ++ cmd_flags, ++ token); ++ DPSECI_CMD_GET_TX_QUEUE(cmd, queue); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSECI_RSP_GET_TX_QUEUE(cmd, attr); ++ ++ return 0; ++} ++ ++int dpseci_get_sec_attr(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpseci_sec_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_GET_SEC_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSECI_RSP_GET_SEC_ATTR(cmd, attr); ++ ++ return 0; ++} ++ ++int dpseci_get_sec_counters(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpseci_sec_counters *counters) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_GET_SEC_COUNTERS, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSECI_RSP_GET_SEC_COUNTERS(cmd, counters); ++ ++ return 0; ++} +diff --git a/drivers/net/dpaa2/mc/dpsw.c b/drivers/net/dpaa2/mc/dpsw.c +new file mode 100644 +index 0000000..2034b55 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/dpsw.c +@@ -0,0 +1,1639 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++#include ++#include ++ ++/* internal functions */ ++static void build_if_id_bitmap(const uint16_t *if_id, ++ const uint16_t num_ifs, ++ struct mc_command *cmd, ++ int start_param) ++{ ++ int i; ++ ++ for (i = 0; (i < num_ifs) && (i < DPSW_MAX_IF); i++) ++ cmd->params[start_param + (if_id[i] / 64)] |= mc_enc( ++ (if_id[i] % 64), 1, 1); ++} ++ ++static int read_if_id_bitmap(uint16_t *if_id, ++ uint16_t *num_ifs, ++ struct mc_command *cmd, ++ int start_param) ++{ ++ int bitmap[DPSW_MAX_IF] = { 0 }; ++ int i, j = 0; ++ int count = 0; ++ ++ for (i = 0; i < DPSW_MAX_IF; i++) { ++ bitmap[i] = (int)mc_dec(cmd->params[start_param + i / 64], ++ i % 64, 1); ++ count += bitmap[i]; ++ } ++ ++ *num_ifs = (uint16_t)count; ++ ++ for (i = 0; (i < DPSW_MAX_IF) && (j < count); i++) { ++ if (bitmap[i]) { ++ if_id[j] = (uint16_t)i; ++ j++; ++ } ++ } ++ ++ return 0; ++} ++ ++/* DPSW APIs */ ++int dpsw_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpsw_id, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_OPEN, ++ cmd_flags, ++ 0); ++ DPSW_CMD_OPEN(cmd, dpsw_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpsw_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_CLOSE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpsw_cfg *cfg, ++ uint16_t *token) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_CREATE, ++ cmd_flags, ++ 0); ++ DPSW_CMD_CREATE(cmd, cfg); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ *token = MC_CMD_HDR_READ_TOKEN(cmd.header); ++ ++ return 0; ++} ++ ++int dpsw_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_DESTROY, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_ENABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_DISABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IS_ENABLED, cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_IS_ENABLED(cmd, *en); ++ ++ return 0; ++} ++ ++int dpsw_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_RESET, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpsw_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_SET_IRQ, ++ cmd_flags, ++ token); ++ DPSW_CMD_SET_IRQ(cmd, irq_index, irq_cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpsw_irq_cfg *irq_cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_GET_IRQ, ++ cmd_flags, ++ token); ++ DPSW_CMD_GET_IRQ(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_GET_IRQ(cmd, *type, irq_cfg); ++ ++ return 0; ++} ++ ++int dpsw_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_SET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPSW_CMD_SET_IRQ_ENABLE(cmd, irq_index, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_GET_IRQ_ENABLE, ++ cmd_flags, ++ token); ++ DPSW_CMD_GET_IRQ_ENABLE(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_GET_IRQ_ENABLE(cmd, *en); ++ ++ return 0; ++} ++ ++int dpsw_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_SET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPSW_CMD_SET_IRQ_MASK(cmd, irq_index, mask); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_GET_IRQ_MASK, ++ cmd_flags, ++ token); ++ DPSW_CMD_GET_IRQ_MASK(cmd, irq_index); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_GET_IRQ_MASK(cmd, *mask); ++ ++ return 0; ++} ++ ++int dpsw_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_GET_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPSW_CMD_GET_IRQ_STATUS(cmd, irq_index, *status); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_GET_IRQ_STATUS(cmd, *status); ++ ++ return 0; ++} ++ ++int dpsw_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_CLEAR_IRQ_STATUS, ++ cmd_flags, ++ token); ++ DPSW_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpsw_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_GET_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_GET_ATTR(cmd, attr); ++ ++ return 0; ++} ++ ++int dpsw_set_reflection_if(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_SET_REFLECTION_IF, ++ cmd_flags, ++ token); ++ DPSW_CMD_SET_REFLECTION_IF(cmd, if_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_if_set_link_cfg(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ struct dpsw_link_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_LINK_CFG, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_SET_LINK_CFG(cmd, if_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_if_get_link_state(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ struct dpsw_link_state *state) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_GET_LINK_STATE, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_GET_LINK_STATE(cmd, if_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_IF_GET_LINK_STATE(cmd, state); ++ ++ return 0; ++} ++ ++int dpsw_if_set_flooding(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ int en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_FLOODING, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_SET_FLOODING(cmd, if_id, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_if_set_broadcast(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ int en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_BROADCAST, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_SET_FLOODING(cmd, if_id, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_if_set_multicast(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ int en) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_MULTICAST, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_SET_FLOODING(cmd, if_id, en); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_if_set_tci(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpsw_tci_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_TCI, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_SET_TCI(cmd, if_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_if_get_tci(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ struct dpsw_tci_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err = 0; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_GET_TCI, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_GET_TCI(cmd, if_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_IF_GET_TCI(cmd, cfg); ++ ++ return 0; ++} ++ ++int dpsw_if_set_stp(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpsw_stp_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_STP, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_SET_STP(cmd, if_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_if_set_accepted_frames(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpsw_accepted_frames_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_ACCEPTED_FRAMES, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_SET_ACCEPTED_FRAMES(cmd, if_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_if_set_accept_all_vlan(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ int accept_all) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_SET_IF_ACCEPT_ALL_VLAN, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_SET_ACCEPT_ALL_VLAN(cmd, if_id, accept_all); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_if_get_counter(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ enum dpsw_counter type, ++ uint64_t *counter) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_GET_COUNTER, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_GET_COUNTER(cmd, if_id, type); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_IF_GET_COUNTER(cmd, *counter); ++ ++ return 0; ++} ++ ++int dpsw_if_set_counter(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ enum dpsw_counter type, ++ uint64_t counter) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_COUNTER, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_SET_COUNTER(cmd, if_id, type, counter); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_if_set_tx_selection(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpsw_tx_selection_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_TX_SELECTION, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_SET_TX_SELECTION(cmd, if_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_if_add_reflection(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpsw_reflection_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_ADD_REFLECTION, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_ADD_REFLECTION(cmd, if_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_if_remove_reflection(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpsw_reflection_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_REMOVE_REFLECTION, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_REMOVE_REFLECTION(cmd, if_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_if_set_flooding_metering(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpsw_metering_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_FLOODING_METERING, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_SET_FLOODING_METERING(cmd, if_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_if_set_metering(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ uint8_t tc_id, ++ const struct dpsw_metering_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_METERING, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_SET_METERING(cmd, if_id, tc_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++void dpsw_prepare_early_drop(const struct dpsw_early_drop_cfg *cfg, ++ uint8_t *early_drop_buf) ++{ ++ uint64_t *ext_params = (uint64_t *)early_drop_buf; ++ ++ DPSW_PREP_EARLY_DROP(ext_params, cfg); ++} ++ ++int dpsw_if_set_early_drop(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ uint8_t tc_id, ++ uint64_t early_drop_iova) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_EARLY_DROP, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_SET_EARLY_DROP(cmd, if_id, tc_id, early_drop_iova); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_add_custom_tpid(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpsw_custom_tpid_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_ADD_CUSTOM_TPID, ++ cmd_flags, ++ token); ++ DPSW_CMD_ADD_CUSTOM_TPID(cmd, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_remove_custom_tpid(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpsw_custom_tpid_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_REMOVE_CUSTOM_TPID, ++ cmd_flags, ++ token); ++ DPSW_CMD_REMOVE_CUSTOM_TPID(cmd, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_if_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_ENABLE, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_ENABLE(cmd, if_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_if_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_DISABLE, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_DISABLE(cmd, if_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_if_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ struct dpsw_if_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_GET_ATTR, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_GET_ATTR(cmd, if_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_IF_GET_ATTR(cmd, attr); ++ ++ return 0; ++} ++ ++int dpsw_if_set_max_frame_length(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ uint16_t frame_length) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_MAX_FRAME_LENGTH, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_SET_MAX_FRAME_LENGTH(cmd, if_id, frame_length); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_if_get_max_frame_length(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ uint16_t *frame_length) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_GET_MAX_FRAME_LENGTH, ++ cmd_flags, ++ token); ++ DPSW_CMD_IF_GET_MAX_FRAME_LENGTH(cmd, if_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ DPSW_RSP_IF_GET_MAX_FRAME_LENGTH(cmd, *frame_length); ++ ++ return 0; ++} ++ ++int dpsw_vlan_add(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ const struct dpsw_vlan_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_ADD, ++ cmd_flags, ++ token); ++ DPSW_CMD_VLAN_ADD(cmd, vlan_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_vlan_add_if(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ const struct dpsw_vlan_if_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 1); ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_ADD_IF, ++ cmd_flags, ++ token); ++ DPSW_CMD_VLAN_ADD_IF(cmd, vlan_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_vlan_add_if_untagged(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ const struct dpsw_vlan_if_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 1); ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_ADD_IF_UNTAGGED, ++ cmd_flags, ++ token); ++ DPSW_CMD_VLAN_ADD_IF_UNTAGGED(cmd, vlan_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_vlan_add_if_flooding(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ const struct dpsw_vlan_if_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 1); ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_ADD_IF_FLOODING, ++ cmd_flags, ++ token); ++ DPSW_CMD_VLAN_ADD_IF_FLOODING(cmd, vlan_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_vlan_remove_if(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ const struct dpsw_vlan_if_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 1); ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_REMOVE_IF, ++ cmd_flags, ++ token); ++ DPSW_CMD_VLAN_REMOVE_IF(cmd, vlan_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_vlan_remove_if_untagged(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ const struct dpsw_vlan_if_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 1); ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_REMOVE_IF_UNTAGGED, ++ cmd_flags, ++ token); ++ DPSW_CMD_VLAN_REMOVE_IF_UNTAGGED(cmd, vlan_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_vlan_remove_if_flooding(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ const struct dpsw_vlan_if_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 1); ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_REMOVE_IF_FLOODING, ++ cmd_flags, ++ token); ++ DPSW_CMD_VLAN_REMOVE_IF_FLOODING(cmd, vlan_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_vlan_remove(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_REMOVE, ++ cmd_flags, ++ token); ++ DPSW_CMD_VLAN_REMOVE(cmd, vlan_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_vlan_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ struct dpsw_vlan_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_GET_ATTRIBUTES, ++ cmd_flags, ++ token); ++ DPSW_CMD_VLAN_GET_ATTR(cmd, vlan_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_VLAN_GET_ATTR(cmd, attr); ++ ++ return 0; ++} ++ ++int dpsw_vlan_get_if(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ struct dpsw_vlan_if_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_GET_IF, ++ cmd_flags, ++ token); ++ DPSW_CMD_VLAN_GET_IF(cmd, vlan_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_VLAN_GET_IF(cmd, cfg); ++ read_if_id_bitmap(cfg->if_id, &cfg->num_ifs, &cmd, 1); ++ ++ return 0; ++} ++ ++int dpsw_vlan_get_if_flooding(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ struct dpsw_vlan_if_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_GET_IF_FLOODING, ++ cmd_flags, ++ token); ++ DPSW_CMD_VLAN_GET_IF_FLOODING(cmd, vlan_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_VLAN_GET_IF_FLOODING(cmd, cfg); ++ read_if_id_bitmap(cfg->if_id, &cfg->num_ifs, &cmd, 1); ++ ++ return 0; ++} ++ ++int dpsw_vlan_get_if_untagged(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ struct dpsw_vlan_if_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_GET_IF_UNTAGGED, ++ cmd_flags, ++ token); ++ DPSW_CMD_VLAN_GET_IF_UNTAGGED(cmd, vlan_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_VLAN_GET_IF(cmd, cfg); ++ read_if_id_bitmap(cfg->if_id, &cfg->num_ifs, &cmd, 1); ++ ++ return 0; ++} ++ ++int dpsw_fdb_add(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t *fdb_id, ++ const struct dpsw_fdb_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_ADD, ++ cmd_flags, ++ token); ++ DPSW_CMD_FDB_ADD(cmd, cfg); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_FDB_ADD(cmd, *fdb_id); ++ ++ return 0; ++} ++ ++int dpsw_fdb_remove(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t fdb_id) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_REMOVE, ++ cmd_flags, ++ token); ++ DPSW_CMD_FDB_REMOVE(cmd, fdb_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_fdb_add_unicast(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t fdb_id, ++ const struct dpsw_fdb_unicast_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_ADD_UNICAST, ++ cmd_flags, ++ token); ++ DPSW_CMD_FDB_ADD_UNICAST(cmd, fdb_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_fdb_get_unicast(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t fdb_id, ++ struct dpsw_fdb_unicast_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_GET_UNICAST, ++ cmd_flags, ++ token); ++ DPSW_CMD_FDB_GET_UNICAST(cmd, fdb_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_FDB_GET_UNICAST(cmd, cfg); ++ ++ return 0; ++} ++ ++int dpsw_fdb_remove_unicast(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t fdb_id, ++ const struct dpsw_fdb_unicast_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_REMOVE_UNICAST, ++ cmd_flags, ++ token); ++ DPSW_CMD_FDB_REMOVE_UNICAST(cmd, fdb_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_fdb_add_multicast(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t fdb_id, ++ const struct dpsw_fdb_multicast_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 2); ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_ADD_MULTICAST, ++ cmd_flags, ++ token); ++ DPSW_CMD_FDB_ADD_MULTICAST(cmd, fdb_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_fdb_get_multicast(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t fdb_id, ++ struct dpsw_fdb_multicast_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_GET_MULTICAST, ++ cmd_flags, ++ token); ++ DPSW_CMD_FDB_GET_MULTICAST(cmd, fdb_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_FDB_GET_MULTICAST(cmd, cfg); ++ read_if_id_bitmap(cfg->if_id, &cfg->num_ifs, &cmd, 2); ++ ++ return 0; ++} ++ ++int dpsw_fdb_remove_multicast(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t fdb_id, ++ const struct dpsw_fdb_multicast_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 2); ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_REMOVE_MULTICAST, ++ cmd_flags, ++ token); ++ DPSW_CMD_FDB_REMOVE_MULTICAST(cmd, fdb_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_fdb_set_learning_mode(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t fdb_id, ++ enum dpsw_fdb_learning_mode mode) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_SET_LEARNING_MODE, ++ cmd_flags, ++ token); ++ DPSW_CMD_FDB_SET_LEARNING_MODE(cmd, fdb_id, mode); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_fdb_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t fdb_id, ++ struct dpsw_fdb_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_GET_ATTR, ++ cmd_flags, ++ token); ++ DPSW_CMD_FDB_GET_ATTR(cmd, fdb_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_FDB_GET_ATTR(cmd, attr); ++ ++ return 0; ++} ++ ++int dpsw_acl_add(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t *acl_id, ++ const struct dpsw_acl_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_ADD, ++ cmd_flags, ++ token); ++ DPSW_CMD_ACL_ADD(cmd, cfg); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_ACL_ADD(cmd, *acl_id); ++ ++ return 0; ++} ++ ++int dpsw_acl_remove(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t acl_id) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_REMOVE, ++ cmd_flags, ++ token); ++ DPSW_CMD_ACL_REMOVE(cmd, acl_id); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++void dpsw_acl_prepare_entry_cfg(const struct dpsw_acl_key *key, ++ uint8_t *entry_cfg_buf) ++{ ++ uint64_t *ext_params = (uint64_t *)entry_cfg_buf; ++ ++ DPSW_PREP_ACL_ENTRY(ext_params, key); ++} ++ ++int dpsw_acl_add_entry(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t acl_id, ++ const struct dpsw_acl_entry_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_ADD_ENTRY, ++ cmd_flags, ++ token); ++ DPSW_CMD_ACL_ADD_ENTRY(cmd, acl_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_acl_remove_entry(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t acl_id, ++ const struct dpsw_acl_entry_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_REMOVE_ENTRY, ++ cmd_flags, ++ token); ++ DPSW_CMD_ACL_REMOVE_ENTRY(cmd, acl_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_acl_add_if(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t acl_id, ++ const struct dpsw_acl_if_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 1); ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_ADD_IF, ++ cmd_flags, ++ token); ++ DPSW_CMD_ACL_ADD_IF(cmd, acl_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_acl_remove_if(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t acl_id, ++ const struct dpsw_acl_if_cfg *cfg) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ build_if_id_bitmap(cfg->if_id, cfg->num_ifs, &cmd, 1); ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_REMOVE_IF, ++ cmd_flags, ++ token); ++ DPSW_CMD_ACL_REMOVE_IF(cmd, acl_id, cfg); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_acl_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t acl_id, ++ struct dpsw_acl_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_GET_ATTR, ++ cmd_flags, ++ token); ++ DPSW_CMD_ACL_GET_ATTR(cmd, acl_id); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_ACL_GET_ATTR(cmd, attr); ++ ++ return 0; ++} ++ ++int dpsw_ctrl_if_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpsw_ctrl_if_attr *attr) ++{ ++ struct mc_command cmd = { 0 }; ++ int err; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_CTRL_IF_GET_ATTR, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ err = mc_send_command(mc_io, &cmd); ++ if (err) ++ return err; ++ ++ /* retrieve response parameters */ ++ DPSW_RSP_CTRL_IF_GET_ATTR(cmd, attr); ++ ++ return 0; ++} ++ ++int dpsw_ctrl_if_set_pools(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpsw_ctrl_if_pools_cfg *pools) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_CTRL_IF_SET_POOLS, ++ cmd_flags, ++ token); ++ DPSW_CMD_CTRL_IF_SET_POOLS(cmd, pools); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++int dpsw_ctrl_if_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_CTRL_IF_ENABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} ++ ++/** ++* @brief Function disables control interface ++* @mc_io: Pointer to MC portal's I/O object ++* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++* @token: Token of DPSW object ++* ++* Return: '0' on Success; Error code otherwise. ++*/ ++int dpsw_ctrl_if_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ struct mc_command cmd = { 0 }; ++ ++ /* prepare command */ ++ cmd.header = mc_encode_cmd_header(DPSW_CMDID_CTRL_IF_DISABLE, ++ cmd_flags, ++ token); ++ ++ /* send command to mc*/ ++ return mc_send_command(mc_io, &cmd); ++} +diff --git a/drivers/net/dpaa2/mc/fsl_dpaiop.h b/drivers/net/dpaa2/mc/fsl_dpaiop.h +new file mode 100644 +index 0000000..b039b2a +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpaiop.h +@@ -0,0 +1,494 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPAIOP_H ++#define __FSL_DPAIOP_H ++ ++struct fsl_mc_io; ++ ++/* Data Path AIOP API ++ * Contains initialization APIs and runtime control APIs for DPAIOP ++ */ ++ ++/** ++ * dpaiop_open() - Open a control session for the specified object. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @dpaiop_id: DPAIOP unique ID ++ * @token: Returned token; use in subsequent API calls ++ * ++ * This function can be used to open a control session for an ++ * already created object; an object may have been declared in ++ * the DPL or by calling the dpaiop_create function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent commands for ++ * this specific object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpaiop_id, ++ uint16_t *token); ++ ++/** ++ * dpaiop_close() - Close the control session of the object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPAIOP object ++ * ++ * After this function is called, no further operations are ++ * allowed on the object without opening a new control session. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_close(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token); ++ ++/** ++ * struct dpaiop_cfg - Structure representing DPAIOP configuration ++ * @aiop_id: AIOP ID ++ * @aiop_container_id: AIOP container ID ++ */ ++struct dpaiop_cfg { ++ int aiop_id; ++ int aiop_container_id; ++}; ++ ++/** ++ * dpaiop_create() - Create the DPAIOP object. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @cfg: Configuration structure ++ * @token: Returned token; use in subsequent API calls ++ * ++ * Create the DPAIOP object, allocate required resources and ++ * perform required initialization. ++ * ++ * The object can be created either by declaring it in the ++ * DPL file, or by calling this function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent calls to ++ * this specific object. For objects that are created using the ++ * DPL file, call dpaiop_open function to get an authentication ++ * token first. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpaiop_cfg *cfg, ++ uint16_t *token); ++ ++/** ++ * dpaiop_destroy() - Destroy the DPAIOP object and release all its resources. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPAIOP object ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpaiop_destroy(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token); ++ ++/** ++ * dpaiop_reset() - Reset the DPAIOP, returns the object to initial state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPAIOP object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_reset(struct fsl_mc_io *mc_io, uint32_t cmd_flags, uint16_t token); ++ ++/** ++ * struct dpaiop_irq_cfg - IRQ configuration ++ * @addr: Address that must be written to signal a message-based interrupt ++ * @val: Value to write into irq_addr address ++ * @irq_num: A user defined number associated with this IRQ ++ */ ++struct dpaiop_irq_cfg { ++ uint64_t addr; ++ uint32_t val; ++ int irq_num; ++}; ++ ++/** ++ * dpaiop_set_irq() - Set IRQ information for the DPAIOP to trigger an interrupt. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPAIOP object ++ * @irq_index: Identifies the interrupt index to configure ++ * @irq_cfg: IRQ configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpaiop_irq_cfg *irq_cfg); ++ ++/** ++ * dpaiop_get_irq() - Get IRQ information from the DPAIOP. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPAIOP object ++ * @irq_index: The interrupt index to configure ++ * @type: Interrupt type: 0 represents message interrupt ++ * type (both irq_addr and irq_val are valid) ++ * @irq_cfg: IRQ attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpaiop_irq_cfg *irq_cfg); ++ ++/** ++ * dpaiop_set_irq_enable() - Set overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPAIOP object ++ * @irq_index: The interrupt index to configure ++ * @en: Interrupt state - enable = 1, disable = 0 ++ * ++ * Allows GPP software to control when interrupts are generated. ++ * Each interrupt can have up to 32 causes. The enable/disable control's the ++ * overall interrupt state. if the interrupt is disabled no causes will cause ++ * an interrupt. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en); ++ ++/** ++ * dpaiop_get_irq_enable() - Get overall interrupt state ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPAIOP object ++ * @irq_index: The interrupt index to configure ++ * @en: Returned interrupt state - enable = 1, disable = 0 ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en); ++ ++/** ++ * dpaiop_set_irq_mask() - Set interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPAIOP object ++ * @irq_index: The interrupt index to configure ++ * @mask: Event mask to trigger interrupt; ++ * each bit: ++ * 0 = ignore event ++ * 1 = consider event for asserting IRQ ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask); ++ ++/** ++ * dpaiop_get_irq_mask() - Get interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPAIOP object ++ * @irq_index: The interrupt index to configure ++ * @mask: Returned event mask to trigger interrupt ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask); ++ ++/** ++ * dpaiop_get_irq_status() - Get the current status of any pending interrupts. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPAIOP object ++ * @irq_index: The interrupt index to configure ++ * @status: Returned interrupts status - one bit per cause: ++ * 0 = no interrupt pending ++ * 1 = interrupt pending ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status); ++ ++/** ++ * dpaiop_clear_irq_status() - Clear a pending interrupt's status ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPAIOP object ++ * @irq_index: The interrupt index to configure ++ * @status: Bits to clear (W1C) - one bit per cause: ++ * 0 = don't change ++ * 1 = clear status bit ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status); ++ ++/** ++ * struct dpaiop_attr - Structure representing DPAIOP attributes ++ * @id: AIOP ID ++ * @version: DPAIOP version ++ */ ++struct dpaiop_attr { ++ int id; ++ /** ++ * struct version - Structure representing DPAIOP version ++ * @major: DPAIOP major version ++ * @minor: DPAIOP minor version ++ */ ++ struct { ++ uint16_t major; ++ uint16_t minor; ++ } version; ++}; ++ ++/** ++ * dpaiop_get_attributes - Retrieve DPAIOP attributes. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPAIOP object ++ * @attr: Returned object's attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpaiop_attr *attr); ++ ++/** ++ * struct dpaiop_load_cfg - AIOP load configuration ++ * @options: AIOP load options ++ * @img_iova: I/O virtual address of AIOP ELF image ++ * @img_size: Size of AIOP ELF image in memory (in bytes) ++ */ ++struct dpaiop_load_cfg { ++ uint64_t options; ++ uint64_t img_iova; ++ uint32_t img_size; ++}; ++ ++/** ++ * dpaiop_load_aiop() - Loads an image to AIOP ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPAIOP object ++ * @cfg: AIOP load configurations ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_load(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpaiop_load_cfg *cfg); ++ ++#define DPAIOP_RUN_OPT_DEBUG 0x0000000000000001ULL ++ ++/** ++ * struct dpaiop_run_cfg - AIOP run configuration ++ * @cores_mask: Mask of AIOP cores to run (core 0 in most significant bit) ++ * @options: Execution options (currently none defined) ++ * @args_iova: I/O virtual address of AIOP arguments ++ * @args_size: Size of AIOP arguments in memory (in bytes) ++ */ ++struct dpaiop_run_cfg { ++ uint64_t cores_mask; ++ uint64_t options; ++ uint64_t args_iova; ++ uint32_t args_size; ++}; ++ ++/** ++ * dpaiop_run_aiop() - Starts AIOP execution ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPAIOP object ++ * @cfg: AIOP run configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_run(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpaiop_run_cfg *cfg); ++ ++/** ++ * struct dpaiop_sl_version - AIOP SL (Service Layer) version ++ * @major: AIOP SL major version number ++ * @minor: AIOP SL minor version number ++ * @revision: AIOP SL revision number ++ */ ++struct dpaiop_sl_version { ++ uint32_t major; ++ uint32_t minor; ++ uint32_t revision; ++}; ++ ++/** ++ * dpaiop_get_sl_version() - Get AIOP SL (Service Layer) version ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPAIOP object ++ * @version: AIOP SL version number ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_get_sl_version(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpaiop_sl_version *version); ++ ++/** ++ * AIOP states ++ * ++ * AIOP internal states, can be retrieved by calling dpaiop_get_state() routine ++ */ ++ ++/** ++ * AIOP reset successfully completed. ++ */ ++#define DPAIOP_STATE_RESET_DONE 0x00000000 ++/** ++ * AIOP reset is ongoing. ++ */ ++#define DPAIOP_STATE_RESET_ONGOING 0x00000001 ++ ++/** ++ * AIOP image loading successfully completed. ++ */ ++#define DPAIOP_STATE_LOAD_DONE 0x00000002 ++/** ++ * AIOP image loading is ongoing. ++ */ ++#define DPAIOP_STATE_LOAD_ONGIONG 0x00000004 ++/** ++ * AIOP image loading completed with error. ++ */ ++#define DPAIOP_STATE_LOAD_ERROR 0x00000008 ++ ++/** ++ * Boot process of AIOP cores is ongoing. ++ */ ++#define DPAIOP_STATE_BOOT_ONGOING 0x00000010 ++/** ++ * Boot process of AIOP cores completed with an error. ++ */ ++#define DPAIOP_STATE_BOOT_ERROR 0x00000020 ++/** ++ * AIOP cores are functional and running ++ */ ++#define DPAIOP_STATE_RUNNING 0x00000040 ++/** @} */ ++ ++/** ++ * dpaiop_get_state() - Get AIOP state ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPAIOP object ++ * @state: AIOP state ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_get_state(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint32_t *state); ++ ++/** ++ * dpaiop_set_time_of_day() - Set AIOP internal time-of-day ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPAIOP object ++ * @time_of_day: Current number of milliseconds since the Epoch ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_set_time_of_day(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint64_t time_of_day); ++ ++/** ++ * dpaiop_get_time_of_day() - Get AIOP internal time-of-day ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPAIOP object ++ * @time_of_day: Current number of milliseconds since the Epoch ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpaiop_get_time_of_day(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint64_t *time_of_day); ++ ++#endif /* __FSL_DPAIOP_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpaiop_cmd.h b/drivers/net/dpaa2/mc/fsl_dpaiop_cmd.h +new file mode 100644 +index 0000000..5b77bb8 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpaiop_cmd.h +@@ -0,0 +1,190 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_DPAIOP_CMD_H ++#define _FSL_DPAIOP_CMD_H ++ ++/* DPAIOP Version */ ++#define DPAIOP_VER_MAJOR 1 ++#define DPAIOP_VER_MINOR 2 ++ ++/* Command IDs */ ++#define DPAIOP_CMDID_CLOSE 0x800 ++#define DPAIOP_CMDID_OPEN 0x80a ++#define DPAIOP_CMDID_CREATE 0x90a ++#define DPAIOP_CMDID_DESTROY 0x900 ++ ++#define DPAIOP_CMDID_GET_ATTR 0x004 ++#define DPAIOP_CMDID_RESET 0x005 ++ ++#define DPAIOP_CMDID_SET_IRQ 0x010 ++#define DPAIOP_CMDID_GET_IRQ 0x011 ++#define DPAIOP_CMDID_SET_IRQ_ENABLE 0x012 ++#define DPAIOP_CMDID_GET_IRQ_ENABLE 0x013 ++#define DPAIOP_CMDID_SET_IRQ_MASK 0x014 ++#define DPAIOP_CMDID_GET_IRQ_MASK 0x015 ++#define DPAIOP_CMDID_GET_IRQ_STATUS 0x016 ++#define DPAIOP_CMDID_CLEAR_IRQ_STATUS 0x017 ++ ++#define DPAIOP_CMDID_LOAD 0x280 ++#define DPAIOP_CMDID_RUN 0x281 ++#define DPAIOP_CMDID_GET_SL_VERSION 0x282 ++#define DPAIOP_CMDID_GET_STATE 0x283 ++#define DPAIOP_CMDID_SET_TIME_OF_DAY 0x284 ++#define DPAIOP_CMDID_GET_TIME_OF_DAY 0x285 ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_CMD_OPEN(cmd, dpaiop_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpaiop_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_CMD_CREATE(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, cfg->aiop_id);\ ++ MC_CMD_OP(cmd, 0, 32, 32, int, cfg->aiop_container_id);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, irq_index);\ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, irq_cfg->val);\ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr); \ ++ MC_CMD_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_CMD_GET_IRQ(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_RSP_GET_IRQ(cmd, type, irq_cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr); \ ++ MC_RSP_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, type); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_CMD_SET_IRQ_ENABLE(cmd, irq_index, en) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, en); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_CMD_GET_IRQ_ENABLE(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_RSP_GET_IRQ_ENABLE(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 8, uint8_t, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, mask);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_CMD_GET_IRQ_MASK(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_RSP_GET_IRQ_MASK(cmd, mask) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mask) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_RSP_GET_IRQ_STATUS(cmd, status) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, status) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_RSP_GET_ATTRIBUTES(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, attr->id);\ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->version.major);\ ++ MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->version.minor);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_CMD_LOAD(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, cfg->img_size); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->img_iova); \ ++ MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->options); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_CMD_RUN(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, cfg->args_size); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->cores_mask); \ ++ MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->options); \ ++ MC_CMD_OP(cmd, 3, 0, 64, uint64_t, cfg->args_iova); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_RSP_GET_SL_VERSION(cmd, version) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, version->major);\ ++ MC_RSP_OP(cmd, 0, 32, 32, uint32_t, version->minor);\ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, version->revision);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_RSP_GET_STATE(cmd, state) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, state) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_CMD_SET_TIME_OF_DAY(cmd, time_of_day) \ ++ MC_CMD_OP(cmd, 0, 0, 64, uint64_t, time_of_day) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPAIOP_RSP_GET_TIME_OF_DAY(cmd, time_of_day) \ ++ MC_RSP_OP(cmd, 0, 0, 64, uint64_t, time_of_day) ++ ++#endif /* _FSL_DPAIOP_CMD_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpbp.h b/drivers/net/dpaa2/mc/fsl_dpbp.h +new file mode 100644 +index 0000000..9856bb8 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpbp.h +@@ -0,0 +1,438 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPBP_H ++#define __FSL_DPBP_H ++ ++/* Data Path Buffer Pool API ++ * Contains initialization APIs and runtime control APIs for DPBP ++ */ ++ ++struct fsl_mc_io; ++ ++/** ++ * dpbp_open() - Open a control session for the specified object. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @dpbp_id: DPBP unique ID ++ * @token: Returned token; use in subsequent API calls ++ * ++ * This function can be used to open a control session for an ++ * already created object; an object may have been declared in ++ * the DPL or by calling the dpbp_create function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent commands for ++ * this specific object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpbp_id, ++ uint16_t *token); ++ ++/** ++ * dpbp_close() - Close the control session of the object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * ++ * After this function is called, no further operations are ++ * allowed on the object without opening a new control session. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * struct dpbp_cfg - Structure representing DPBP configuration ++ * @options: place holder ++ */ ++struct dpbp_cfg { ++ uint32_t options; ++}; ++ ++/** ++ * dpbp_create() - Create the DPBP object. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @cfg: Configuration structure ++ * @token: Returned token; use in subsequent API calls ++ * ++ * Create the DPBP object, allocate required resources and ++ * perform required initialization. ++ * ++ * The object can be created either by declaring it in the ++ * DPL file, or by calling this function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent calls to ++ * this specific object. For objects that are created using the ++ * DPL file, call dpbp_open function to get an authentication ++ * token first. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpbp_cfg *cfg, ++ uint16_t *token); ++ ++/** ++ * dpbp_destroy() - Destroy the DPBP object and release all its resources. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpbp_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpbp_enable() - Enable the DPBP. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpbp_disable() - Disable the DPBP. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpbp_is_enabled() - Check if the DPBP is enabled. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * @en: Returns '1' if object is enabled; '0' otherwise ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en); ++ ++/** ++ * dpbp_reset() - Reset the DPBP, returns the object to initial state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * struct dpbp_irq_cfg - IRQ configuration ++ * @addr: Address that must be written to signal a message-based interrupt ++ * @val: Value to write into irq_addr address ++ * @irq_num: A user defined number associated with this IRQ ++ */ ++struct dpbp_irq_cfg { ++ uint64_t addr; ++ uint32_t val; ++ int irq_num; ++}; ++ ++/** ++ * dpbp_set_irq() - Set IRQ information for the DPBP to trigger an interrupt. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * @irq_index: Identifies the interrupt index to configure ++ * @irq_cfg: IRQ configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpbp_irq_cfg *irq_cfg); ++ ++/** ++ * dpbp_get_irq() - Get IRQ information from the DPBP. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * @irq_index: The interrupt index to configure ++ * @type: Interrupt type: 0 represents message interrupt ++ * type (both irq_addr and irq_val are valid) ++ * @irq_cfg: IRQ attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpbp_irq_cfg *irq_cfg); ++ ++/** ++ * dpbp_set_irq_enable() - Set overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * @irq_index: The interrupt index to configure ++ * @en: Interrupt state - enable = 1, disable = 0 ++ * ++ * Allows GPP software to control when interrupts are generated. ++ * Each interrupt can have up to 32 causes. The enable/disable control's the ++ * overall interrupt state. if the interrupt is disabled no causes will cause ++ * an interrupt. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en); ++ ++/** ++ * dpbp_get_irq_enable() - Get overall interrupt state ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * @irq_index: The interrupt index to configure ++ * @en: Returned interrupt state - enable = 1, disable = 0 ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en); ++ ++/** ++ * dpbp_set_irq_mask() - Set interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * @irq_index: The interrupt index to configure ++ * @mask: Event mask to trigger interrupt; ++ * each bit: ++ * 0 = ignore event ++ * 1 = consider event for asserting IRQ ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask); ++ ++/** ++ * dpbp_get_irq_mask() - Get interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * @irq_index: The interrupt index to configure ++ * @mask: Returned event mask to trigger interrupt ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask); ++ ++/** ++ * dpbp_get_irq_status() - Get the current status of any pending interrupts. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * @irq_index: The interrupt index to configure ++ * @status: Returned interrupts status - one bit per cause: ++ * 0 = no interrupt pending ++ * 1 = interrupt pending ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status); ++ ++/** ++ * dpbp_clear_irq_status() - Clear a pending interrupt's status ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * @irq_index: The interrupt index to configure ++ * @status: Bits to clear (W1C) - one bit per cause: ++ * 0 = don't change ++ * 1 = clear status bit ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status); ++ ++/** ++ * struct dpbp_attr - Structure representing DPBP attributes ++ * @id: DPBP object ID ++ * @version: DPBP version ++ * @bpid: Hardware buffer pool ID; should be used as an argument in ++ * acquire/release operations on buffers ++ */ ++struct dpbp_attr { ++ int id; ++ /** ++ * struct version - Structure representing DPBP version ++ * @major: DPBP major version ++ * @minor: DPBP minor version ++ */ ++ struct { ++ uint16_t major; ++ uint16_t minor; ++ } version; ++ uint16_t bpid; ++}; ++ ++/** ++ * dpbp_get_attributes - Retrieve DPBP attributes. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * @attr: Returned object's attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpbp_attr *attr); ++ ++/** ++ * DPBP notifications options ++ */ ++ ++/** ++ * BPSCN write will attempt to allocate into a cache (coherent write) ++ */ ++#define DPBP_NOTIF_OPT_COHERENT_WRITE 0x00000001 ++ ++/** ++ * struct dpbp_notification_cfg - Structure representing DPBP notifications ++ * towards software ++ * @depletion_entry: below this threshold the pool is "depleted"; ++ * set it to '0' to disable it ++ * @depletion_exit: greater than or equal to this threshold the pool exit its ++ * "depleted" state ++ * @surplus_entry: above this threshold the pool is in "surplus" state; ++ * set it to '0' to disable it ++ * @surplus_exit: less than or equal to this threshold the pool exit its ++ * "surplus" state ++ * @message_iova: MUST be given if either 'depletion_entry' or 'surplus_entry' ++ * is not '0' (enable); I/O virtual address (must be in DMA-able memory), ++ * must be 16B aligned. ++ * @message_ctx: The context that will be part of the BPSCN message and will ++ * be written to 'message_iova' ++ * @options: Mask of available options; use 'DPBP_NOTIF_OPT_' values ++ */ ++struct dpbp_notification_cfg { ++ uint32_t depletion_entry; ++ uint32_t depletion_exit; ++ uint32_t surplus_entry; ++ uint32_t surplus_exit; ++ uint64_t message_iova; ++ uint64_t message_ctx; ++ uint16_t options; ++}; ++ ++/** ++ * dpbp_set_notifications() - Set notifications towards software ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * @cfg: notifications configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_set_notifications(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpbp_notification_cfg *cfg); ++ ++/** ++ * dpbp_get_notifications() - Get the notifications configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPBP object ++ * @cfg: notifications configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpbp_get_notifications(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpbp_notification_cfg *cfg); ++ ++#endif /* __FSL_DPBP_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpbp_cmd.h b/drivers/net/dpaa2/mc/fsl_dpbp_cmd.h +new file mode 100644 +index 0000000..71ad96a +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpbp_cmd.h +@@ -0,0 +1,172 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_DPBP_CMD_H ++#define _FSL_DPBP_CMD_H ++ ++/* DPBP Version */ ++#define DPBP_VER_MAJOR 2 ++#define DPBP_VER_MINOR 2 ++ ++/* Command IDs */ ++#define DPBP_CMDID_CLOSE 0x800 ++#define DPBP_CMDID_OPEN 0x804 ++#define DPBP_CMDID_CREATE 0x904 ++#define DPBP_CMDID_DESTROY 0x900 ++ ++#define DPBP_CMDID_ENABLE 0x002 ++#define DPBP_CMDID_DISABLE 0x003 ++#define DPBP_CMDID_GET_ATTR 0x004 ++#define DPBP_CMDID_RESET 0x005 ++#define DPBP_CMDID_IS_ENABLED 0x006 ++ ++#define DPBP_CMDID_SET_IRQ 0x010 ++#define DPBP_CMDID_GET_IRQ 0x011 ++#define DPBP_CMDID_SET_IRQ_ENABLE 0x012 ++#define DPBP_CMDID_GET_IRQ_ENABLE 0x013 ++#define DPBP_CMDID_SET_IRQ_MASK 0x014 ++#define DPBP_CMDID_GET_IRQ_MASK 0x015 ++#define DPBP_CMDID_GET_IRQ_STATUS 0x016 ++#define DPBP_CMDID_CLEAR_IRQ_STATUS 0x017 ++ ++#define DPBP_CMDID_SET_NOTIFICATIONS 0x01b0 ++#define DPBP_CMDID_GET_NOTIFICATIONS 0x01b1 ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPBP_CMD_OPEN(cmd, dpbp_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpbp_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPBP_RSP_IS_ENABLED(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPBP_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, irq_index);\ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, irq_cfg->val);\ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr); \ ++ MC_CMD_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPBP_CMD_GET_IRQ(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPBP_RSP_GET_IRQ(cmd, type, irq_cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr); \ ++ MC_RSP_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, type); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPBP_CMD_SET_IRQ_ENABLE(cmd, irq_index, en) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, en); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPBP_CMD_GET_IRQ_ENABLE(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPBP_RSP_GET_IRQ_ENABLE(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 8, uint8_t, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPBP_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, mask);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPBP_CMD_GET_IRQ_MASK(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPBP_RSP_GET_IRQ_MASK(cmd, mask) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mask) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPBP_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++/* cmd, param, offset, width, type, arg_name */ ++#define DPBP_RSP_GET_IRQ_STATUS(cmd, status) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, status) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPBP_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPBP_RSP_GET_ATTRIBUTES(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 16, 16, uint16_t, attr->bpid); \ ++ MC_RSP_OP(cmd, 0, 32, 32, int, attr->id);\ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->version.major);\ ++ MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->version.minor);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPBP_CMD_SET_NOTIFICATIONS(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, cfg->depletion_entry); \ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, cfg->depletion_exit);\ ++ MC_CMD_OP(cmd, 1, 0, 32, uint32_t, cfg->surplus_entry);\ ++ MC_CMD_OP(cmd, 1, 32, 32, uint32_t, cfg->surplus_exit);\ ++ MC_CMD_OP(cmd, 2, 0, 16, uint16_t, cfg->options);\ ++ MC_CMD_OP(cmd, 3, 0, 64, uint64_t, cfg->message_ctx);\ ++ MC_CMD_OP(cmd, 4, 0, 64, uint64_t, cfg->message_iova);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPBP_CMD_GET_NOTIFICATIONS(cmd, cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, cfg->depletion_entry); \ ++ MC_RSP_OP(cmd, 0, 32, 32, uint32_t, cfg->depletion_exit);\ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, cfg->surplus_entry);\ ++ MC_RSP_OP(cmd, 1, 32, 32, uint32_t, cfg->surplus_exit);\ ++ MC_RSP_OP(cmd, 2, 0, 16, uint16_t, cfg->options);\ ++ MC_RSP_OP(cmd, 3, 0, 64, uint64_t, cfg->message_ctx);\ ++ MC_RSP_OP(cmd, 4, 0, 64, uint64_t, cfg->message_iova);\ ++} while (0) ++#endif /* _FSL_DPBP_CMD_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpci.h b/drivers/net/dpaa2/mc/fsl_dpci.h +new file mode 100644 +index 0000000..d885935 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpci.h +@@ -0,0 +1,594 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPCI_H ++#define __FSL_DPCI_H ++ ++/* Data Path Communication Interface API ++ * Contains initialization APIs and runtime control APIs for DPCI ++ */ ++ ++struct fsl_mc_io; ++ ++/** General DPCI macros */ ++ ++/** ++ * Maximum number of Tx/Rx priorities per DPCI object ++ */ ++#define DPCI_PRIO_NUM 2 ++ ++/** ++ * Indicates an invalid frame queue ++ */ ++#define DPCI_FQID_NOT_VALID (uint32_t)(-1) ++ ++/** ++ * All queues considered; see dpci_set_rx_queue() ++ */ ++#define DPCI_ALL_QUEUES (uint8_t)(-1) ++ ++/** ++ * dpci_open() - Open a control session for the specified object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @dpci_id: DPCI unique ID ++ * @token: Returned token; use in subsequent API calls ++ * ++ * This function can be used to open a control session for an ++ * already created object; an object may have been declared in ++ * the DPL or by calling the dpci_create() function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent commands for ++ * this specific object. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpci_id, ++ uint16_t *token); ++ ++/** ++ * dpci_close() - Close the control session of the object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * ++ * After this function is called, no further operations are ++ * allowed on the object without opening a new control session. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * struct dpci_cfg - Structure representing DPCI configuration ++ * @num_of_priorities: Number of receive priorities (queues) for the DPCI; ++ * note, that the number of transmit priorities (queues) ++ * is determined by the number of receive priorities of ++ * the peer DPCI object ++ */ ++struct dpci_cfg { ++ uint8_t num_of_priorities; ++}; ++ ++/** ++ * dpci_create() - Create the DPCI object. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @cfg: Configuration structure ++ * @token: Returned token; use in subsequent API calls ++ * ++ * Create the DPCI object, allocate required resources and perform required ++ * initialization. ++ * ++ * The object can be created either by declaring it in the ++ * DPL file, or by calling this function. ++ * ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent calls to ++ * this specific object. For objects that are created using the ++ * DPL file, call dpci_open() function to get an authentication ++ * token first. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpci_cfg *cfg, ++ uint16_t *token); ++ ++/** ++ * dpci_destroy() - Destroy the DPCI object and release all its resources. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpci_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpci_enable() - Enable the DPCI, allow sending and receiving frames. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpci_disable() - Disable the DPCI, stop sending and receiving frames. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpci_is_enabled() - Check if the DPCI is enabled. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @en: Returns '1' if object is enabled; '0' otherwise ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en); ++ ++/** ++ * dpci_reset() - Reset the DPCI, returns the object to initial state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** DPCI IRQ Index and Events */ ++ ++/** ++ * IRQ index ++ */ ++#define DPCI_IRQ_INDEX 0 ++ ++/** ++ * IRQ event - indicates a change in link state ++ */ ++#define DPCI_IRQ_EVENT_LINK_CHANGED 0x00000001 ++/** ++ * IRQ event - indicates a connection event ++ */ ++#define DPCI_IRQ_EVENT_CONNECTED 0x00000002 ++/** ++ * IRQ event - indicates a disconnection event ++ */ ++#define DPCI_IRQ_EVENT_DISCONNECTED 0x00000004 ++ ++/** ++ * struct dpci_irq_cfg - IRQ configuration ++ * @addr: Address that must be written to signal a message-based interrupt ++ * @val: Value to write into irq_addr address ++ * @irq_num: A user defined number associated with this IRQ ++ */ ++struct dpci_irq_cfg { ++ uint64_t addr; ++ uint32_t val; ++ int irq_num; ++}; ++ ++/** ++ * dpci_set_irq() - Set IRQ information for the DPCI to trigger an interrupt. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @irq_index: Identifies the interrupt index to configure ++ * @irq_cfg: IRQ configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpci_irq_cfg *irq_cfg); ++ ++/** ++ * dpci_get_irq() - Get IRQ information from the DPCI. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @irq_index: The interrupt index to configure ++ * @type: Interrupt type: 0 represents message interrupt ++ * type (both irq_addr and irq_val are valid) ++ * @irq_cfg: IRQ attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpci_irq_cfg *irq_cfg); ++ ++/** ++ * dpci_set_irq_enable() - Set overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @irq_index: The interrupt index to configure ++ * @en: Interrupt state - enable = 1, disable = 0 ++ * ++ * Allows GPP software to control when interrupts are generated. ++ * Each interrupt can have up to 32 causes. The enable/disable control's the ++ * overall interrupt state. if the interrupt is disabled no causes will cause ++ * an interrupt. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en); ++ ++/** ++ * dpci_get_irq_enable() - Get overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @irq_index: The interrupt index to configure ++ * @en: Returned interrupt state - enable = 1, disable = 0 ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en); ++ ++/** ++ * dpci_set_irq_mask() - Set interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @irq_index: The interrupt index to configure ++ * @mask: event mask to trigger interrupt; ++ * each bit: ++ * 0 = ignore event ++ * 1 = consider event for asserting IRQ ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask); ++ ++/** ++ * dpci_get_irq_mask() - Get interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @irq_index: The interrupt index to configure ++ * @mask: Returned event mask to trigger interrupt ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask); ++ ++/** ++ * dpci_get_irq_status() - Get the current status of any pending interrupts. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @irq_index: The interrupt index to configure ++ * @status: Returned interrupts status - one bit per cause: ++ * 0 = no interrupt pending ++ * 1 = interrupt pending ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status); ++ ++/** ++ * dpci_clear_irq_status() - Clear a pending interrupt's status ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @irq_index: The interrupt index to configure ++ * @status: bits to clear (W1C) - one bit per cause: ++ * 0 = don't change ++ * 1 = clear status bit ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status); ++ ++/** ++ * struct dpci_attr - Structure representing DPCI attributes ++ * @id: DPCI object ID ++ * @version: DPCI version ++ * @num_of_priorities: Number of receive priorities ++ */ ++struct dpci_attr { ++ int id; ++ /** ++ * struct version - Structure representing DPCI attributes ++ * @major: DPCI major version ++ * @minor: DPCI minor version ++ */ ++ struct { ++ uint16_t major; ++ uint16_t minor; ++ } version; ++ uint8_t num_of_priorities; ++}; ++ ++/** ++ * dpci_get_attributes() - Retrieve DPCI attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @attr: Returned object's attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpci_attr *attr); ++ ++/** ++ * struct dpci_peer_attr - Structure representing the peer DPCI attributes ++ * @peer_id: DPCI peer id; if no peer is connected returns (-1) ++ * @num_of_priorities: The pper's number of receive priorities; determines the ++ * number of transmit priorities for the local DPCI object ++ */ ++struct dpci_peer_attr { ++ int peer_id; ++ uint8_t num_of_priorities; ++}; ++ ++/** ++ * dpci_get_peer_attributes() - Retrieve peer DPCI attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @attr: Returned peer attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_get_peer_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpci_peer_attr *attr); ++ ++/** ++ * dpci_get_link_state() - Retrieve the DPCI link state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @up: Returned link state; returns '1' if link is up, '0' otherwise ++ * ++ * DPCI can be connected to another DPCI, together they ++ * create a 'link'. In order to use the DPCI Tx and Rx queues, ++ * both objects must be enabled. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_get_link_state(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *up); ++ ++/** ++ * enum dpci_dest - DPCI destination types ++ * @DPCI_DEST_NONE: Unassigned destination; The queue is set in parked mode ++ * and does not generate FQDAN notifications; user is ++ * expected to dequeue from the queue based on polling or ++ * other user-defined method ++ * @DPCI_DEST_DPIO: The queue is set in schedule mode and generates FQDAN ++ * notifications to the specified DPIO; user is expected ++ * to dequeue from the queue only after notification is ++ * received ++ * @DPCI_DEST_DPCON: The queue is set in schedule mode and does not generate ++ * FQDAN notifications, but is connected to the specified ++ * DPCON object; ++ * user is expected to dequeue from the DPCON channel ++ */ ++enum dpci_dest { ++ DPCI_DEST_NONE = 0, ++ DPCI_DEST_DPIO = 1, ++ DPCI_DEST_DPCON = 2 ++}; ++ ++/** ++ * struct dpci_dest_cfg - Structure representing DPCI destination configuration ++ * @dest_type: Destination type ++ * @dest_id: Either DPIO ID or DPCON ID, depending on the destination type ++ * @priority: Priority selection within the DPIO or DPCON channel; valid ++ * values are 0-1 or 0-7, depending on the number of priorities ++ * in that channel; not relevant for 'DPCI_DEST_NONE' option ++ */ ++struct dpci_dest_cfg { ++ enum dpci_dest dest_type; ++ int dest_id; ++ uint8_t priority; ++}; ++ ++/** DPCI queue modification options */ ++ ++/** ++ * Select to modify the user's context associated with the queue ++ */ ++#define DPCI_QUEUE_OPT_USER_CTX 0x00000001 ++ ++/** ++ * Select to modify the queue's destination ++ */ ++#define DPCI_QUEUE_OPT_DEST 0x00000002 ++ ++/** ++ * struct dpci_rx_queue_cfg - Structure representing RX queue configuration ++ * @options: Flags representing the suggested modifications to the queue; ++ * Use any combination of 'DPCI_QUEUE_OPT_' flags ++ * @user_ctx: User context value provided in the frame descriptor of each ++ * dequeued frame; ++ * valid only if 'DPCI_QUEUE_OPT_USER_CTX' is contained in ++ * 'options' ++ * @dest_cfg: Queue destination parameters; ++ * valid only if 'DPCI_QUEUE_OPT_DEST' is contained in 'options' ++ */ ++struct dpci_rx_queue_cfg { ++ uint32_t options; ++ uint64_t user_ctx; ++ struct dpci_dest_cfg dest_cfg; ++}; ++ ++/** ++ * dpci_set_rx_queue() - Set Rx queue configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @priority: Select the queue relative to number of ++ * priorities configured at DPCI creation; use ++ * DPCI_ALL_QUEUES to configure all Rx queues ++ * identically. ++ * @cfg: Rx queue configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_set_rx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t priority, ++ const struct dpci_rx_queue_cfg *cfg); ++ ++/** ++ * struct dpci_rx_queue_attr - Structure representing Rx queue attributes ++ * @user_ctx: User context value provided in the frame descriptor of each ++ * dequeued frame ++ * @dest_cfg: Queue destination configuration ++ * @fqid: Virtual FQID value to be used for dequeue operations ++ */ ++struct dpci_rx_queue_attr { ++ uint64_t user_ctx; ++ struct dpci_dest_cfg dest_cfg; ++ uint32_t fqid; ++}; ++ ++/** ++ * dpci_get_rx_queue() - Retrieve Rx queue attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @priority: Select the queue relative to number of ++ * priorities configured at DPCI creation ++ * @attr: Returned Rx queue attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_get_rx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t priority, ++ struct dpci_rx_queue_attr *attr); ++ ++/** ++ * struct dpci_tx_queue_attr - Structure representing attributes of Tx queues ++ * @fqid: Virtual FQID to be used for sending frames to peer DPCI; ++ * returns 'DPCI_FQID_NOT_VALID' if a no peer is connected or if ++ * the selected priority exceeds the number of priorities of the ++ * peer DPCI object ++ */ ++struct dpci_tx_queue_attr { ++ uint32_t fqid; ++}; ++ ++/** ++ * dpci_get_tx_queue() - Retrieve Tx queue attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @priority: Select the queue relative to number of ++ * priorities of the peer DPCI object ++ * @attr: Returned Tx queue attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpci_get_tx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t priority, ++ struct dpci_tx_queue_attr *attr); ++ ++#endif /* __FSL_DPCI_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpci_cmd.h b/drivers/net/dpaa2/mc/fsl_dpci_cmd.h +new file mode 100644 +index 0000000..f45e435 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpci_cmd.h +@@ -0,0 +1,200 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_DPCI_CMD_H ++#define _FSL_DPCI_CMD_H ++ ++/* DPCI Version */ ++#define DPCI_VER_MAJOR 2 ++#define DPCI_VER_MINOR 2 ++ ++/* Command IDs */ ++#define DPCI_CMDID_CLOSE 0x800 ++#define DPCI_CMDID_OPEN 0x807 ++#define DPCI_CMDID_CREATE 0x907 ++#define DPCI_CMDID_DESTROY 0x900 ++ ++#define DPCI_CMDID_ENABLE 0x002 ++#define DPCI_CMDID_DISABLE 0x003 ++#define DPCI_CMDID_GET_ATTR 0x004 ++#define DPCI_CMDID_RESET 0x005 ++#define DPCI_CMDID_IS_ENABLED 0x006 ++ ++#define DPCI_CMDID_SET_IRQ 0x010 ++#define DPCI_CMDID_GET_IRQ 0x011 ++#define DPCI_CMDID_SET_IRQ_ENABLE 0x012 ++#define DPCI_CMDID_GET_IRQ_ENABLE 0x013 ++#define DPCI_CMDID_SET_IRQ_MASK 0x014 ++#define DPCI_CMDID_GET_IRQ_MASK 0x015 ++#define DPCI_CMDID_GET_IRQ_STATUS 0x016 ++#define DPCI_CMDID_CLEAR_IRQ_STATUS 0x017 ++ ++#define DPCI_CMDID_SET_RX_QUEUE 0x0e0 ++#define DPCI_CMDID_GET_LINK_STATE 0x0e1 ++#define DPCI_CMDID_GET_PEER_ATTR 0x0e2 ++#define DPCI_CMDID_GET_RX_QUEUE 0x0e3 ++#define DPCI_CMDID_GET_TX_QUEUE 0x0e4 ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_CMD_OPEN(cmd, dpci_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpci_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_CMD_CREATE(cmd, cfg) \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, cfg->num_of_priorities) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_RSP_IS_ENABLED(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, irq_index);\ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, irq_cfg->val);\ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\ ++ MC_CMD_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_CMD_GET_IRQ(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_RSP_GET_IRQ(cmd, type, irq_cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\ ++ MC_RSP_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, type); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_CMD_SET_IRQ_ENABLE(cmd, irq_index, en) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, en); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_CMD_GET_IRQ_ENABLE(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_RSP_GET_IRQ_ENABLE(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 8, uint8_t, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, mask); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_CMD_GET_IRQ_MASK(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_RSP_GET_IRQ_MASK(cmd, mask) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mask) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_RSP_GET_IRQ_STATUS(cmd, status) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, status) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_RSP_GET_ATTR(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, attr->id);\ ++ MC_RSP_OP(cmd, 0, 48, 8, uint8_t, attr->num_of_priorities);\ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->version.major);\ ++ MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->version.minor);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_RSP_GET_PEER_ATTR(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, attr->peer_id);\ ++ MC_RSP_OP(cmd, 1, 0, 8, uint8_t, attr->num_of_priorities);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_RSP_GET_LINK_STATE(cmd, up) \ ++ MC_RSP_OP(cmd, 0, 0, 1, int, up) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_CMD_SET_RX_QUEUE(cmd, priority, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, cfg->dest_cfg.dest_id);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->dest_cfg.priority);\ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, priority);\ ++ MC_CMD_OP(cmd, 0, 48, 4, enum dpci_dest, cfg->dest_cfg.dest_type);\ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->user_ctx);\ ++ MC_CMD_OP(cmd, 2, 0, 32, uint32_t, cfg->options);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_CMD_GET_RX_QUEUE(cmd, priority) \ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, priority) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_RSP_GET_RX_QUEUE(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, attr->dest_cfg.dest_id);\ ++ MC_RSP_OP(cmd, 0, 32, 8, uint8_t, attr->dest_cfg.priority);\ ++ MC_RSP_OP(cmd, 0, 48, 4, enum dpci_dest, attr->dest_cfg.dest_type);\ ++ MC_RSP_OP(cmd, 1, 0, 8, uint64_t, attr->user_ctx);\ ++ MC_RSP_OP(cmd, 2, 0, 32, uint32_t, attr->fqid);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_CMD_GET_TX_QUEUE(cmd, priority) \ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, priority) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCI_RSP_GET_TX_QUEUE(cmd, attr) \ ++ MC_RSP_OP(cmd, 0, 32, 32, uint32_t, attr->fqid) ++ ++#endif /* _FSL_DPCI_CMD_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpcon.h b/drivers/net/dpaa2/mc/fsl_dpcon.h +new file mode 100644 +index 0000000..2555be5 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpcon.h +@@ -0,0 +1,407 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPCON_H ++#define __FSL_DPCON_H ++ ++/* Data Path Concentrator API ++ * Contains initialization APIs and runtime control APIs for DPCON ++ */ ++ ++struct fsl_mc_io; ++ ++/** General DPCON macros */ ++ ++/** ++ * Use it to disable notifications; see dpcon_set_notification() ++ */ ++#define DPCON_INVALID_DPIO_ID (int)(-1) ++ ++/** ++ * dpcon_open() - Open a control session for the specified object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @dpcon_id: DPCON unique ID ++ * @token: Returned token; use in subsequent API calls ++ * ++ * This function can be used to open a control session for an ++ * already created object; an object may have been declared in ++ * the DPL or by calling the dpcon_create() function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent commands for ++ * this specific object. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpcon_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpcon_id, ++ uint16_t *token); ++ ++/** ++ * dpcon_close() - Close the control session of the object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * ++ * After this function is called, no further operations are ++ * allowed on the object without opening a new control session. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpcon_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * struct dpcon_cfg - Structure representing DPCON configuration ++ * @num_priorities: Number of priorities for the DPCON channel (1-8) ++ */ ++struct dpcon_cfg { ++ uint8_t num_priorities; ++}; ++ ++/** ++ * dpcon_create() - Create the DPCON object. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @cfg: Configuration structure ++ * @token: Returned token; use in subsequent API calls ++ * ++ * Create the DPCON object, allocate required resources and ++ * perform required initialization. ++ * ++ * The object can be created either by declaring it in the ++ * DPL file, or by calling this function. ++ * ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent calls to ++ * this specific object. For objects that are created using the ++ * DPL file, call dpcon_open() function to get an authentication ++ * token first. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpcon_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpcon_cfg *cfg, ++ uint16_t *token); ++ ++/** ++ * dpcon_destroy() - Destroy the DPCON object and release all its resources. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpcon_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpcon_enable() - Enable the DPCON ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * ++ * Return: '0' on Success; Error code otherwise ++ */ ++int dpcon_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpcon_disable() - Disable the DPCON ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * ++ * Return: '0' on Success; Error code otherwise ++ */ ++int dpcon_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpcon_is_enabled() - Check if the DPCON is enabled. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * @en: Returns '1' if object is enabled; '0' otherwise ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpcon_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en); ++ ++/** ++ * dpcon_reset() - Reset the DPCON, returns the object to initial state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpcon_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * struct dpcon_irq_cfg - IRQ configuration ++ * @addr: Address that must be written to signal a message-based interrupt ++ * @val: Value to write into irq_addr address ++ * @irq_num: A user defined number associated with this IRQ ++ */ ++struct dpcon_irq_cfg { ++ uint64_t addr; ++ uint32_t val; ++ int irq_num; ++}; ++ ++/** ++ * dpcon_set_irq() - Set IRQ information for the DPCON to trigger an interrupt. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * @irq_index: Identifies the interrupt index to configure ++ * @irq_cfg: IRQ configuration ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpcon_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpcon_irq_cfg *irq_cfg); ++ ++/** ++ * dpcon_get_irq() - Get IRQ information from the DPCON. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * @irq_index: The interrupt index to configure ++ * @type: Interrupt type: 0 represents message interrupt ++ * type (both irq_addr and irq_val are valid) ++ * @irq_cfg: IRQ attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpcon_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpcon_irq_cfg *irq_cfg); ++ ++/** ++ * dpcon_set_irq_enable() - Set overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * @irq_index: The interrupt index to configure ++ * @en: Interrupt state - enable = 1, disable = 0 ++ * ++ * Allows GPP software to control when interrupts are generated. ++ * Each interrupt can have up to 32 causes. The enable/disable control's the ++ * overall interrupt state. if the interrupt is disabled no causes will cause ++ * an interrupt. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpcon_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en); ++ ++/** ++ * dpcon_get_irq_enable() - Get overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * @irq_index: The interrupt index to configure ++ * @en: Returned interrupt state - enable = 1, disable = 0 ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpcon_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en); ++ ++/** ++ * dpcon_set_irq_mask() - Set interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * @irq_index: The interrupt index to configure ++ * @mask: Event mask to trigger interrupt; ++ * each bit: ++ * 0 = ignore event ++ * 1 = consider event for asserting IRQ ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpcon_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask); ++ ++/** ++ * dpcon_get_irq_mask() - Get interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * @irq_index: The interrupt index to configure ++ * @mask: Returned event mask to trigger interrupt ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpcon_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask); ++ ++/** ++ * dpcon_get_irq_status() - Get the current status of any pending interrupts. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * @irq_index: The interrupt index to configure ++ * @status: interrupts status - one bit per cause: ++ * 0 = no interrupt pending ++ * 1 = interrupt pending ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpcon_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status); ++ ++/** ++ * dpcon_clear_irq_status() - Clear a pending interrupt's status ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * @irq_index: The interrupt index to configure ++ * @status: bits to clear (W1C) - one bit per cause: ++ * 0 = don't change ++ * 1 = clear status bit ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpcon_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status); ++ ++/** ++ * struct dpcon_attr - Structure representing DPCON attributes ++ * @id: DPCON object ID ++ * @version: DPCON version ++ * @qbman_ch_id: Channel ID to be used by dequeue operation ++ * @num_priorities: Number of priorities for the DPCON channel (1-8) ++ */ ++struct dpcon_attr { ++ int id; ++ /** ++ * struct version - DPCON version ++ * @major: DPCON major version ++ * @minor: DPCON minor version ++ */ ++ struct { ++ uint16_t major; ++ uint16_t minor; ++ } version; ++ uint16_t qbman_ch_id; ++ uint8_t num_priorities; ++}; ++ ++/** ++ * dpcon_get_attributes() - Retrieve DPCON attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * @attr: Object's attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpcon_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpcon_attr *attr); ++ ++/** ++ * struct dpcon_notification_cfg - Structure representing notification parameters ++ * @dpio_id: DPIO object ID; must be configured with a notification channel; ++ * to disable notifications set it to 'DPCON_INVALID_DPIO_ID'; ++ * @priority: Priority selection within the DPIO channel; valid values ++ * are 0-7, depending on the number of priorities in that channel ++ * @user_ctx: User context value provided with each CDAN message ++ */ ++struct dpcon_notification_cfg { ++ int dpio_id; ++ uint8_t priority; ++ uint64_t user_ctx; ++}; ++ ++/** ++ * dpcon_set_notification() - Set DPCON notification destination ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCON object ++ * @cfg: Notification parameters ++ * ++ * Return: '0' on Success; Error code otherwise ++ */ ++int dpcon_set_notification(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpcon_notification_cfg *cfg); ++ ++#endif /* __FSL_DPCON_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpcon_cmd.h b/drivers/net/dpaa2/mc/fsl_dpcon_cmd.h +new file mode 100644 +index 0000000..ecb40d0 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpcon_cmd.h +@@ -0,0 +1,162 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_DPCON_CMD_H ++#define _FSL_DPCON_CMD_H ++ ++/* DPCON Version */ ++#define DPCON_VER_MAJOR 2 ++#define DPCON_VER_MINOR 2 ++ ++/* Command IDs */ ++#define DPCON_CMDID_CLOSE 0x800 ++#define DPCON_CMDID_OPEN 0x808 ++#define DPCON_CMDID_CREATE 0x908 ++#define DPCON_CMDID_DESTROY 0x900 ++ ++#define DPCON_CMDID_ENABLE 0x002 ++#define DPCON_CMDID_DISABLE 0x003 ++#define DPCON_CMDID_GET_ATTR 0x004 ++#define DPCON_CMDID_RESET 0x005 ++#define DPCON_CMDID_IS_ENABLED 0x006 ++ ++#define DPCON_CMDID_SET_IRQ 0x010 ++#define DPCON_CMDID_GET_IRQ 0x011 ++#define DPCON_CMDID_SET_IRQ_ENABLE 0x012 ++#define DPCON_CMDID_GET_IRQ_ENABLE 0x013 ++#define DPCON_CMDID_SET_IRQ_MASK 0x014 ++#define DPCON_CMDID_GET_IRQ_MASK 0x015 ++#define DPCON_CMDID_GET_IRQ_STATUS 0x016 ++#define DPCON_CMDID_CLEAR_IRQ_STATUS 0x017 ++ ++#define DPCON_CMDID_SET_NOTIFICATION 0x100 ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCON_CMD_OPEN(cmd, dpcon_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpcon_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCON_CMD_CREATE(cmd, cfg) \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, cfg->num_priorities) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCON_RSP_IS_ENABLED(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCON_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, irq_index);\ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, irq_cfg->val);\ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\ ++ MC_CMD_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCON_CMD_GET_IRQ(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCON_RSP_GET_IRQ(cmd, type, irq_cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val);\ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\ ++ MC_RSP_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, type);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCON_CMD_SET_IRQ_ENABLE(cmd, irq_index, en) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, en); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCON_CMD_GET_IRQ_ENABLE(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCON_RSP_GET_IRQ_ENABLE(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 8, uint8_t, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCON_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, mask); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCON_CMD_GET_IRQ_MASK(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCON_RSP_GET_IRQ_MASK(cmd, mask) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mask) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCON_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCON_RSP_GET_IRQ_STATUS(cmd, status) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, status) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCON_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCON_RSP_GET_ATTR(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, attr->id);\ ++ MC_RSP_OP(cmd, 0, 32, 16, uint16_t, attr->qbman_ch_id);\ ++ MC_RSP_OP(cmd, 0, 48, 8, uint8_t, attr->num_priorities);\ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->version.major);\ ++ MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->version.minor);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPCON_CMD_SET_NOTIFICATION(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, cfg->dpio_id);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->priority);\ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->user_ctx);\ ++} while (0) ++ ++#endif /* _FSL_DPCON_CMD_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpdbg.h b/drivers/net/dpaa2/mc/fsl_dpdbg.h +new file mode 100644 +index 0000000..ead22e8 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpdbg.h +@@ -0,0 +1,635 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPDBG_H ++#define __FSL_DPDBG_H ++ ++#include ++#include ++#include ++ ++/* Data Path Debug API ++ * Contains initialization APIs and runtime control APIs for DPDBG ++ */ ++ ++struct fsl_mc_io; ++ ++/** ++ * dpdbg_open() - Open a control session for the specified object. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @dpdbg_id: DPDBG unique ID ++ * @token: Returned token; use in subsequent API calls ++ * ++ * This function can be used to open a control session for an ++ * already created object; ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent commands for ++ * this specific object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpdbg_id, ++ uint16_t *token); ++ ++/** ++ * dpdbg_close() - Close the control session of the object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * ++ * After this function is called, no further operations are ++ * allowed on the object without opening a new control session. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * struct dpdbg_attr - Structure representing DPDBG attributes ++ * @id: DPDBG object ID ++ * @version: DPDBG version ++ */ ++struct dpdbg_attr { ++ int id; ++ /** ++ * struct version - Structure representing DPDBG version ++ * @major: DPDBG major version ++ * @minor: DPDBG minor version ++ */ ++ struct { ++ uint16_t major; ++ uint16_t minor; ++ } version; ++}; ++ ++/** ++ * dpdbg_get_attributes - Retrieve DPDBG attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * @attr: Returned object's attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpdbg_attr *attr); ++ ++/** ++ * struct dpdbg_dpni_info - Info of DPNI ++ * @max_senders: Maximum number of different senders; used as the number ++ * of dedicated Tx flows; Non-power-of-2 values are rounded ++ * up to the next power-of-2 value as hardware demands it; ++ * '0' will be treated as '1' ++ * @qdid: Virtual QDID. ++ * @err_fqid: Virtual FQID for error queues ++ * @tx_conf_fqid: Virtual FQID for global TX confirmation queue ++ */ ++struct dpdbg_dpni_info { ++ uint8_t max_senders; ++ uint32_t qdid; ++ uint32_t err_fqid; ++ uint32_t tx_conf_fqid; ++}; ++ ++/** ++ * dpdbg_get_dpni_info() - Retrieve info for a specific DPNI ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * @dpni_id: The requested DPNI ID ++ * @info: The returned info ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_get_dpni_info(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpni_id, ++ struct dpdbg_dpni_info *info); ++ ++/** ++ * dpdbg_get_dpni_private_fqid() - Retrieve the virtual TX confirmation queue ++ * FQID of the required DPNI ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * @dpni_id: The requested DPNI ID ++ * @sender_id: The requested sender ID ++ * @fqid: The returned virtual private TX confirmation FQID. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_get_dpni_priv_tx_conf_fqid(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpni_id, ++ uint8_t sender_id, ++ uint32_t *fqid); ++ ++/** ++ * struct dpdbg_dpcon_info - Info of DPCON ++ * @ch_id: Channel ID ++ */ ++struct dpdbg_dpcon_info { ++ uint32_t ch_id; ++}; ++ ++/** ++ * dpdbg_get_dpcon_info() - Retrieve info of DPCON ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * @dpcon_id: The requested DPCON ID ++ * @info: The returned info. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_get_dpcon_info(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpcon_id, ++ struct dpdbg_dpcon_info *info); ++ ++/** ++ * struct dpdbg_dpbp_info - Info of DPBP ++ * @bpid: Virtual buffer pool ID ++ */ ++struct dpdbg_dpbp_info { ++ uint32_t bpid; ++}; ++ ++/** ++ * dpdbg_get_dpbp_info() - Retrieve info of DPBP ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * @dpbp_id: The requested DPBP ID ++ * @info: The returned info. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_get_dpbp_info(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpbp_id, ++ struct dpdbg_dpbp_info *info); ++ ++/** ++ * dpdbg_get_dpci_fqid() - Retrieve the virtual FQID of the required DPCI ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * @dpci_id: The requested DPCI ID ++ * @priority: Select the queue relative to number of priorities configured at ++ * DPCI creation ++ * @fqid: The returned virtual FQID. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_get_dpci_fqid(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpci_id, ++ uint8_t priority, ++ uint32_t *fqid); ++ ++/** ++ * Maximum size for rule match (in bytes) ++ */ ++#define DPDBG_MAX_RULE_SIZE 56 ++/** ++ * Disable marking ++ */ ++#define DPDBG_DISABLE_MARKING 0xFF ++ ++/** ++ * dpdbg_prepare_ctlu_global_rule() - function prepare extract parameters ++ * @dpkg_rule: defining a full Key Generation profile (rule) ++ * @rule_buf: Zeroed 256 bytes of memory before mapping it to DMA ++ * ++ * This function has to be called before dpdbg_set_global_marking() ++ */ ++int dpdbg_prepare_ctlu_global_rule(struct dpkg_profile_cfg *dpkg_rule, ++ uint8_t *rule_buf); ++ ++/** ++ * struct dpdbg_rule_cfg - Rule configuration for table lookup ++ * @key_iova: I/O virtual address of the key (must be in DMA-able memory) ++ * @rule_iova: I/O virtual address of the rule (must be in DMA-able memory) ++ * @mask_iova: I/O virtual address of the mask (must be in DMA-able memory) ++ * @key_size: key and mask size (in bytes) ++ */ ++struct dpdbg_rule_cfg { ++ uint64_t key_iova; ++ uint64_t mask_iova; ++ uint64_t rule_iova; ++ uint8_t key_size; ++}; ++ ++/** ++ * dpdbg_set_ctlu_global_marking() - Set marking for all match rule frames ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * @marking: The requested Debug marking ++ * @cfg: Marking rule to add ++ * ++ * Warning: must be called after dpdbg_prepare_global_rule() ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_set_ctlu_global_marking(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t marking, ++ struct dpdbg_rule_cfg *cfg); ++ ++/** ++ * All traffic classes considered ++ */ ++#define DPDBG_DPNI_ALL_TCS (uint8_t)(-1) ++/** ++ * All flows within traffic class considered ++ */ ++#define DPDBG_DPNI_ALL_TC_FLOWS (uint8_t)(-1) ++/** ++ * All buffer pools considered ++ */ ++#define DPDBG_DPNI_ALL_DPBP (uint8_t)(-1) ++ ++/** ++ * struct dpdbg_dpni_rx_marking_cfg - Ingress frame configuration ++ * @tc_id: Traffic class ID (0-7); DPDBG_DPNI_ALL_TCS for all traffic classes. ++ * @flow_id: Rx flow id within the traffic class; use ++ * 'DPDBG_DPNI_ALL_TC_FLOWS' to set all flows within this tc_id; ++ * ignored if tc_id is set to 'DPDBG_DPNI_ALL_TCS'; ++ * @dpbp_id: buffer pool ID; 'DPDBG_DPNI_ALL_DPBP' to set all DPBP ++ * @marking: Marking for match frames; ++ * 'DPDBG_DISABLE_MARKING' for disable marking ++ */ ++struct dpdbg_dpni_rx_marking_cfg { ++ uint8_t tc_id; ++ uint16_t flow_id; ++ uint16_t dpbp_id; ++ uint8_t marking; ++}; ++ ++/** ++ * dpdbg_set_dpni_rx_marking() - Set Rx frame marking for DPNI ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * @dpni_id: The requested DPNI ID ++ * @cfg: RX frame marking configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_set_dpni_rx_marking(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpni_id, ++ struct dpdbg_dpni_rx_marking_cfg *cfg); ++ ++/* selects global confirmation queues */ ++#define DPDBG_DPNI_GLOBAL_TX_CONF_QUEUE (uint16_t)(-1) ++ ++/** ++ * dpdbg_set_dpni_tx_conf_marking() - Set Tx frame marking for DPNI ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * @dpni_id: The requested DPNI ID ++ * @sender_id: Sender Id for the confirmation queue; ++ * 'DPDBG_DPNI_GLOBAL_TX_CONF_QUEUE' for global confirmation queue ++ * @marking: The requested marking; ++ * 'DPDBG_DISABLE_MARKING' for disable marking ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_set_dpni_tx_conf_marking(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpni_id, ++ uint16_t sender_id, ++ uint8_t marking); ++ ++/** ++ * dpdbg_set_dpio_marking() - Set debug frame marking on enqueue ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * @dpio_id: The requested DPIO ID ++ * @marking: The requested marking; ++ * 'DPDBG_DISABLE_MARKING' for disable marking ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_set_dpio_marking(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpio_id, ++ uint8_t marking); ++ ++/** ++ * enum dpdbg_verbosity_level - Trace verbosity level ++ * @DPDBG_VERBOSITY_LEVEL_DISABLE: Trace disabled ++ * @DPDBG_VERBOSITY_LEVEL_TERSE: Terse trace ++ * @DPDBG_VERBOSITY_LEVEL_VERBOSE: Verbose trace ++ */ ++enum dpdbg_verbosity_level { ++ DPDBG_VERBOSITY_LEVEL_DISABLE = 0, ++ DPDBG_VERBOSITY_LEVEL_TERSE, ++ DPDBG_VERBOSITY_LEVEL_VERBOSE ++}; ++ ++/** ++ * dpdbg_set_ctlu_global_trace() - Set global trace configuration for CTLU trace ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * @cfg: trace rule to add ++ * ++ * Warning: must be called after dpdbg_prepare_global_rule() ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_set_ctlu_global_trace(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpdbg_rule_cfg *cfg); ++ ++/** ++ * Number of DPIO trace points ++ */ ++#define DPDBG_NUM_OF_DPIO_TRACE_POINTS 2 ++ ++/** ++ * enum dpdbg_dpio_trace_type - Define Trace point type ++ * @DPDBG_DPIO_TRACE_TYPE_ENQUEUE: This trace point triggers when an enqueue ++ * command, received via this portal, ++ * and containing a marked frame, is executed ++ * @DPDBG_DPIO_TRACE_TYPE_DEFERRED: This trace point triggers when the deferred ++ * enqueue of a marked frame received via this ++ * portal completes ++ */ ++enum dpdbg_dpio_trace_type { ++ DPDBG_DPIO_TRACE_TYPE_ENQUEUE = 0, ++ DPDBG_DPIO_TRACE_TYPE_DEFERRED = 1 ++}; ++ ++/** ++ * struct dpdbg_dpio_trace_cfg - Configure the behavior of a trace point ++ * when a frame marked with the specified DD code point is ++ * encountered ++ * @marking: this field will be written into the DD field of every FD ++ * enqueued in this DPIO. ++ * 'DPDBG_DISABLE_MARKING' for disable marking ++ * @verbosity: Verbosity level ++ * @enqueue_type: Enqueue trace point type defining a full Key Generation ++ * profile (rule) ++ */ ++struct dpdbg_dpio_trace_cfg { ++ uint8_t marking; ++ enum dpdbg_verbosity_level verbosity; ++ enum dpdbg_dpio_trace_type enqueue_type; ++}; ++ ++/** ++ * dpdbg_set_dpio_trace() - Set trace for DPIO for every enqueued frame to ++ * the portal ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * @dpio_id: The requested DPIO ID ++ * @trace_point: Trace points configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_set_dpio_trace(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpio_id, ++ struct dpdbg_dpio_trace_cfg ++ trace_point[DPDBG_NUM_OF_DPIO_TRACE_POINTS]); ++ ++/** ++ * struct dpdbg_dpni_trace_cfg - Configure the behavior of a trace point when a ++ * @tc_id: Traffic class ID (0-7); DPDBG_DPNI_ALL_TCS for all traffic classes. ++ * @flow_id: Rx flow id within the traffic class; use ++ * 'DPDBG_DPNI_ALL_TC_FLOWS' to set all flows within this tc_id; ++ * ignored if tc_id is set to 'DPDBG_DPNI_ALL_TCS'; ++ * @dpbp_id: buffer pool ID; 'DPDBG_DPNI_ALL_DPBP' to set all DPBP ++ * @marking: Marking for match frames; ++ * 'DPDBG_DISABLE_MARKING' for disable marking ++ */ ++struct dpdbg_dpni_rx_trace_cfg { ++ uint8_t tc_id; ++ uint16_t flow_id; ++ uint16_t dpbp_id; ++ uint8_t marking; ++}; ++ ++/** ++ * dpdbg_set_dpni_rx_trace() - Set trace for DPNI ingress (WRIOP ingress). ++ * in case of multiple requests for different DPNIs - the trace ++ * will be for the latest DPNI requested. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * @dpni_id: The requested DPNI ID ++ * @trace_cfg: Trace configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_set_dpni_rx_trace(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpni_id, ++ struct dpdbg_dpni_rx_trace_cfg *trace_cfg); ++ ++/** ++ * All DPNI senders ++ */ ++#define DPDBG_DPNI_ALL_SENDERS (uint16_t)(-1) ++ ++/** ++ * struct dpdbg_dpni_trace_cfg - Configure the behavior of a trace point when a ++ * frame marked with the specified DD code point is encountered ++ * @marking: The requested debug marking; ++ * 'DPDBG_DISABLE_MARKING' for disable marking ++ */ ++struct dpdbg_dpni_tx_trace_cfg { ++ uint8_t marking; ++}; ++ ++/** ++ * dpdbg_set_dpni_tx_trace() - Set trace for DPNI dequeued frames ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * @dpni_id: The requested DPNI ID ++ * @sender_id: Sender ID; 'DPDBG_DPNI_ALL_SENDERS' for all senders ++ * @trace_cfg: Trace configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_set_dpni_tx_trace(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpni_id, ++ uint16_t sender_id, ++ struct dpdbg_dpni_tx_trace_cfg *trace_cfg); ++ ++/** ++ * Number of DPCON trace points ++ */ ++#define DPDBG_NUM_OF_DPCON_TRACE_POINTS 2 ++ ++/** ++ * struct dpdbg_dpcon_trace_cfg - Configure the behavior of a trace point when a ++ * frame marked with the specified DD code point is encountered ++ * @marking: The requested debug marking; ++ * 'DPDBG_DISABLE_MARKING' for disable marking ++ * @verbosity: Verbosity level ++ */ ++struct dpdbg_dpcon_trace_cfg { ++ uint8_t marking; ++ enum dpdbg_verbosity_level verbosity; ++}; ++ ++/** ++ * dpdbg_set_dpcon_trace() - Set trace for DPCON when a frame marked with a ++ * specified marking is dequeued from a WQ in the ++ * channel selected ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * @dpcon_id: The requested DPCON ID ++ * @trace_point: Trace points configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_set_dpcon_trace(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpcon_id, ++ struct dpdbg_dpcon_trace_cfg ++ trace_point[DPDBG_NUM_OF_DPCON_TRACE_POINTS]); ++ ++/** ++ * Number of DPSECI trace points ++ */ ++#define DPDBG_NUM_OF_DPSECI_TRACE_POINTS 2 ++ ++/** ++ * struct dpdbg_dpseci_trace_cfg - Configure the behavior of a trace point when ++ * a frame marked with the specified DD code point is ++ * encountered ++ * @marking: The requested debug marking; ++ * 'DPDBG_DISABLE_MARKING' for disable marking ++ * @verbosity: Verbosity level ++ */ ++struct dpdbg_dpseci_trace_cfg { ++ uint8_t marking; ++ enum dpdbg_verbosity_level verbosity; ++}; ++ ++/** ++ * dpdbg_set_dpseci_trace() - Set trace for DPSECI when a frame marked with the ++ * specific marking is enqueued via this portal. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * @dpseci_id: The requested DPSECI ID ++ * @trace_point: Trace points configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_set_dpseci_trace(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpseci_id, ++ struct dpdbg_dpseci_trace_cfg ++ trace_point[DPDBG_NUM_OF_DPSECI_TRACE_POINTS]); ++ ++/** ++ * dpdbg_get_dpmac_counter() - DPMAC packet throughput ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * @dpmac_id: The requested DPMAC ID ++ * @counter_type: The requested DPMAC counter ++ * @counter: Returned counter value ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_get_dpmac_counter(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpmac_id, ++ enum dpmac_counter counter_type, ++ uint64_t *counter); ++ ++/** ++ * dpdbg_get_dpni_counter() - DPNI packet throughput ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDBG object ++ * @dpni_id: The requested DPNI ID ++ * @counter_type: The requested DPNI counter ++ * @counter: Returned counter value ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdbg_get_dpni_counter(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpni_id, ++ enum dpni_counter counter_type, ++ uint64_t *counter); ++ ++#endif /* __FSL_DPDBG_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpdbg_cmd.h b/drivers/net/dpaa2/mc/fsl_dpdbg_cmd.h +new file mode 100644 +index 0000000..b672788 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpdbg_cmd.h +@@ -0,0 +1,249 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_DPDBG_CMD_H ++#define _FSL_DPDBG_CMD_H ++ ++/* DPDBG Version */ ++#define DPDBG_VER_MAJOR 1 ++#define DPDBG_VER_MINOR 0 ++ ++/* Command IDs */ ++#define DPDBG_CMDID_CLOSE 0x800 ++#define DPDBG_CMDID_OPEN 0x80F ++ ++#define DPDBG_CMDID_GET_ATTR 0x004 ++ ++#define DPDBG_CMDID_GET_DPNI_INFO 0x130 ++#define DPDBG_CMDID_GET_DPNI_PRIV_TX_CONF_FQID 0x131 ++#define DPDBG_CMDID_GET_DPCON_INFO 0x132 ++#define DPDBG_CMDID_GET_DPBP_INFO 0x133 ++#define DPDBG_CMDID_GET_DPCI_FQID 0x134 ++ ++#define DPDBG_CMDID_SET_CTLU_GLOBAL_MARKING 0x135 ++#define DPDBG_CMDID_SET_DPNI_RX_MARKING 0x136 ++#define DPDBG_CMDID_SET_DPNI_TX_CONF_MARKING 0x137 ++#define DPDBG_CMDID_SET_DPIO_MARKING 0x138 ++ ++#define DPDBG_CMDID_SET_CTLU_GLOBAL_TRACE 0x140 ++#define DPDBG_CMDID_SET_DPIO_TRACE 0x141 ++#define DPDBG_CMDID_SET_DPNI_RX_TRACE 0x142 ++#define DPDBG_CMDID_SET_DPNI_TX_TRACE 0x143 ++#define DPDBG_CMDID_SET_DPCON_TRACE 0x145 ++#define DPDBG_CMDID_SET_DPSECI_TRACE 0x146 ++ ++#define DPDBG_CMDID_GET_DPMAC_COUNTER 0x150 ++#define DPDBG_CMDID_GET_DPNI_COUNTER 0x151 ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_CMD_OPEN(cmd, dpdbg_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpdbg_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_RSP_GET_ATTRIBUTES(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 32, 32, int, attr->id);\ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->version.major);\ ++ MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->version.minor);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_CMD_GET_DPNI_INFO(cmd, dpni_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpni_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_RSP_GET_DPNI_INFO(cmd, info) \ ++do { \ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, info->qdid);\ ++ MC_RSP_OP(cmd, 1, 32, 8, uint8_t, info->max_senders);\ ++ MC_RSP_OP(cmd, 2, 0, 32, uint32_t, info->err_fqid);\ ++ MC_RSP_OP(cmd, 2, 32, 32, uint32_t, info->tx_conf_fqid);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_CMD_GET_DPNI_PRIV_TX_CONF_FQID(cmd, dpni_id, sender_id) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpni_id);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, sender_id);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_RSP_GET_DPNI_PRIV_TX_CONF_FQID(cmd, fqid) \ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, fqid) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_CMD_GET_DPCON_INFO(cmd, dpcon_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpcon_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_RSP_GET_DPCON_INFO(cmd, info) \ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, info->ch_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_CMD_GET_DPBP_INFO(cmd, dpbp_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpbp_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_RSP_GET_DPBP_INFO(cmd, info) \ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, info->bpid) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_CMD_GET_DPCI_FQID(cmd, dpci_id, priority) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpci_id);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, priority);\ ++} while (0) ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_RSP_GET_DPCI_FQID(cmd, fqid) \ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, fqid) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_CMD_SET_CTLU_GLOBAL_MARKING(cmd, marking, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, marking);\ ++ MC_CMD_OP(cmd, 0, 8, 8, uint8_t, cfg->key_size); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->key_iova); \ ++ MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->mask_iova); \ ++ MC_CMD_OP(cmd, 3, 0, 64, uint64_t, cfg->rule_iova); \ ++} while (0) ++ ++#define DPDBG_CMD_SET_DPNI_RX_MARKING(cmd, dpni_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpni_id);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->tc_id);\ ++ MC_CMD_OP(cmd, 0, 48, 16, uint16_t, cfg->flow_id);\ ++ MC_CMD_OP(cmd, 1, 0, 16, uint16_t, cfg->dpbp_id);\ ++ MC_CMD_OP(cmd, 1, 16, 8, uint8_t, cfg->marking);\ ++} while (0) ++ ++#define DPDBG_CMD_SET_DPNI_TX_CONF_MARKING(cmd, dpni_id, sender_id, marking) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpni_id);\ ++ MC_CMD_OP(cmd, 0, 48, 16, uint16_t, sender_id);\ ++ MC_CMD_OP(cmd, 1, 16, 8, uint8_t, marking);\ ++} while (0) ++ ++#define DPDBG_CMD_SET_DPIO_MARKING(cmd, dpio_id, marking) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpio_id);\ ++ MC_CMD_OP(cmd, 1, 16, 8, uint8_t, marking);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_CMD_SET_CTLU_GLOBAL_TRACE(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 8, 8, uint8_t, cfg->key_size); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->key_iova); \ ++ MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->mask_iova); \ ++ MC_CMD_OP(cmd, 3, 0, 64, uint64_t, cfg->rule_iova); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_CMD_SET_DPIO_TRACE(cmd, dpio_id, trace_point) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpio_id);\ ++ MC_CMD_OP(cmd, 1, 0, 4, enum dpdbg_verbosity_level, \ ++ trace_point[0].verbosity); \ ++ MC_CMD_OP(cmd, 1, 4, 4, enum dpdbg_dpio_trace_type, \ ++ trace_point[0].enqueue_type); \ ++ MC_CMD_OP(cmd, 1, 8, 8, uint8_t, trace_point[0].marking); \ ++ MC_CMD_OP(cmd, 1, 32, 4, enum dpdbg_verbosity_level, \ ++ trace_point[1].verbosity); \ ++ MC_CMD_OP(cmd, 1, 36, 4, enum dpdbg_dpio_trace_type, \ ++ trace_point[1].enqueue_type); \ ++ MC_CMD_OP(cmd, 1, 40, 8, uint8_t, trace_point[1].marking); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_CMD_SET_DPNI_RX_TRACE(cmd, dpni_id, trace_cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpni_id);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, trace_cfg->tc_id);\ ++ MC_CMD_OP(cmd, 0, 48, 16, uint16_t, trace_cfg->flow_id);\ ++ MC_CMD_OP(cmd, 1, 0, 16, uint16_t, trace_cfg->dpbp_id);\ ++ MC_CMD_OP(cmd, 1, 16, 8, uint8_t, trace_cfg->marking);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_CMD_SET_DPNI_TX_TRACE(cmd, dpni_id, sender_id, trace_cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpni_id);\ ++ MC_CMD_OP(cmd, 0, 48, 16, uint16_t, sender_id);\ ++ MC_CMD_OP(cmd, 1, 16, 8, uint8_t, trace_cfg->marking);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_CMD_SET_DPCON_TRACE(cmd, dpcon_id, trace_point) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpcon_id);\ ++ MC_CMD_OP(cmd, 1, 0, 4, enum dpdbg_verbosity_level, \ ++ trace_point[0].verbosity); \ ++ MC_CMD_OP(cmd, 1, 8, 8, uint8_t, trace_point[0].marking); \ ++ MC_CMD_OP(cmd, 1, 32, 4, enum dpdbg_verbosity_level, \ ++ trace_point[1].verbosity); \ ++ MC_CMD_OP(cmd, 1, 40, 8, uint8_t, trace_point[1].marking); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_CMD_SET_DPSECI_TRACE(cmd, dpseci_id, trace_point) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpseci_id);\ ++ MC_CMD_OP(cmd, 1, 0, 4, enum dpdbg_verbosity_level, \ ++ trace_point[0].verbosity); \ ++ MC_CMD_OP(cmd, 1, 8, 8, uint8_t, trace_point[0].marking); \ ++ MC_CMD_OP(cmd, 1, 32, 4, enum dpdbg_verbosity_level, \ ++ trace_point[1].verbosity); \ ++ MC_CMD_OP(cmd, 1, 40, 8, uint8_t, trace_point[1].marking); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_CMD_GET_DPMAC_COUNTER(cmd, dpmac_id, counter_type) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpmac_id);\ ++ MC_CMD_OP(cmd, 0, 32, 16, enum dpmac_counter, counter_type);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_RSP_GET_DPMAC_COUNTER(cmd, counter) \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, counter) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_CMD_GET_DPNI_COUNTER(cmd, dpni_id, counter_type) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpni_id);\ ++ MC_CMD_OP(cmd, 0, 32, 16, enum dpni_counter, counter_type);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDBG_RSP_GET_DPNI_COUNTER(cmd, counter) \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, counter) ++ ++#endif /* _FSL_DPDBG_CMD_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpdcei.h b/drivers/net/dpaa2/mc/fsl_dpdcei.h +new file mode 100644 +index 0000000..319795c +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpdcei.h +@@ -0,0 +1,515 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPDCEI_H ++#define __FSL_DPDCEI_H ++ ++/* Data Path DCE Interface API ++ * Contains initialization APIs and runtime control APIs for DPDCEI ++ */ ++ ++struct fsl_mc_io; ++ ++/** General DPDCEI macros */ ++ ++/** ++ * Indicates an invalid frame queue ++ */ ++#define DPDCEI_FQID_NOT_VALID (uint32_t)(-1) ++ ++/** ++ * enum dpdcei_engine - DCE engine block ++ * @DPDCEI_ENGINE_COMPRESSION: Engine compression ++ * @DPDCEI_ENGINE_DECOMPRESSION: Engine decompression ++ */ ++enum dpdcei_engine { ++ DPDCEI_ENGINE_COMPRESSION, ++ DPDCEI_ENGINE_DECOMPRESSION ++}; ++ ++/** ++ * dpdcei_open() - Open a control session for the specified object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDCEI object ++ * @dpdcei_id: DPDCEI unique ID ++ * ++ * This function can be used to open a control session for an ++ * already created object; an object may have been declared in ++ * the DPL or by calling the dpdcei_create() function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent commands for ++ * this specific object. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpdcei_id, ++ uint16_t *token); ++ ++/** ++ * dpdcei_close() - Close the control session of the object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDCEI object ++ * ++ * After this function is called, no further operations are ++ * allowed on the object without opening a new control session. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * struct dpdcei_cfg - Structure representing DPDCEI configuration ++ * @engine: compression or decompression engine to be selected ++ * @priority: Priority for the DCE hardware processing (valid values 1-8). ++ */ ++struct dpdcei_cfg { ++ enum dpdcei_engine engine; ++ uint8_t priority; ++}; ++ ++/** ++ * dpdcei_create() - Create the DPDCEI object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDCEI object ++ * @cfg: configuration parameters ++ * ++ * Create the DPDCEI object, allocate required resources and ++ * perform required initialization. ++ * ++ * The object can be created either by declaring it in the ++ * DPL file, or by calling this function. ++ * ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent calls to ++ * this specific object. For objects that are created using the ++ * DPL file, call dpdcei_open() function to get an authentication ++ * token first. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpdcei_cfg *cfg, ++ uint16_t *token); ++ ++/** ++ * dpdcei_destroy() - Destroy the DPDCEI object and release all its resources. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDCEI object ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpdcei_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpdcei_enable() - Enable the DPDCEI, allow sending and receiving frames. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDCEI object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpdcei_disable() - Disable the DPDCEI, stop sending and receiving frames. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDCEI object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpdcei_is_enabled() - Check if the DPDCEI is enabled. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDCEI object ++ * @en: Return '1' for object enabled/'0' otherwise ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en); ++ ++/** ++ * dpdcei_reset() - Reset the DPDCEI, returns the object to initial state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDCEI object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * struct dpdcei_irq_cfg - IRQ configuration ++ * @addr: Address that must be written to signal a message-based interrupt ++ * @val: Value to write into irq_addr address ++ * @irq_num: A user defined number associated with this IRQ ++ */ ++struct dpdcei_irq_cfg { ++ uint64_t addr; ++ uint32_t val; ++ int irq_num; ++}; ++ ++/** ++ * dpdcei_set_irq() - Set IRQ information for the DPDCEI to trigger an interrupt ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDCEI object ++ * @irq_index: Identifies the interrupt index to configure ++ * @irq_cfg: IRQ configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpdcei_irq_cfg *irq_cfg); ++ ++/** ++ * dpdcei_get_irq() - Get IRQ information from the DPDCEI ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDCEI object ++ * @irq_index: The interrupt index to configure ++ * @type: Interrupt type: 0 represents message interrupt ++ * type (both irq_addr and irq_val are valid) ++ * @irq_cfg: IRQ attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpdcei_irq_cfg *irq_cfg); ++ ++/** ++ * dpdcei_set_irq_enable() - Set overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @irq_index: The interrupt index to configure ++ * @en: Interrupt state - enable = 1, disable = 0 ++ * ++ * Allows GPP software to control when interrupts are generated. ++ * Each interrupt can have up to 32 causes. The enable/disable control's the ++ * overall interrupt state. if the interrupt is disabled no causes will cause ++ * an interrupt ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en); ++ ++/** ++ * dpdcei_get_irq_enable() - Get overall interrupt state ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDCEI object ++ * @irq_index: The interrupt index to configure ++ * @en: Returned Interrupt state - enable = 1, disable = 0 ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en); ++ ++/** ++ * dpdcei_set_irq_mask() - Set interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @irq_index: The interrupt index to configure ++ * @mask: event mask to trigger interrupt; ++ * each bit: ++ * 0 = ignore event ++ * 1 = consider event for asserting IRQ ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask); ++ ++/** ++ * dpdcei_get_irq_mask() - Get interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDCEI object ++ * @irq_index: The interrupt index to configure ++ * @mask: Returned event mask to trigger interrupt ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask); ++ ++/** ++ * dpdcei_get_irq_status() - Get the current status of any pending interrupts ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDCEI object ++ * @irq_index: The interrupt index to configure ++ * @status: Returned interrupts status - one bit per cause: ++ * 0 = no interrupt pending ++ * 1 = interrupt pending ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status); ++ ++/** ++ * dpdcei_clear_irq_status() - Clear a pending interrupt's status ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDCEI object ++ * @irq_index: The interrupt index to configure ++ * @status: bits to clear (W1C) - one bit per cause: ++ * 0 = don't change ++ * 1 = clear status bit ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status); ++/** ++ * struct dpdcei_attr - Structure representing DPDCEI attributes ++ * @id: DPDCEI object ID ++ * @engine: DCE engine block ++ * @version: DPDCEI version ++ */ ++struct dpdcei_attr { ++ int id; ++ enum dpdcei_engine engine; ++ /** ++ * struct version - DPDCEI version ++ * @major: DPDCEI major version ++ * @minor: DPDCEI minor version ++ */ ++ struct { ++ uint16_t major; ++ uint16_t minor; ++ } version; ++}; ++ ++/** ++ * dpdcei_get_attributes() - Retrieve DPDCEI attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDCEI object ++ * @attr: Returned object's attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpdcei_attr *attr); ++ ++/** ++ * enum dpdcei_dest - DPDCEI destination types ++ * @DPDCEI_DEST_NONE: Unassigned destination; The queue is set in parked mode ++ * and does not generate FQDAN notifications; ++ * user is expected to dequeue from the queue based on ++ * polling or other user-defined method ++ * @DPDCEI_DEST_DPIO: The queue is set in schedule mode and generates FQDAN ++ * notifications to the specified DPIO; user is expected to ++ * dequeue from the queue only after notification is ++ * received ++ * @DPDCEI_DEST_DPCON: The queue is set in schedule mode and does not generate ++ * FQDAN notifications, but is connected to the specified ++ * DPCON object; ++ * user is expected to dequeue from the DPCON channel ++ */ ++enum dpdcei_dest { ++ DPDCEI_DEST_NONE = 0, ++ DPDCEI_DEST_DPIO = 1, ++ DPDCEI_DEST_DPCON = 2 ++}; ++ ++/** ++ * struct dpdcei_dest_cfg - Structure representing DPDCEI destination parameters ++ * @dest_type: Destination type ++ * @dest_id: Either DPIO ID or DPCON ID, depending on the destination type ++ * @priority: Priority selection within the DPIO or DPCON channel; valid values ++ * are 0-1 or 0-7, depending on the number of priorities in that ++ * channel; not relevant for 'DPDCEI_DEST_NONE' option ++ */ ++struct dpdcei_dest_cfg { ++ enum dpdcei_dest dest_type; ++ int dest_id; ++ uint8_t priority; ++}; ++ ++/** DPDCEI queue modification options */ ++ ++/** ++ * Select to modify the user's context associated with the queue ++ */ ++#define DPDCEI_QUEUE_OPT_USER_CTX 0x00000001 ++ ++/** ++ * Select to modify the queue's destination ++ */ ++#define DPDCEI_QUEUE_OPT_DEST 0x00000002 ++ ++/** ++ * struct dpdcei_rx_queue_cfg - RX queue configuration ++ * @options: Flags representing the suggested modifications to the queue; ++ * Use any combination of 'DPDCEI_QUEUE_OPT_' flags ++ * @user_ctx: User context value provided in the frame descriptor of each ++ * dequeued frame; ++ * valid only if 'DPDCEI_QUEUE_OPT_USER_CTX' is contained in 'options' ++ * @dest_cfg: Queue destination parameters; ++ * valid only if 'DPDCEI_QUEUE_OPT_DEST' is contained in 'options' ++ */ ++struct dpdcei_rx_queue_cfg { ++ uint32_t options; ++ uint64_t user_ctx; ++ struct dpdcei_dest_cfg dest_cfg; ++}; ++ ++/** ++ * dpdcei_set_rx_queue() - Set Rx queue configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDCEI object ++ * @cfg: Rx queue configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_set_rx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpdcei_rx_queue_cfg *cfg); ++ ++/** ++ * struct dpdcei_rx_queue_attr - Structure representing attributes of Rx queues ++ * @user_ctx: User context value provided in the frame descriptor of each ++ * dequeued frame ++ * @dest_cfg: Queue destination configuration ++ * @fqid: Virtual FQID value to be used for dequeue operations ++ */ ++struct dpdcei_rx_queue_attr { ++ uint64_t user_ctx; ++ struct dpdcei_dest_cfg dest_cfg; ++ uint32_t fqid; ++}; ++ ++/** ++ * dpdcei_get_rx_queue() - Retrieve Rx queue attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDCEI object ++ * @attr: Returned Rx queue attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_get_rx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpdcei_rx_queue_attr *attr); ++ ++/** ++ * struct dpdcei_tx_queue_attr - Structure representing attributes of Tx queues ++ * @fqid: Virtual FQID to be used for sending frames to DCE hardware ++ */ ++struct dpdcei_tx_queue_attr { ++ uint32_t fqid; ++}; ++ ++/** ++ * dpdcei_get_tx_queue() - Retrieve Tx queue attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDCEI object ++ * @attr: Returned Tx queue attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdcei_get_tx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpdcei_tx_queue_attr *attr); ++ ++#endif /* __FSL_DPDCEI_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpdcei_cmd.h b/drivers/net/dpaa2/mc/fsl_dpdcei_cmd.h +new file mode 100644 +index 0000000..8452d88 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpdcei_cmd.h +@@ -0,0 +1,182 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_DPDCEI_CMD_H ++#define _FSL_DPDCEI_CMD_H ++ ++/* DPDCEI Version */ ++#define DPDCEI_VER_MAJOR 1 ++#define DPDCEI_VER_MINOR 2 ++ ++/* Command IDs */ ++#define DPDCEI_CMDID_CLOSE 0x800 ++#define DPDCEI_CMDID_OPEN 0x80D ++#define DPDCEI_CMDID_CREATE 0x90D ++#define DPDCEI_CMDID_DESTROY 0x900 ++ ++#define DPDCEI_CMDID_ENABLE 0x002 ++#define DPDCEI_CMDID_DISABLE 0x003 ++#define DPDCEI_CMDID_GET_ATTR 0x004 ++#define DPDCEI_CMDID_RESET 0x005 ++#define DPDCEI_CMDID_IS_ENABLED 0x006 ++ ++#define DPDCEI_CMDID_SET_IRQ 0x010 ++#define DPDCEI_CMDID_GET_IRQ 0x011 ++#define DPDCEI_CMDID_SET_IRQ_ENABLE 0x012 ++#define DPDCEI_CMDID_GET_IRQ_ENABLE 0x013 ++#define DPDCEI_CMDID_SET_IRQ_MASK 0x014 ++#define DPDCEI_CMDID_GET_IRQ_MASK 0x015 ++#define DPDCEI_CMDID_GET_IRQ_STATUS 0x016 ++#define DPDCEI_CMDID_CLEAR_IRQ_STATUS 0x017 ++ ++#define DPDCEI_CMDID_SET_RX_QUEUE 0x1B0 ++#define DPDCEI_CMDID_GET_RX_QUEUE 0x1B1 ++#define DPDCEI_CMDID_GET_TX_QUEUE 0x1B2 ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_CMD_OPEN(cmd, dpdcei_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpdcei_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_CMD_CREATE(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 8, 8, enum dpdcei_engine, cfg->engine);\ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, cfg->priority);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_RSP_IS_ENABLED(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, irq_index);\ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, irq_cfg->val);\ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\ ++ MC_CMD_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_CMD_GET_IRQ(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_RSP_GET_IRQ(cmd, type, irq_cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\ ++ MC_RSP_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, type); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_CMD_SET_IRQ_ENABLE(cmd, irq_index, enable_state) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, enable_state); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_CMD_GET_IRQ_ENABLE(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_RSP_GET_IRQ_ENABLE(cmd, enable_state) \ ++ MC_RSP_OP(cmd, 0, 0, 8, uint8_t, enable_state) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, mask); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_CMD_GET_IRQ_MASK(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_RSP_GET_IRQ_MASK(cmd, mask) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mask) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_RSP_GET_IRQ_STATUS(cmd, status) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, status) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_RSP_GET_ATTR(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, attr->id); \ ++ MC_RSP_OP(cmd, 0, 32, 8, enum dpdcei_engine, attr->engine); \ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->version.major);\ ++ MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->version.minor);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_CMD_SET_RX_QUEUE(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, cfg->dest_cfg.dest_id); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->dest_cfg.priority); \ ++ MC_CMD_OP(cmd, 0, 48, 4, enum dpdcei_dest, cfg->dest_cfg.dest_type); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->user_ctx); \ ++ MC_CMD_OP(cmd, 2, 0, 32, uint32_t, cfg->options);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_RSP_GET_RX_QUEUE(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, attr->dest_cfg.dest_id);\ ++ MC_RSP_OP(cmd, 0, 32, 8, uint8_t, attr->dest_cfg.priority);\ ++ MC_RSP_OP(cmd, 0, 48, 4, enum dpdcei_dest, attr->dest_cfg.dest_type);\ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, attr->user_ctx);\ ++ MC_RSP_OP(cmd, 2, 0, 32, uint32_t, attr->fqid);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDCEI_RSP_GET_TX_QUEUE(cmd, attr) \ ++ MC_RSP_OP(cmd, 0, 32, 32, uint32_t, attr->fqid) ++ ++#endif /* _FSL_DPDCEI_CMD_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpdmai.h b/drivers/net/dpaa2/mc/fsl_dpdmai.h +new file mode 100644 +index 0000000..e931ce1 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpdmai.h +@@ -0,0 +1,521 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPDMAI_H ++#define __FSL_DPDMAI_H ++ ++struct fsl_mc_io; ++ ++/* Data Path DMA Interface API ++ * Contains initialization APIs and runtime control APIs for DPDMAI ++ */ ++ ++/* General DPDMAI macros */ ++ ++/** ++ * Maximum number of Tx/Rx priorities per DPDMAI object ++ */ ++#define DPDMAI_PRIO_NUM 2 ++ ++/** ++ * All queues considered; see dpdmai_set_rx_queue() ++ */ ++#define DPDMAI_ALL_QUEUES (uint8_t)(-1) ++ ++/** ++ * dpdmai_open() - Open a control session for the specified object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @dpdmai_id: DPDMAI unique ID ++ * @token: Returned token; use in subsequent API calls ++ * ++ * This function can be used to open a control session for an ++ * already created object; an object may have been declared in ++ * the DPL or by calling the dpdmai_create() function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent commands for ++ * this specific object. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpdmai_id, ++ uint16_t *token); ++ ++/** ++ * dpdmai_close() - Close the control session of the object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMAI object ++ * ++ * After this function is called, no further operations are ++ * allowed on the object without opening a new control session. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * struct dpdmai_cfg - Structure representing DPDMAI configuration ++ * @priorities: Priorities for the DMA hardware processing; valid priorities are ++ * configured with values 1-8; the entry following last valid entry ++ * should be configured with 0 ++ */ ++struct dpdmai_cfg { ++ uint8_t priorities[DPDMAI_PRIO_NUM]; ++}; ++ ++/** ++ * dpdmai_create() - Create the DPDMAI object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @cfg: Configuration structure ++ * @token: Returned token; use in subsequent API calls ++ * ++ * Create the DPDMAI object, allocate required resources and ++ * perform required initialization. ++ * ++ * The object can be created either by declaring it in the ++ * DPL file, or by calling this function. ++ * ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent calls to ++ * this specific object. For objects that are created using the ++ * DPL file, call dpdmai_open() function to get an authentication ++ * token first. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpdmai_cfg *cfg, ++ uint16_t *token); ++ ++/** ++ * dpdmai_destroy() - Destroy the DPDMAI object and release all its resources. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMAI object ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpdmai_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpdmai_enable() - Enable the DPDMAI, allow sending and receiving frames. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMAI object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpdmai_disable() - Disable the DPDMAI, stop sending and receiving frames. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMAI object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpdmai_is_enabled() - Check if the DPDMAI is enabled. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMAI object ++ * @en: Returns '1' if object is enabled; '0' otherwise ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en); ++ ++/** ++ * dpdmai_reset() - Reset the DPDMAI, returns the object to initial state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMAI object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * struct dpdmai_irq_cfg - IRQ configuration ++ * @addr: Address that must be written to signal a message-based interrupt ++ * @val: Value to write into irq_addr address ++ * @irq_num: A user defined number associated with this IRQ ++ */ ++struct dpdmai_irq_cfg { ++ uint64_t addr; ++ uint32_t val; ++ int irq_num; ++}; ++ ++/** ++ * dpdmai_set_irq() - Set IRQ information for the DPDMAI to trigger an interrupt. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMAI object ++ * @irq_index: Identifies the interrupt index to configure ++ * @irq_cfg: IRQ configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpdmai_irq_cfg *irq_cfg); ++ ++/** ++ * dpdmai_get_irq() - Get IRQ information from the DPDMAI ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMAI object ++ * @irq_index: The interrupt index to configure ++ * @type: Interrupt type: 0 represents message interrupt ++ * type (both irq_addr and irq_val are valid) ++ * @irq_cfg: IRQ attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpdmai_irq_cfg *irq_cfg); ++ ++/** ++ * dpdmai_set_irq_enable() - Set overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMAI object ++ * @irq_index: The interrupt index to configure ++ * @en: Interrupt state - enable = 1, disable = 0 ++ * ++ * Allows GPP software to control when interrupts are generated. ++ * Each interrupt can have up to 32 causes. The enable/disable control's the ++ * overall interrupt state. if the interrupt is disabled no causes will cause ++ * an interrupt ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en); ++ ++/** ++ * dpdmai_get_irq_enable() - Get overall interrupt state ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMAI object ++ * @irq_index: The interrupt index to configure ++ * @en: Returned Interrupt state - enable = 1, disable = 0 ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en); ++ ++/** ++ * dpdmai_set_irq_mask() - Set interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMAI object ++ * @irq_index: The interrupt index to configure ++ * @mask: event mask to trigger interrupt; ++ * each bit: ++ * 0 = ignore event ++ * 1 = consider event for asserting IRQ ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask); ++ ++/** ++ * dpdmai_get_irq_mask() - Get interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMAI object ++ * @irq_index: The interrupt index to configure ++ * @mask: Returned event mask to trigger interrupt ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask); ++ ++/** ++ * dpdmai_get_irq_status() - Get the current status of any pending interrupts ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMAI object ++ * @irq_index: The interrupt index to configure ++ * @status: Returned interrupts status - one bit per cause: ++ * 0 = no interrupt pending ++ * 1 = interrupt pending ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status); ++ ++/** ++ * dpdmai_clear_irq_status() - Clear a pending interrupt's status ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMAI object ++ * @irq_index: The interrupt index to configure ++ * @status: bits to clear (W1C) - one bit per cause: ++ * 0 = don't change ++ * 1 = clear status bit ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status); ++ ++/** ++ * struct dpdmai_attr - Structure representing DPDMAI attributes ++ * @id: DPDMAI object ID ++ * @version: DPDMAI version ++ * @num_of_priorities: number of priorities ++ */ ++struct dpdmai_attr { ++ int id; ++ /** ++ * struct version - DPDMAI version ++ * @major: DPDMAI major version ++ * @minor: DPDMAI minor version ++ */ ++ struct { ++ uint16_t major; ++ uint16_t minor; ++ } version; ++ uint8_t num_of_priorities; ++}; ++ ++/** ++ * dpdmai_get_attributes() - Retrieve DPDMAI attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMAI object ++ * @attr: Returned object's attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpdmai_attr *attr); ++ ++/** ++ * enum dpdmai_dest - DPDMAI destination types ++ * @DPDMAI_DEST_NONE: Unassigned destination; The queue is set in parked mode ++ * and does not generate FQDAN notifications; user is expected to dequeue ++ * from the queue based on polling or other user-defined method ++ * @DPDMAI_DEST_DPIO: The queue is set in schedule mode and generates FQDAN ++ * notifications to the specified DPIO; user is expected to dequeue ++ * from the queue only after notification is received ++ * @DPDMAI_DEST_DPCON: The queue is set in schedule mode and does not generate ++ * FQDAN notifications, but is connected to the specified DPCON object; ++ * user is expected to dequeue from the DPCON channel ++ */ ++enum dpdmai_dest { ++ DPDMAI_DEST_NONE = 0, ++ DPDMAI_DEST_DPIO = 1, ++ DPDMAI_DEST_DPCON = 2 ++}; ++ ++/** ++ * struct dpdmai_dest_cfg - Structure representing DPDMAI destination parameters ++ * @dest_type: Destination type ++ * @dest_id: Either DPIO ID or DPCON ID, depending on the destination type ++ * @priority: Priority selection within the DPIO or DPCON channel; valid values ++ * are 0-1 or 0-7, depending on the number of priorities in that ++ * channel; not relevant for 'DPDMAI_DEST_NONE' option ++ */ ++struct dpdmai_dest_cfg { ++ enum dpdmai_dest dest_type; ++ int dest_id; ++ uint8_t priority; ++}; ++ ++/* DPDMAI queue modification options */ ++ ++/** ++ * Select to modify the user's context associated with the queue ++ */ ++#define DPDMAI_QUEUE_OPT_USER_CTX 0x00000001 ++ ++/** ++ * Select to modify the queue's destination ++ */ ++#define DPDMAI_QUEUE_OPT_DEST 0x00000002 ++ ++/** ++ * struct dpdmai_rx_queue_cfg - DPDMAI RX queue configuration ++ * @options: Flags representing the suggested modifications to the queue; ++ * Use any combination of 'DPDMAI_QUEUE_OPT_' flags ++ * @user_ctx: User context value provided in the frame descriptor of each ++ * dequeued frame; ++ * valid only if 'DPDMAI_QUEUE_OPT_USER_CTX' is contained in 'options' ++ * @dest_cfg: Queue destination parameters; ++ * valid only if 'DPDMAI_QUEUE_OPT_DEST' is contained in 'options' ++ */ ++struct dpdmai_rx_queue_cfg { ++ uint32_t options; ++ uint64_t user_ctx; ++ struct dpdmai_dest_cfg dest_cfg; ++ ++}; ++ ++/** ++ * dpdmai_set_rx_queue() - Set Rx queue configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMAI object ++ * @priority: Select the queue relative to number of ++ * priorities configured at DPDMAI creation; use ++ * DPDMAI_ALL_QUEUES to configure all Rx queues ++ * identically. ++ * @cfg: Rx queue configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_set_rx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t priority, ++ const struct dpdmai_rx_queue_cfg *cfg); ++ ++/** ++ * struct dpdmai_rx_queue_attr - Structure representing attributes of Rx queues ++ * @user_ctx: User context value provided in the frame descriptor of each ++ * dequeued frame ++ * @dest_cfg: Queue destination configuration ++ * @fqid: Virtual FQID value to be used for dequeue operations ++ */ ++struct dpdmai_rx_queue_attr { ++ uint64_t user_ctx; ++ struct dpdmai_dest_cfg dest_cfg; ++ uint32_t fqid; ++}; ++ ++/** ++ * dpdmai_get_rx_queue() - Retrieve Rx queue attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMAI object ++ * @priority: Select the queue relative to number of ++ * priorities configured at DPDMAI creation ++ * @attr: Returned Rx queue attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_get_rx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t priority, ++ struct dpdmai_rx_queue_attr *attr); ++ ++/** ++ * struct dpdmai_tx_queue_attr - Structure representing attributes of Tx queues ++ * @fqid: Virtual FQID to be used for sending frames to DMA hardware ++ */ ++ ++struct dpdmai_tx_queue_attr { ++ uint32_t fqid; ++}; ++ ++/** ++ * dpdmai_get_tx_queue() - Retrieve Tx queue attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMAI object ++ * @priority: Select the queue relative to number of ++ * priorities configured at DPDMAI creation ++ * @attr: Returned Tx queue attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmai_get_tx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t priority, ++ struct dpdmai_tx_queue_attr *attr); ++ ++#endif /* __FSL_DPDMAI_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpdmai_cmd.h b/drivers/net/dpaa2/mc/fsl_dpdmai_cmd.h +new file mode 100644 +index 0000000..7c4a31a +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpdmai_cmd.h +@@ -0,0 +1,191 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_DPDMAI_CMD_H ++#define _FSL_DPDMAI_CMD_H ++ ++/* DPDMAI Version */ ++#define DPDMAI_VER_MAJOR 2 ++#define DPDMAI_VER_MINOR 2 ++ ++/* Command IDs */ ++#define DPDMAI_CMDID_CLOSE 0x800 ++#define DPDMAI_CMDID_OPEN 0x80E ++#define DPDMAI_CMDID_CREATE 0x90E ++#define DPDMAI_CMDID_DESTROY 0x900 ++ ++#define DPDMAI_CMDID_ENABLE 0x002 ++#define DPDMAI_CMDID_DISABLE 0x003 ++#define DPDMAI_CMDID_GET_ATTR 0x004 ++#define DPDMAI_CMDID_RESET 0x005 ++#define DPDMAI_CMDID_IS_ENABLED 0x006 ++ ++#define DPDMAI_CMDID_SET_IRQ 0x010 ++#define DPDMAI_CMDID_GET_IRQ 0x011 ++#define DPDMAI_CMDID_SET_IRQ_ENABLE 0x012 ++#define DPDMAI_CMDID_GET_IRQ_ENABLE 0x013 ++#define DPDMAI_CMDID_SET_IRQ_MASK 0x014 ++#define DPDMAI_CMDID_GET_IRQ_MASK 0x015 ++#define DPDMAI_CMDID_GET_IRQ_STATUS 0x016 ++#define DPDMAI_CMDID_CLEAR_IRQ_STATUS 0x017 ++ ++#define DPDMAI_CMDID_SET_RX_QUEUE 0x1A0 ++#define DPDMAI_CMDID_GET_RX_QUEUE 0x1A1 ++#define DPDMAI_CMDID_GET_TX_QUEUE 0x1A2 ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_CMD_OPEN(cmd, dpdmai_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpdmai_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_CMD_CREATE(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 8, 8, uint8_t, cfg->priorities[0]);\ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, cfg->priorities[1]);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_RSP_IS_ENABLED(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, irq_index);\ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, irq_cfg->val);\ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\ ++ MC_CMD_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_CMD_GET_IRQ(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_RSP_GET_IRQ(cmd, type, irq_cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\ ++ MC_RSP_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, type); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_CMD_SET_IRQ_ENABLE(cmd, irq_index, enable_state) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, enable_state); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_CMD_GET_IRQ_ENABLE(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_RSP_GET_IRQ_ENABLE(cmd, enable_state) \ ++ MC_RSP_OP(cmd, 0, 0, 8, uint8_t, enable_state) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, mask); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_CMD_GET_IRQ_MASK(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_RSP_GET_IRQ_MASK(cmd, mask) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mask) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_RSP_GET_IRQ_STATUS(cmd, status) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, status) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_RSP_GET_ATTR(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, attr->id); \ ++ MC_RSP_OP(cmd, 0, 32, 8, uint8_t, attr->num_of_priorities); \ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->version.major);\ ++ MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->version.minor);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_CMD_SET_RX_QUEUE(cmd, priority, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, cfg->dest_cfg.dest_id); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->dest_cfg.priority); \ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, priority); \ ++ MC_CMD_OP(cmd, 0, 48, 4, enum dpdmai_dest, cfg->dest_cfg.dest_type); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->user_ctx); \ ++ MC_CMD_OP(cmd, 2, 0, 32, uint32_t, cfg->options);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_CMD_GET_RX_QUEUE(cmd, priority) \ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, priority) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_RSP_GET_RX_QUEUE(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, attr->dest_cfg.dest_id);\ ++ MC_RSP_OP(cmd, 0, 32, 8, uint8_t, attr->dest_cfg.priority);\ ++ MC_RSP_OP(cmd, 0, 48, 4, enum dpdmai_dest, attr->dest_cfg.dest_type);\ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, attr->user_ctx);\ ++ MC_RSP_OP(cmd, 2, 0, 32, uint32_t, attr->fqid);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_CMD_GET_TX_QUEUE(cmd, priority) \ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, priority) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMAI_RSP_GET_TX_QUEUE(cmd, attr) \ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, attr->fqid) ++ ++#endif /* _FSL_DPDMAI_CMD_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpdmux.h b/drivers/net/dpaa2/mc/fsl_dpdmux.h +new file mode 100644 +index 0000000..455a042 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpdmux.h +@@ -0,0 +1,724 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPDMUX_H ++#define __FSL_DPDMUX_H ++ ++#include ++ ++struct fsl_mc_io; ++ ++/* Data Path Demux API ++ * Contains API for handling DPDMUX topology and functionality ++ */ ++ ++/** ++ * dpdmux_open() - Open a control session for the specified object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @dpdmux_id: DPDMUX unique ID ++ * @token: Returned token; use in subsequent API calls ++ * ++ * This function can be used to open a control session for an ++ * already created object; an object may have been declared in ++ * the DPL or by calling the dpdmux_create() function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent commands for ++ * this specific object. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpdmux_id, ++ uint16_t *token); ++ ++/** ++ * dpdmux_close() - Close the control session of the object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * ++ * After this function is called, no further operations are ++ * allowed on the object without opening a new control session. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * DPDMUX general options ++ */ ++ ++/** ++ * Enable bridging between internal interfaces ++ */ ++#define DPDMUX_OPT_BRIDGE_EN 0x0000000000000002ULL ++ ++#define DPDMUX_IRQ_INDEX_IF 0x0000 ++#define DPDMUX_IRQ_INDEX 0x0001 ++ ++/** ++ * IRQ event - Indicates that the link state changed ++ */ ++#define DPDMUX_IRQ_EVENT_LINK_CHANGED 0x0001 ++ ++/** ++ * enum dpdmux_manip - DPDMUX manipulation operations ++ * @DPDMUX_MANIP_NONE: No manipulation on frames ++ * @DPDMUX_MANIP_ADD_REMOVE_S_VLAN: Add S-VLAN on egress, remove it on ingress ++ */ ++enum dpdmux_manip { ++ DPDMUX_MANIP_NONE = 0x0, ++ DPDMUX_MANIP_ADD_REMOVE_S_VLAN = 0x1 ++}; ++ ++/** ++ * enum dpdmux_method - DPDMUX method options ++ * @DPDMUX_METHOD_NONE: no DPDMUX method ++ * @DPDMUX_METHOD_C_VLAN_MAC: DPDMUX based on C-VLAN and MAC address ++ * @DPDMUX_METHOD_MAC: DPDMUX based on MAC address ++ * @DPDMUX_METHOD_C_VLAN: DPDMUX based on C-VLAN ++ * @DPDMUX_METHOD_S_VLAN: DPDMUX based on S-VLAN ++ */ ++enum dpdmux_method { ++ DPDMUX_METHOD_NONE = 0x0, ++ DPDMUX_METHOD_C_VLAN_MAC = 0x1, ++ DPDMUX_METHOD_MAC = 0x2, ++ DPDMUX_METHOD_C_VLAN = 0x3, ++ DPDMUX_METHOD_S_VLAN = 0x4 ++}; ++ ++/** ++ * struct dpdmux_cfg - DPDMUX configuration parameters ++ * @method: Defines the operation method for the DPDMUX address table ++ * @manip: Required manipulation operation ++ * @num_ifs: Number of interfaces (excluding the uplink interface) ++ * @adv: Advanced parameters; default is all zeros; ++ * use this structure to change default settings ++ */ ++struct dpdmux_cfg { ++ enum dpdmux_method method; ++ enum dpdmux_manip manip; ++ uint16_t num_ifs; ++ /** ++ * struct adv - Advanced parameters ++ * @options: DPDMUX options - combination of 'DPDMUX_OPT_' flags ++ * @max_dmat_entries: Maximum entries in DPDMUX address table ++ * 0 - indicates default: 64 entries per interface. ++ * @max_mc_groups: Number of multicast groups in DPDMUX table ++ * 0 - indicates default: 32 multicast groups ++ * @max_vlan_ids: max vlan ids allowed in the system - ++ * relevant only case of working in mac+vlan method. ++ * 0 - indicates default 16 vlan ids. ++ */ ++ struct { ++ uint64_t options; ++ uint16_t max_dmat_entries; ++ uint16_t max_mc_groups; ++ uint16_t max_vlan_ids; ++ } adv; ++}; ++ ++/** ++ * dpdmux_create() - Create the DPDMUX object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @cfg: Configuration structure ++ * @token: Returned token; use in subsequent API calls ++ * ++ * Create the DPDMUX object, allocate required resources and ++ * perform required initialization. ++ * ++ * The object can be created either by declaring it in the ++ * DPL file, or by calling this function. ++ * ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent calls to ++ * this specific object. For objects that are created using the ++ * DPL file, call dpdmux_open() function to get an authentication ++ * token first. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpdmux_cfg *cfg, ++ uint16_t *token); ++ ++/** ++ * dpdmux_destroy() - Destroy the DPDMUX object and release all its resources. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpdmux_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpdmux_enable() - Enable DPDMUX functionality ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpdmux_disable() - Disable DPDMUX functionality ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpdmux_is_enabled() - Check if the DPDMUX is enabled. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * @en: Returns '1' if object is enabled; '0' otherwise ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en); ++ ++/** ++ * dpdmux_reset() - Reset the DPDMUX, returns the object to initial state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * struct dpdmux_irq_cfg - IRQ configuration ++ * @addr: Address that must be written to signal a message-based interrupt ++ * @val: Value to write into irq_addr address ++ * @irq_num: A user defined number associated with this IRQ ++ */ ++struct dpdmux_irq_cfg { ++ uint64_t addr; ++ uint32_t val; ++ int irq_num; ++}; ++ ++/** ++ * dpdmux_set_irq() - Set IRQ information for the DPDMUX to trigger an interrupt. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * @irq_index: Identifies the interrupt index to configure ++ * @irq_cfg: IRQ configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpdmux_irq_cfg *irq_cfg); ++ ++/** ++ * dpdmux_get_irq() - Get IRQ information from the DPDMUX. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * @irq_index: The interrupt index to configure ++ * @type: Interrupt type: 0 represents message interrupt ++ * type (both irq_addr and irq_val are valid) ++ * @irq_cfg: IRQ attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpdmux_irq_cfg *irq_cfg); ++ ++/** ++ * dpdmux_set_irq_enable() - Set overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * @irq_index: The interrupt index to configure ++ * @en: Interrupt state - enable = 1, disable = 0 ++ * ++ * Allows GPP software to control when interrupts are generated. ++ * Each interrupt can have up to 32 causes. The enable/disable control's the ++ * overall interrupt state. if the interrupt is disabled no causes will cause ++ * an interrupt. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en); ++ ++/** ++ * dpdmux_get_irq_enable() - Get overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * @irq_index: The interrupt index to configure ++ * @en: Returned interrupt state - enable = 1, disable = 0 ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en); ++ ++/** ++ * dpdmux_set_irq_mask() - Set interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * @irq_index: The interrupt index to configure ++ * @mask: event mask to trigger interrupt; ++ * each bit: ++ * 0 = ignore event ++ * 1 = consider event for asserting IRQ ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask); ++ ++/** ++ * dpdmux_get_irq_mask() - Get interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * @irq_index: The interrupt index to configure ++ * @mask: Returned event mask to trigger interrupt ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask); ++ ++/** ++ * dpdmux_get_irq_status() - Get the current status of any pending interrupts. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * @irq_index: The interrupt index to configure ++ * @status: Returned interrupts status - one bit per cause: ++ * 0 = no interrupt pending ++ * 1 = interrupt pending ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status); ++ ++/** ++ * dpdmux_clear_irq_status() - Clear a pending interrupt's status ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * @irq_index: The interrupt index to configure ++ * @status: bits to clear (W1C) - one bit per cause: ++ * 0 = don't change ++ * 1 = clear status bit ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status); ++ ++/** ++ * struct dpdmux_attr - Structure representing DPDMUX attributes ++ * @id: DPDMUX object ID ++ * @version: DPDMUX version ++ * @options: Configuration options (bitmap) ++ * @method: DPDMUX address table method ++ * @manip: DPDMUX manipulation type ++ * @num_ifs: Number of interfaces (excluding the uplink interface) ++ * @mem_size: DPDMUX frame storage memory size ++ */ ++struct dpdmux_attr { ++ int id; ++ /** ++ * struct version - DPDMUX version ++ * @major: DPDMUX major version ++ * @minor: DPDMUX minor version ++ */ ++ struct { ++ uint16_t major; ++ uint16_t minor; ++ } version; ++ uint64_t options; ++ enum dpdmux_method method; ++ enum dpdmux_manip manip; ++ uint16_t num_ifs; ++ uint16_t mem_size; ++}; ++ ++/** ++ * dpdmux_get_attributes() - Retrieve DPDMUX attributes ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * @attr: Returned object's attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpdmux_attr *attr); ++ ++/** ++ * dpdmux_ul_set_max_frame_length() - Set the maximum frame length in DPDMUX ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * @max_frame_length: The required maximum frame length ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_ul_set_max_frame_length(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t max_frame_length); ++ ++/** ++ * enum dpdmux_counter_type - Counter types ++ * @DPDMUX_CNT_ING_FRAME: Counts ingress frames ++ * @DPDMUX_CNT_ING_BYTE: Counts ingress bytes ++ * @DPDMUX_CNT_ING_FLTR_FRAME: Counts filtered ingress frames ++ * @DPDMUX_CNT_ING_FRAME_DISCARD: Counts discarded ingress frames ++ * @DPDMUX_CNT_ING_MCAST_FRAME: Counts ingress multicast frames ++ * @DPDMUX_CNT_ING_MCAST_BYTE: Counts ingress multicast bytes ++ * @DPDMUX_CNT_ING_BCAST_FRAME: Counts ingress broadcast frames ++ * @DPDMUX_CNT_ING_BCAST_BYTES: Counts ingress broadcast bytes ++ * @DPDMUX_CNT_EGR_FRAME: Counts egress frames ++ * @DPDMUX_CNT_EGR_BYTE: Counts egress bytes ++ * @DPDMUX_CNT_EGR_FRAME_DISCARD: Counts discarded egress frames ++ */ ++enum dpdmux_counter_type { ++ DPDMUX_CNT_ING_FRAME = 0x0, ++ DPDMUX_CNT_ING_BYTE = 0x1, ++ DPDMUX_CNT_ING_FLTR_FRAME = 0x2, ++ DPDMUX_CNT_ING_FRAME_DISCARD = 0x3, ++ DPDMUX_CNT_ING_MCAST_FRAME = 0x4, ++ DPDMUX_CNT_ING_MCAST_BYTE = 0x5, ++ DPDMUX_CNT_ING_BCAST_FRAME = 0x6, ++ DPDMUX_CNT_ING_BCAST_BYTES = 0x7, ++ DPDMUX_CNT_EGR_FRAME = 0x8, ++ DPDMUX_CNT_EGR_BYTE = 0x9, ++ DPDMUX_CNT_EGR_FRAME_DISCARD = 0xa ++}; ++ ++/** ++ * enum dpdmux_accepted_frames_type - DPDMUX frame types ++ * @DPDMUX_ADMIT_ALL: The device accepts VLAN tagged, untagged and ++ * priority-tagged frames ++ * @DPDMUX_ADMIT_ONLY_VLAN_TAGGED: The device discards untagged frames or ++ * priority-tagged frames that are received on this ++ * interface ++ * @DPDMUX_ADMIT_ONLY_UNTAGGED: Untagged frames or priority-tagged frames ++ * received on this interface are accepted ++ */ ++enum dpdmux_accepted_frames_type { ++ DPDMUX_ADMIT_ALL = 0, ++ DPDMUX_ADMIT_ONLY_VLAN_TAGGED = 1, ++ DPDMUX_ADMIT_ONLY_UNTAGGED = 2 ++}; ++ ++/** ++ * enum dpdmux_action - DPDMUX action for un-accepted frames ++ * @DPDMUX_ACTION_DROP: Drop un-accepted frames ++ * @DPDMUX_ACTION_REDIRECT_TO_CTRL: Redirect un-accepted frames to the ++ * control interface ++ */ ++enum dpdmux_action { ++ DPDMUX_ACTION_DROP = 0, ++ DPDMUX_ACTION_REDIRECT_TO_CTRL = 1 ++}; ++ ++/** ++ * struct dpdmux_accepted_frames - Frame types configuration ++ * @type: Defines ingress accepted frames ++ * @unaccept_act: Defines action on frames not accepted ++ */ ++struct dpdmux_accepted_frames { ++ enum dpdmux_accepted_frames_type type; ++ enum dpdmux_action unaccept_act; ++}; ++ ++/** ++ * dpdmux_if_set_accepted_frames() - Set the accepted frame types ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * @if_id: Interface ID (0 for uplink, or 1-num_ifs); ++ * @cfg: Frame types configuration ++ * ++ * if 'DPDMUX_ADMIT_ONLY_VLAN_TAGGED' is set - untagged frames or ++ * priority-tagged frames are discarded. ++ * if 'DPDMUX_ADMIT_ONLY_UNTAGGED' is set - untagged frames or ++ * priority-tagged frames are accepted. ++ * if 'DPDMUX_ADMIT_ALL' is set (default mode) - all VLAN tagged, ++ * untagged and priority-tagged frame are accepted; ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_if_set_accepted_frames(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpdmux_accepted_frames *cfg); ++ ++/** ++ * struct dpdmux_if_attr - Structure representing frame types configuration ++ * @rate: Configured interface rate (in bits per second) ++ * @enabled: Indicates if interface is enabled ++ * @accept_frame_type: Indicates type of accepted frames for the interface ++ */ ++struct dpdmux_if_attr { ++ uint32_t rate; ++ int enabled; ++ enum dpdmux_accepted_frames_type accept_frame_type; ++}; ++ ++/** ++ * dpdmux_if_get_attributes() - Obtain DPDMUX interface attributes ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * @if_id: Interface ID (0 for uplink, or 1-num_ifs); ++ * @attr: Interface attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_if_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ struct dpdmux_if_attr *attr); ++ ++/** ++ * struct dpdmux_l2_rule - Structure representing L2 rule ++ * @mac_addr: MAC address ++ * @vlan_id: VLAN ID ++ */ ++struct dpdmux_l2_rule { ++ uint8_t mac_addr[6]; ++ uint16_t vlan_id; ++}; ++ ++/** ++ * dpdmux_if_remove_l2_rule() - Remove L2 rule from DPDMUX table ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * @if_id: Destination interface ID ++ * @rule: L2 rule ++ * ++ * Function removes a L2 rule from DPDMUX table ++ * or adds an interface to an existing multicast address ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_if_remove_l2_rule(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpdmux_l2_rule *rule); ++ ++/** ++ * dpdmux_if_add_l2_rule() - Add L2 rule into DPDMUX table ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPDMUX object ++ * @if_id: Destination interface ID ++ * @rule: L2 rule ++ * ++ * Function adds a L2 rule into DPDMUX table ++ * or adds an interface to an existing multicast address ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_if_add_l2_rule(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpdmux_l2_rule *rule); ++ ++/** ++* dpdmux_if_get_counter() - Functions obtains specific counter of an interface ++* @mc_io: Pointer to MC portal's I/O object ++* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++* @token: Token of DPDMUX object ++* @if_id: Interface Id ++* @counter_type: counter type ++* @counter: Returned specific counter information ++* ++* Return: '0' on Success; Error code otherwise. ++*/ ++int dpdmux_if_get_counter(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ enum dpdmux_counter_type counter_type, ++ uint64_t *counter); ++ ++/** ++* dpdmux_ul_reset_counters() - Function resets the uplink counter ++* @mc_io: Pointer to MC portal's I/O object ++* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++* @token: Token of DPDMUX object ++* ++* Return: '0' on Success; Error code otherwise. ++*/ ++int dpdmux_ul_reset_counters(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * Enable auto-negotiation ++ */ ++#define DPDMUX_LINK_OPT_AUTONEG 0x0000000000000001ULL ++/** ++ * Enable half-duplex mode ++ */ ++#define DPDMUX_LINK_OPT_HALF_DUPLEX 0x0000000000000002ULL ++/** ++ * Enable pause frames ++ */ ++#define DPDMUX_LINK_OPT_PAUSE 0x0000000000000004ULL ++/** ++ * Enable a-symmetric pause frames ++ */ ++#define DPDMUX_LINK_OPT_ASYM_PAUSE 0x0000000000000008ULL ++ ++/** ++ * struct dpdmux_link_cfg - Structure representing DPDMUX link configuration ++ * @rate: Rate ++ * @options: Mask of available options; use 'DPDMUX_LINK_OPT_' values ++ */ ++struct dpdmux_link_cfg { ++ uint32_t rate; ++ uint64_t options; ++}; ++ ++/** ++ * dpdmux_if_set_link_cfg() - set the link configuration. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: interface id ++ * @cfg: Link configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpdmux_if_set_link_cfg(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ struct dpdmux_link_cfg *cfg); ++/** ++ * struct dpdmux_link_state - Structure representing DPDMUX link state ++ * @rate: Rate ++ * @options: Mask of available options; use 'DPDMUX_LINK_OPT_' values ++ * @up: 0 - down, 1 - up ++ */ ++struct dpdmux_link_state { ++ uint32_t rate; ++ uint64_t options; ++ int up; ++}; ++ ++/** ++ * dpdmux_if_get_link_state - Return the link state ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: interface id ++ * @state: link state ++ * ++ * @returns '0' on Success; Error code otherwise. ++ */ ++int dpdmux_if_get_link_state(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ struct dpdmux_link_state *state); ++ ++#endif /* __FSL_DPDMUX_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpdmux_cmd.h b/drivers/net/dpaa2/mc/fsl_dpdmux_cmd.h +new file mode 100644 +index 0000000..0a5cf17 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpdmux_cmd.h +@@ -0,0 +1,256 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_DPDMUX_CMD_H ++#define _FSL_DPDMUX_CMD_H ++ ++/* DPDMUX Version */ ++#define DPDMUX_VER_MAJOR 5 ++#define DPDMUX_VER_MINOR 0 ++ ++/* Command IDs */ ++#define DPDMUX_CMDID_CLOSE 0x800 ++#define DPDMUX_CMDID_OPEN 0x806 ++#define DPDMUX_CMDID_CREATE 0x906 ++#define DPDMUX_CMDID_DESTROY 0x900 ++ ++#define DPDMUX_CMDID_ENABLE 0x002 ++#define DPDMUX_CMDID_DISABLE 0x003 ++#define DPDMUX_CMDID_GET_ATTR 0x004 ++#define DPDMUX_CMDID_RESET 0x005 ++#define DPDMUX_CMDID_IS_ENABLED 0x006 ++ ++#define DPDMUX_CMDID_SET_IRQ 0x010 ++#define DPDMUX_CMDID_GET_IRQ 0x011 ++#define DPDMUX_CMDID_SET_IRQ_ENABLE 0x012 ++#define DPDMUX_CMDID_GET_IRQ_ENABLE 0x013 ++#define DPDMUX_CMDID_SET_IRQ_MASK 0x014 ++#define DPDMUX_CMDID_GET_IRQ_MASK 0x015 ++#define DPDMUX_CMDID_GET_IRQ_STATUS 0x016 ++#define DPDMUX_CMDID_CLEAR_IRQ_STATUS 0x017 ++ ++#define DPDMUX_CMDID_UL_SET_MAX_FRAME_LENGTH 0x0a1 ++ ++#define DPDMUX_CMDID_UL_RESET_COUNTERS 0x0a3 ++ ++#define DPDMUX_CMDID_IF_SET_ACCEPTED_FRAMES 0x0a7 ++#define DPDMUX_CMDID_IF_GET_ATTR 0x0a8 ++ ++#define DPDMUX_CMDID_IF_ADD_L2_RULE 0x0b0 ++#define DPDMUX_CMDID_IF_REMOVE_L2_RULE 0x0b1 ++#define DPDMUX_CMDID_IF_GET_COUNTER 0x0b2 ++#define DPDMUX_CMDID_IF_SET_LINK_CFG 0x0b3 ++#define DPDMUX_CMDID_IF_GET_LINK_STATE 0x0b4 ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_CMD_OPEN(cmd, dpdmux_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpdmux_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_CMD_CREATE(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, enum dpdmux_method, cfg->method);\ ++ MC_CMD_OP(cmd, 0, 8, 8, enum dpdmux_manip, cfg->manip);\ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->num_ifs);\ ++ MC_CMD_OP(cmd, 1, 0, 16, uint16_t, cfg->adv.max_dmat_entries);\ ++ MC_CMD_OP(cmd, 1, 16, 16, uint16_t, cfg->adv.max_mc_groups);\ ++ MC_CMD_OP(cmd, 1, 32, 16, uint16_t, cfg->adv.max_vlan_ids);\ ++ MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->adv.options);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_RSP_IS_ENABLED(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, irq_index);\ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, irq_cfg->val);\ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\ ++ MC_CMD_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_CMD_GET_IRQ(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_RSP_GET_IRQ(cmd, type, irq_cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr); \ ++ MC_RSP_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, type); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_CMD_SET_IRQ_ENABLE(cmd, irq_index, en) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, en);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_CMD_GET_IRQ_ENABLE(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_RSP_GET_IRQ_ENABLE(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 8, uint8_t, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, mask); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_CMD_GET_IRQ_MASK(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_RSP_GET_IRQ_MASK(cmd, mask) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mask) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_RSP_GET_IRQ_STATUS(cmd, status) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, status) \ ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index); \ ++} while (0) ++ ++#define DPDMUX_RSP_GET_ATTR(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 8, enum dpdmux_method, attr->method);\ ++ MC_RSP_OP(cmd, 0, 8, 8, enum dpdmux_manip, attr->manip);\ ++ MC_RSP_OP(cmd, 0, 16, 16, uint16_t, attr->num_ifs);\ ++ MC_RSP_OP(cmd, 0, 32, 16, uint16_t, attr->mem_size);\ ++ MC_RSP_OP(cmd, 2, 0, 32, int, attr->id);\ ++ MC_RSP_OP(cmd, 3, 0, 64, uint64_t, attr->options);\ ++ MC_RSP_OP(cmd, 4, 0, 16, uint16_t, attr->version.major);\ ++ MC_RSP_OP(cmd, 4, 16, 16, uint16_t, attr->version.minor);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_CMD_UL_SET_MAX_FRAME_LENGTH(cmd, max_frame_length) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, max_frame_length) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_CMD_IF_SET_ACCEPTED_FRAMES(cmd, if_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 16, 4, enum dpdmux_accepted_frames_type, cfg->type);\ ++ MC_CMD_OP(cmd, 0, 20, 4, enum dpdmux_unaccepted_frames_action, \ ++ cfg->unaccept_act);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_CMD_IF_GET_ATTR(cmd, if_id) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_RSP_IF_GET_ATTR(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 56, 4, enum dpdmux_accepted_frames_type, \ ++ attr->accept_frame_type);\ ++ MC_RSP_OP(cmd, 0, 24, 1, int, attr->enabled);\ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, attr->rate);\ ++} while (0) ++ ++#define DPDMUX_CMD_IF_REMOVE_L2_RULE(cmd, if_id, l2_rule) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, l2_rule->mac_addr[5]);\ ++ MC_CMD_OP(cmd, 0, 24, 8, uint8_t, l2_rule->mac_addr[4]);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, l2_rule->mac_addr[3]);\ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, l2_rule->mac_addr[2]);\ ++ MC_CMD_OP(cmd, 0, 48, 8, uint8_t, l2_rule->mac_addr[1]);\ ++ MC_CMD_OP(cmd, 0, 56, 8, uint8_t, l2_rule->mac_addr[0]);\ ++ MC_CMD_OP(cmd, 1, 32, 16, uint16_t, l2_rule->vlan_id);\ ++} while (0) ++ ++#define DPDMUX_CMD_IF_ADD_L2_RULE(cmd, if_id, l2_rule) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, l2_rule->mac_addr[5]);\ ++ MC_CMD_OP(cmd, 0, 24, 8, uint8_t, l2_rule->mac_addr[4]);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, l2_rule->mac_addr[3]);\ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, l2_rule->mac_addr[2]);\ ++ MC_CMD_OP(cmd, 0, 48, 8, uint8_t, l2_rule->mac_addr[1]);\ ++ MC_CMD_OP(cmd, 0, 56, 8, uint8_t, l2_rule->mac_addr[0]);\ ++ MC_CMD_OP(cmd, 1, 32, 16, uint16_t, l2_rule->vlan_id);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_CMD_IF_GET_COUNTER(cmd, if_id, counter_type) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 16, 8, enum dpdmux_counter_type, counter_type);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_RSP_IF_GET_COUNTER(cmd, counter) \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, counter) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_CMD_IF_SET_LINK_CFG(cmd, if_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 1, 0, 32, uint32_t, cfg->rate);\ ++ MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->options);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_CMD_IF_GET_LINK_STATE(cmd, if_id) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPDMUX_RSP_IF_GET_LINK_STATE(cmd, state) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 32, 1, int, state->up);\ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, state->rate);\ ++ MC_RSP_OP(cmd, 2, 0, 64, uint64_t, state->options);\ ++} while (0) ++ ++#endif /* _FSL_DPDMUX_CMD_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpio.h b/drivers/net/dpaa2/mc/fsl_dpio.h +new file mode 100644 +index 0000000..88a492f +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpio.h +@@ -0,0 +1,460 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPIO_H ++#define __FSL_DPIO_H ++ ++/* Data Path I/O Portal API ++ * Contains initialization APIs and runtime control APIs for DPIO ++ */ ++ ++struct fsl_mc_io; ++ ++/** ++ * dpio_open() - Open a control session for the specified object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @dpio_id: DPIO unique ID ++ * @token: Returned token; use in subsequent API calls ++ * ++ * This function can be used to open a control session for an ++ * already created object; an object may have been declared in ++ * the DPL or by calling the dpio_create() function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent commands for ++ * this specific object. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpio_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpio_id, ++ uint16_t *token); ++ ++/** ++ * dpio_close() - Close the control session of the object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpio_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * enum dpio_channel_mode - DPIO notification channel mode ++ * @DPIO_NO_CHANNEL: No support for notification channel ++ * @DPIO_LOCAL_CHANNEL: Notifications on data availability can be received by a ++ * dedicated channel in the DPIO; user should point the queue's ++ * destination in the relevant interface to this DPIO ++ */ ++enum dpio_channel_mode { ++ DPIO_NO_CHANNEL = 0, ++ DPIO_LOCAL_CHANNEL = 1, ++}; ++ ++/** ++ * struct dpio_cfg - Structure representing DPIO configuration ++ * @channel_mode: Notification channel mode ++ * @num_priorities: Number of priorities for the notification channel (1-8); ++ * relevant only if 'channel_mode = DPIO_LOCAL_CHANNEL' ++ */ ++struct dpio_cfg { ++ enum dpio_channel_mode channel_mode; ++ uint8_t num_priorities; ++}; ++ ++/** ++ * dpio_create() - Create the DPIO object. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @cfg: Configuration structure ++ * @token: Returned token; use in subsequent API calls ++ * ++ * Create the DPIO object, allocate required resources and ++ * perform required initialization. ++ * ++ * The object can be created either by declaring it in the ++ * DPL file, or by calling this function. ++ * ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent calls to ++ * this specific object. For objects that are created using the ++ * DPL file, call dpio_open() function to get an authentication ++ * token first. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpio_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpio_cfg *cfg, ++ uint16_t *token); ++ ++/** ++ * dpio_destroy() - Destroy the DPIO object and release all its resources. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * ++ * Return: '0' on Success; Error code otherwise ++ */ ++int dpio_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpio_enable() - Enable the DPIO, allow I/O portal operations. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * ++ * Return: '0' on Success; Error code otherwise ++ */ ++int dpio_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpio_disable() - Disable the DPIO, stop any I/O portal operation. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * ++ * Return: '0' on Success; Error code otherwise ++ */ ++int dpio_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpio_is_enabled() - Check if the DPIO is enabled. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * @en: Returns '1' if object is enabled; '0' otherwise ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpio_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en); ++ ++/** ++ * dpio_reset() - Reset the DPIO, returns the object to initial state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpio_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpio_set_stashing_destination() - Set the stashing destination. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * @sdest: stashing destination value ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpio_set_stashing_destination(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t sdest); ++ ++/** ++ * dpio_get_stashing_destination() - Get the stashing destination.. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * @sdest: Returns the stashing destination value ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpio_get_stashing_destination(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t *sdest); ++ ++/** ++ * dpio_add_static_dequeue_channel() - Add a static dequeue channel. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * @dpcon_id: DPCON object ID ++ * @channel_index: Returned channel index to be used in qbman API ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpio_add_static_dequeue_channel(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpcon_id, ++ uint8_t *channel_index); ++ ++/** ++ * dpio_remove_static_dequeue_channel() - Remove a static dequeue channel. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * @dpcon_id: DPCON object ID ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpio_remove_static_dequeue_channel(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int dpcon_id); ++ ++/** ++ * DPIO IRQ Index and Events ++ */ ++ ++/** ++ * Irq software-portal index ++ */ ++#define DPIO_IRQ_SWP_INDEX 0 ++ ++/** ++ * struct dpio_irq_cfg - IRQ configuration ++ * @addr: Address that must be written to signal a message-based interrupt ++ * @val: Value to write into irq_addr address ++ * @irq_num: A user defined number associated with this IRQ ++ */ ++struct dpio_irq_cfg { ++ uint64_t addr; ++ uint32_t val; ++ int irq_num; ++}; ++ ++/** ++ * dpio_set_irq() - Set IRQ information for the DPIO to trigger an interrupt. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * @irq_index: Identifies the interrupt index to configure ++ * @irq_cfg: IRQ configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpio_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpio_irq_cfg *irq_cfg); ++ ++/** ++ * dpio_get_irq() - Get IRQ information from the DPIO. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * @irq_index: The interrupt index to configure ++ * @type: Interrupt type: 0 represents message interrupt ++ * type (both irq_addr and irq_val are valid) ++ * @irq_cfg: IRQ attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpio_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpio_irq_cfg *irq_cfg); ++ ++/** ++ * dpio_set_irq_enable() - Set overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * @irq_index: The interrupt index to configure ++ * @en: Interrupt state - enable = 1, disable = 0 ++ * ++ * Allows GPP software to control when interrupts are generated. ++ * Each interrupt can have up to 32 causes. The enable/disable control's the ++ * overall interrupt state. if the interrupt is disabled no causes will cause ++ * an interrupt. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpio_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en); ++ ++/** ++ * dpio_get_irq_enable() - Get overall interrupt state ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * @irq_index: The interrupt index to configure ++ * @en: Returned interrupt state - enable = 1, disable = 0 ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpio_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en); ++ ++/** ++ * dpio_set_irq_mask() - Set interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * @irq_index: The interrupt index to configure ++ * @mask: event mask to trigger interrupt; ++ * each bit: ++ * 0 = ignore event ++ * 1 = consider event for asserting IRQ ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpio_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask); ++ ++/** ++ * dpio_get_irq_mask() - Get interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * @irq_index: The interrupt index to configure ++ * @mask: Returned event mask to trigger interrupt ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpio_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask); ++ ++/** ++ * dpio_get_irq_status() - Get the current status of any pending interrupts. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * @irq_index: The interrupt index to configure ++ * @status: Returned interrupts status - one bit per cause: ++ * 0 = no interrupt pending ++ * 1 = interrupt pending ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpio_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status); ++ ++/** ++ * dpio_clear_irq_status() - Clear a pending interrupt's status ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * @irq_index: The interrupt index to configure ++ * @status: bits to clear (W1C) - one bit per cause: ++ * 0 = don't change ++ * 1 = clear status bit ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpio_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status); ++ ++/** ++ * struct dpio_attr - Structure representing DPIO attributes ++ * @id: DPIO object ID ++ * @version: DPIO version ++ * @qbman_portal_ce_offset: offset of the software portal cache-enabled area ++ * @qbman_portal_ci_offset: offset of the software portal cache-inhibited area ++ * @qbman_portal_id: Software portal ID ++ * @channel_mode: Notification channel mode ++ * @num_priorities: Number of priorities for the notification channel (1-8); ++ * relevant only if 'channel_mode = DPIO_LOCAL_CHANNEL' ++ * @qbman_version: QBMAN version ++ */ ++struct dpio_attr { ++ int id; ++ /** ++ * struct version - DPIO version ++ * @major: DPIO major version ++ * @minor: DPIO minor version ++ */ ++ struct { ++ uint16_t major; ++ uint16_t minor; ++ } version; ++ uint64_t qbman_portal_ce_offset; ++ uint64_t qbman_portal_ci_offset; ++ uint16_t qbman_portal_id; ++ enum dpio_channel_mode channel_mode; ++ uint8_t num_priorities; ++ uint32_t qbman_version; ++}; ++ ++/** ++ * dpio_get_attributes() - Retrieve DPIO attributes ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPIO object ++ * @attr: Returned object's attributes ++ * ++ * Return: '0' on Success; Error code otherwise ++ */ ++int dpio_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpio_attr *attr); ++#endif /* __FSL_DPIO_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpio_cmd.h b/drivers/net/dpaa2/mc/fsl_dpio_cmd.h +new file mode 100644 +index 0000000..f339cd6 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpio_cmd.h +@@ -0,0 +1,184 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_DPIO_CMD_H ++#define _FSL_DPIO_CMD_H ++ ++/* DPIO Version */ ++#define DPIO_VER_MAJOR 3 ++#define DPIO_VER_MINOR 2 ++ ++/* Command IDs */ ++#define DPIO_CMDID_CLOSE 0x800 ++#define DPIO_CMDID_OPEN 0x803 ++#define DPIO_CMDID_CREATE 0x903 ++#define DPIO_CMDID_DESTROY 0x900 ++ ++#define DPIO_CMDID_ENABLE 0x002 ++#define DPIO_CMDID_DISABLE 0x003 ++#define DPIO_CMDID_GET_ATTR 0x004 ++#define DPIO_CMDID_RESET 0x005 ++#define DPIO_CMDID_IS_ENABLED 0x006 ++ ++#define DPIO_CMDID_SET_IRQ 0x010 ++#define DPIO_CMDID_GET_IRQ 0x011 ++#define DPIO_CMDID_SET_IRQ_ENABLE 0x012 ++#define DPIO_CMDID_GET_IRQ_ENABLE 0x013 ++#define DPIO_CMDID_SET_IRQ_MASK 0x014 ++#define DPIO_CMDID_GET_IRQ_MASK 0x015 ++#define DPIO_CMDID_GET_IRQ_STATUS 0x016 ++#define DPIO_CMDID_CLEAR_IRQ_STATUS 0x017 ++ ++#define DPIO_CMDID_SET_STASHING_DEST 0x120 ++#define DPIO_CMDID_GET_STASHING_DEST 0x121 ++#define DPIO_CMDID_ADD_STATIC_DEQUEUE_CHANNEL 0x122 ++#define DPIO_CMDID_REMOVE_STATIC_DEQUEUE_CHANNEL 0x123 ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_CMD_OPEN(cmd, dpio_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpio_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_CMD_CREATE(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 16, 2, enum dpio_channel_mode, \ ++ cfg->channel_mode);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->num_priorities);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_RSP_IS_ENABLED(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, irq_index);\ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, irq_cfg->val);\ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\ ++ MC_CMD_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_CMD_GET_IRQ(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_RSP_GET_IRQ(cmd, type, irq_cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr); \ ++ MC_RSP_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, type); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_CMD_SET_IRQ_ENABLE(cmd, irq_index, en) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, en); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_CMD_GET_IRQ_ENABLE(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_RSP_GET_IRQ_ENABLE(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 8, uint8_t, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, mask); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_CMD_GET_IRQ_MASK(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_RSP_GET_IRQ_MASK(cmd, mask) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mask) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_RSP_GET_IRQ_STATUS(cmd, status) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, status) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_RSP_GET_ATTR(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, attr->id);\ ++ MC_RSP_OP(cmd, 0, 32, 16, uint16_t, attr->qbman_portal_id);\ ++ MC_RSP_OP(cmd, 0, 48, 8, uint8_t, attr->num_priorities);\ ++ MC_RSP_OP(cmd, 0, 56, 4, enum dpio_channel_mode, attr->channel_mode);\ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, attr->qbman_portal_ce_offset);\ ++ MC_RSP_OP(cmd, 2, 0, 64, uint64_t, attr->qbman_portal_ci_offset);\ ++ MC_RSP_OP(cmd, 3, 0, 16, uint16_t, attr->version.major);\ ++ MC_RSP_OP(cmd, 3, 16, 16, uint16_t, attr->version.minor);\ ++ MC_RSP_OP(cmd, 3, 32, 32, uint32_t, attr->qbman_version);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_CMD_SET_STASHING_DEST(cmd, sdest) \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, sdest) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_RSP_GET_STASHING_DEST(cmd, sdest) \ ++ MC_RSP_OP(cmd, 0, 0, 8, uint8_t, sdest) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_CMD_ADD_STATIC_DEQUEUE_CHANNEL(cmd, dpcon_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpcon_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_RSP_ADD_STATIC_DEQUEUE_CHANNEL(cmd, channel_index) \ ++ MC_RSP_OP(cmd, 0, 0, 8, uint8_t, channel_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPIO_CMD_REMOVE_STATIC_DEQUEUE_CHANNEL(cmd, dpcon_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpcon_id) ++#endif /* _FSL_DPIO_CMD_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpkg.h b/drivers/net/dpaa2/mc/fsl_dpkg.h +new file mode 100644 +index 0000000..b2bceaf +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpkg.h +@@ -0,0 +1,174 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPKG_H_ ++#define __FSL_DPKG_H_ ++ ++#include ++ ++/* Data Path Key Generator API ++ * Contains initialization APIs and runtime APIs for the Key Generator ++ */ ++ ++/** Key Generator properties */ ++ ++/** ++ * Number of masks per key extraction ++ */ ++#define DPKG_NUM_OF_MASKS 4 ++/** ++ * Number of extractions per key profile ++ */ ++#define DPKG_MAX_NUM_OF_EXTRACTS 10 ++ ++/** ++ * enum dpkg_extract_from_hdr_type - Selecting extraction by header types ++ * @DPKG_FROM_HDR: Extract selected bytes from header, by offset ++ * @DPKG_FROM_FIELD: Extract selected bytes from header, by offset from field ++ * @DPKG_FULL_FIELD: Extract a full field ++ */ ++enum dpkg_extract_from_hdr_type { ++ DPKG_FROM_HDR = 0, ++ DPKG_FROM_FIELD = 1, ++ DPKG_FULL_FIELD = 2 ++}; ++ ++/** ++ * enum dpkg_extract_type - Enumeration for selecting extraction type ++ * @DPKG_EXTRACT_FROM_HDR: Extract from the header ++ * @DPKG_EXTRACT_FROM_DATA: Extract from data not in specific header ++ * @DPKG_EXTRACT_FROM_PARSE: Extract from parser-result; ++ * e.g. can be used to extract header existence; ++ * please refer to 'Parse Result definition' section in the parser BG ++ */ ++enum dpkg_extract_type { ++ DPKG_EXTRACT_FROM_HDR = 0, ++ DPKG_EXTRACT_FROM_DATA = 1, ++ DPKG_EXTRACT_FROM_PARSE = 3 ++}; ++ ++/** ++ * struct dpkg_mask - A structure for defining a single extraction mask ++ * @mask: Byte mask for the extracted content ++ * @offset: Offset within the extracted content ++ */ ++struct dpkg_mask { ++ uint8_t mask; ++ uint8_t offset; ++}; ++ ++/** ++ * struct dpkg_extract - A structure for defining a single extraction ++ * @type: Determines how the union below is interpreted: ++ * DPKG_EXTRACT_FROM_HDR: selects 'from_hdr'; ++ * DPKG_EXTRACT_FROM_DATA: selects 'from_data'; ++ * DPKG_EXTRACT_FROM_PARSE: selects 'from_parse' ++ * @extract: Selects extraction method ++ * @num_of_byte_masks: Defines the number of valid entries in the array below; ++ * This is also the number of bytes to be used as masks ++ * @masks: Masks parameters ++ */ ++struct dpkg_extract { ++ enum dpkg_extract_type type; ++ /** ++ * union extract - Selects extraction method ++ * @from_hdr - Used when 'type = DPKG_EXTRACT_FROM_HDR' ++ * @from_data - Used when 'type = DPKG_EXTRACT_FROM_DATA' ++ * @from_parse - Used when 'type = DPKG_EXTRACT_FROM_PARSE' ++ */ ++ union { ++ /** ++ * struct from_hdr - Used when 'type = DPKG_EXTRACT_FROM_HDR' ++ * @prot: Any of the supported headers ++ * @type: Defines the type of header extraction: ++ * DPKG_FROM_HDR: use size & offset below; ++ * DPKG_FROM_FIELD: use field, size and offset below; ++ * DPKG_FULL_FIELD: use field below ++ * @field: One of the supported fields (NH_FLD_) ++ * ++ * @size: Size in bytes ++ * @offset: Byte offset ++ * @hdr_index: Clear for cases not listed below; ++ * Used for protocols that may have more than a single ++ * header, 0 indicates an outer header; ++ * Supported protocols (possible values): ++ * NET_PROT_VLAN (0, HDR_INDEX_LAST); ++ * NET_PROT_MPLS (0, 1, HDR_INDEX_LAST); ++ * NET_PROT_IP(0, HDR_INDEX_LAST); ++ * NET_PROT_IPv4(0, HDR_INDEX_LAST); ++ * NET_PROT_IPv6(0, HDR_INDEX_LAST); ++ */ ++ ++ struct { ++ enum net_prot prot; ++ enum dpkg_extract_from_hdr_type type; ++ uint32_t field; ++ uint8_t size; ++ uint8_t offset; ++ uint8_t hdr_index; ++ } from_hdr; ++ /** ++ * struct from_data - Used when 'type = DPKG_EXTRACT_FROM_DATA' ++ * @size: Size in bytes ++ * @offset: Byte offset ++ */ ++ struct { ++ uint8_t size; ++ uint8_t offset; ++ } from_data; ++ ++ /** ++ * struct from_parse - Used when 'type = DPKG_EXTRACT_FROM_PARSE' ++ * @size: Size in bytes ++ * @offset: Byte offset ++ */ ++ struct { ++ uint8_t size; ++ uint8_t offset; ++ } from_parse; ++ } extract; ++ ++ uint8_t num_of_byte_masks; ++ struct dpkg_mask masks[DPKG_NUM_OF_MASKS]; ++}; ++ ++/** ++ * struct dpkg_profile_cfg - A structure for defining a full Key Generation ++ * profile (rule) ++ * @num_extracts: Defines the number of valid entries in the array below ++ * @extracts: Array of required extractions ++ */ ++struct dpkg_profile_cfg { ++ uint8_t num_extracts; ++ struct dpkg_extract extracts[DPKG_MAX_NUM_OF_EXTRACTS]; ++}; ++ ++#endif /* __FSL_DPKG_H_ */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpmac.h b/drivers/net/dpaa2/mc/fsl_dpmac.h +new file mode 100644 +index 0000000..ad27772 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpmac.h +@@ -0,0 +1,593 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPMAC_H ++#define __FSL_DPMAC_H ++ ++/* Data Path MAC API ++ * Contains initialization APIs and runtime control APIs for DPMAC ++ */ ++ ++struct fsl_mc_io; ++ ++/** ++ * dpmac_open() - Open a control session for the specified object. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @dpmac_id: DPMAC unique ID ++ * @token: Returned token; use in subsequent API calls ++ * ++ * This function can be used to open a control session for an ++ * already created object; an object may have been declared in ++ * the DPL or by calling the dpmac_create function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent commands for ++ * this specific object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmac_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpmac_id, ++ uint16_t *token); ++ ++/** ++ * dpmac_close() - Close the control session of the object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMAC object ++ * ++ * After this function is called, no further operations are ++ * allowed on the object without opening a new control session. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmac_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * enum dpmac_link_type - DPMAC link type ++ * @DPMAC_LINK_TYPE_NONE: No link ++ * @DPMAC_LINK_TYPE_FIXED: Link is fixed type ++ * @DPMAC_LINK_TYPE_PHY: Link by PHY ID ++ * @DPMAC_LINK_TYPE_BACKPLANE: Backplane link type ++ */ ++enum dpmac_link_type { ++ DPMAC_LINK_TYPE_NONE, ++ DPMAC_LINK_TYPE_FIXED, ++ DPMAC_LINK_TYPE_PHY, ++ DPMAC_LINK_TYPE_BACKPLANE ++}; ++ ++/** ++ * enum dpmac_eth_if - DPMAC Ethrnet interface ++ * @DPMAC_ETH_IF_MII: MII interface ++ * @DPMAC_ETH_IF_RMII: RMII interface ++ * @DPMAC_ETH_IF_SMII: SMII interface ++ * @DPMAC_ETH_IF_GMII: GMII interface ++ * @DPMAC_ETH_IF_RGMII: RGMII interface ++ * @DPMAC_ETH_IF_SGMII: SGMII interface ++ * @DPMAC_ETH_IF_QSGMII: QSGMII interface ++ * @DPMAC_ETH_IF_XAUI: XAUI interface ++ * @DPMAC_ETH_IF_XFI: XFI interface ++ */ ++enum dpmac_eth_if { ++ DPMAC_ETH_IF_MII, ++ DPMAC_ETH_IF_RMII, ++ DPMAC_ETH_IF_SMII, ++ DPMAC_ETH_IF_GMII, ++ DPMAC_ETH_IF_RGMII, ++ DPMAC_ETH_IF_SGMII, ++ DPMAC_ETH_IF_QSGMII, ++ DPMAC_ETH_IF_XAUI, ++ DPMAC_ETH_IF_XFI ++}; ++ ++/** ++ * struct dpmac_cfg - Structure representing DPMAC configuration ++ * @mac_id: Represents the Hardware MAC ID; in case of multiple WRIOP, ++ * the MAC IDs are continuous. ++ * For example: 2 WRIOPs, 16 MACs in each: ++ * MAC IDs for the 1st WRIOP: 1-16, ++ * MAC IDs for the 2nd WRIOP: 17-32. ++ */ ++struct dpmac_cfg { ++ int mac_id; ++}; ++ ++/** ++ * dpmac_create() - Create the DPMAC object. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @cfg: Configuration structure ++ * @token: Returned token; use in subsequent API calls ++ * ++ * Create the DPMAC object, allocate required resources and ++ * perform required initialization. ++ * ++ * The object can be created either by declaring it in the ++ * DPL file, or by calling this function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent calls to ++ * this specific object. For objects that are created using the ++ * DPL file, call dpmac_open function to get an authentication ++ * token first. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmac_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpmac_cfg *cfg, ++ uint16_t *token); ++ ++/** ++ * dpmac_destroy() - Destroy the DPMAC object and release all its resources. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMAC object ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpmac_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * DPMAC IRQ Index and Events ++ */ ++ ++/** ++ * IRQ index ++ */ ++#define DPMAC_IRQ_INDEX 0 ++/** ++ * IRQ event - indicates a change in link state ++ */ ++#define DPMAC_IRQ_EVENT_LINK_CFG_REQ 0x00000001 ++/** ++ * IRQ event - Indicates that the link state changed ++ */ ++#define DPMAC_IRQ_EVENT_LINK_CHANGED 0x00000002 ++ ++/** ++ * struct dpmac_irq_cfg - IRQ configuration ++ * @addr: Address that must be written to signal a message-based interrupt ++ * @val: Value to write into irq_addr address ++ * @irq_num: A user defined number associated with this IRQ ++ */ ++struct dpmac_irq_cfg { ++ uint64_t addr; ++ uint32_t val; ++ int irq_num; ++}; ++ ++/** ++ * dpmac_set_irq() - Set IRQ information for the DPMAC to trigger an interrupt. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMAC object ++ * @irq_index: Identifies the interrupt index to configure ++ * @irq_cfg: IRQ configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmac_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpmac_irq_cfg *irq_cfg); ++ ++/** ++ * dpmac_get_irq() - Get IRQ information from the DPMAC. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMAC object ++ * @irq_index: The interrupt index to configure ++ * @type: Interrupt type: 0 represents message interrupt ++ * type (both irq_addr and irq_val are valid) ++ * @irq_cfg: IRQ attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmac_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpmac_irq_cfg *irq_cfg); ++ ++/** ++ * dpmac_set_irq_enable() - Set overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMAC object ++ * @irq_index: The interrupt index to configure ++ * @en: Interrupt state - enable = 1, disable = 0 ++ * ++ * Allows GPP software to control when interrupts are generated. ++ * Each interrupt can have up to 32 causes. The enable/disable control's the ++ * overall interrupt state. if the interrupt is disabled no causes will cause ++ * an interrupt. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmac_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en); ++ ++/** ++ * dpmac_get_irq_enable() - Get overall interrupt state ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMAC object ++ * @irq_index: The interrupt index to configure ++ * @en: Returned interrupt state - enable = 1, disable = 0 ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmac_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en); ++ ++/** ++ * dpmac_set_irq_mask() - Set interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMAC object ++ * @irq_index: The interrupt index to configure ++ * @mask: Event mask to trigger interrupt; ++ * each bit: ++ * 0 = ignore event ++ * 1 = consider event for asserting IRQ ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmac_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask); ++ ++/** ++ * dpmac_get_irq_mask() - Get interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMAC object ++ * @irq_index: The interrupt index to configure ++ * @mask: Returned event mask to trigger interrupt ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmac_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask); ++ ++/** ++ * dpmac_get_irq_status() - Get the current status of any pending interrupts. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMAC object ++ * @irq_index: The interrupt index to configure ++ * @status: Returned interrupts status - one bit per cause: ++ * 0 = no interrupt pending ++ * 1 = interrupt pending ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmac_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status); ++ ++/** ++ * dpmac_clear_irq_status() - Clear a pending interrupt's status ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMAC object ++ * @irq_index: The interrupt index to configure ++ * @status: Bits to clear (W1C) - one bit per cause: ++ * 0 = don't change ++ * 1 = clear status bit ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmac_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status); ++ ++/** ++ * struct dpmac_attr - Structure representing DPMAC attributes ++ * @id: DPMAC object ID ++ * @phy_id: PHY ID ++ * @link_type: link type ++ * @eth_if: Ethernet interface ++ * @max_rate: Maximum supported rate - in Mbps ++ * @version: DPMAC version ++ */ ++struct dpmac_attr { ++ int id; ++ int phy_id; ++ enum dpmac_link_type link_type; ++ enum dpmac_eth_if eth_if; ++ uint32_t max_rate; ++ /** ++ * struct version - Structure representing DPMAC version ++ * @major: DPMAC major version ++ * @minor: DPMAC minor version ++ */ ++ struct { ++ uint16_t major; ++ uint16_t minor; ++ } version; ++}; ++ ++/** ++ * dpmac_get_attributes - Retrieve DPMAC attributes. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMAC object ++ * @attr: Returned object's attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmac_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpmac_attr *attr); ++ ++/** ++ * struct dpmac_mdio_cfg - DPMAC MDIO read/write parameters ++ * @phy_addr: MDIO device address ++ * @reg: Address of the register within the Clause 45 PHY device from which data ++ * is to be read ++ * @data: Data read/write from/to MDIO ++ */ ++struct dpmac_mdio_cfg { ++ uint8_t phy_addr; ++ uint8_t reg; ++ uint16_t data; ++}; ++ ++/** ++ * dpmac_mdio_read() - Perform MDIO read transaction ++ * @mc_io: Pointer to opaque I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMAC object ++ * @cfg: Structure with MDIO transaction parameters ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmac_mdio_read(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpmac_mdio_cfg *cfg); ++ ++/** ++ * dpmac_mdio_write() - Perform MDIO write transaction ++ * @mc_io: Pointer to opaque I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMAC object ++ * @cfg: Structure with MDIO transaction parameters ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmac_mdio_write(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpmac_mdio_cfg *cfg); ++ ++/** ++ * DPMAC link configuration/state options ++ */ ++ ++/** ++ * Enable auto-negotiation ++ */ ++#define DPMAC_LINK_OPT_AUTONEG 0x0000000000000001ULL ++/** ++ * Enable half-duplex mode ++ */ ++#define DPMAC_LINK_OPT_HALF_DUPLEX 0x0000000000000002ULL ++/** ++ * Enable pause frames ++ */ ++#define DPMAC_LINK_OPT_PAUSE 0x0000000000000004ULL ++/** ++ * Enable a-symmetric pause frames ++ */ ++#define DPMAC_LINK_OPT_ASYM_PAUSE 0x0000000000000008ULL ++ ++/** ++ * struct dpmac_link_cfg - Structure representing DPMAC link configuration ++ * @rate: Link's rate - in Mbps ++ * @options: Enable/Disable DPMAC link cfg features (bitmap) ++ */ ++struct dpmac_link_cfg { ++ uint32_t rate; ++ uint64_t options; ++}; ++ ++/** ++ * dpmac_get_link_cfg() - Get Ethernet link configuration ++ * @mc_io: Pointer to opaque I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMAC object ++ * @cfg: Returned structure with the link configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmac_get_link_cfg(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpmac_link_cfg *cfg); ++ ++/** ++ * struct dpmac_link_state - DPMAC link configuration request ++ * @rate: Rate in Mbps ++ * @options: Enable/Disable DPMAC link cfg features (bitmap) ++ * @up: Link state ++ */ ++struct dpmac_link_state { ++ uint32_t rate; ++ uint64_t options; ++ int up; ++}; ++ ++/** ++ * dpmac_set_link_state() - Set the Ethernet link status ++ * @mc_io: Pointer to opaque I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMAC object ++ * @link_state: Link state configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmac_set_link_state(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpmac_link_state *link_state); ++ ++/** ++ * enum dpmac_counter - DPMAC counter types ++ * @DPMAC_CNT_ING_FRAME_64: counts 64-bytes frames, good or bad. ++ * @DPMAC_CNT_ING_FRAME_127: counts 65- to 127-bytes frames, good or bad. ++ * @DPMAC_CNT_ING_FRAME_255: counts 128- to 255-bytes frames, good or bad. ++ * @DPMAC_CNT_ING_FRAME_511: counts 256- to 511-bytes frames, good or bad. ++ * @DPMAC_CNT_ING_FRAME_1023: counts 512- to 1023-bytes frames, good or bad. ++ * @DPMAC_CNT_ING_FRAME_1518: counts 1024- to 1518-bytes frames, good or bad. ++ * @DPMAC_CNT_ING_FRAME_1519_MAX: counts 1519-bytes frames and larger ++ * (up to max frame length specified), ++ * good or bad. ++ * @DPMAC_CNT_ING_FRAG: counts frames which are shorter than 64 bytes received ++ * with a wrong CRC ++ * @DPMAC_CNT_ING_JABBER: counts frames longer than the maximum frame length ++ * specified, with a bad frame check sequence. ++ * @DPMAC_CNT_ING_FRAME_DISCARD: counts dropped frames due to internal errors. ++ * Occurs when a receive FIFO overflows. ++ * Includes also frames truncated as a result of ++ * the receive FIFO overflow. ++ * @DPMAC_CNT_ING_ALIGN_ERR: counts frames with an alignment error ++ * (optional used for wrong SFD). ++ * @DPMAC_CNT_EGR_UNDERSIZED: counts frames transmitted that was less than 64 ++ * bytes long with a good CRC. ++ * @DPMAC_CNT_ING_OVERSIZED: counts frames longer than the maximum frame length ++ * specified, with a good frame check sequence. ++ * @DPMAC_CNT_ING_VALID_PAUSE_FRAME: counts valid pause frames (regular and PFC) ++ * @DPMAC_CNT_EGR_VALID_PAUSE_FRAME: counts valid pause frames transmitted ++ * (regular and PFC). ++ * @DPMAC_CNT_ING_BYTE: counts bytes received except preamble for all valid ++ * frames and valid pause frames. ++ * @DPMAC_CNT_ING_MCAST_FRAME: counts received multicast frames. ++ * @DPMAC_CNT_ING_BCAST_FRAME: counts received broadcast frames. ++ * @DPMAC_CNT_ING_ALL_FRAME: counts each good or bad frames received. ++ * @DPMAC_CNT_ING_UCAST_FRAME: counts received unicast frames. ++ * @DPMAC_CNT_ING_ERR_FRAME: counts frames received with an error ++ * (except for undersized/fragment frame). ++ * @DPMAC_CNT_EGR_BYTE: counts bytes transmitted except preamble for all valid ++ * frames and valid pause frames transmitted. ++ * @DPMAC_CNT_EGR_MCAST_FRAME: counts transmitted multicast frames. ++ * @DPMAC_CNT_EGR_BCAST_FRAME: counts transmitted broadcast frames. ++ * @DPMAC_CNT_EGR_UCAST_FRAME: counts transmitted unicast frames. ++ * @DPMAC_CNT_EGR_ERR_FRAME: counts frames transmitted with an error. ++ * @DPMAC_CNT_ING_GOOD_FRAME: counts frames received without error, including ++ * pause frames. ++ * @DPMAC_CNT_ENG_GOOD_FRAME: counts frames transmitted without error, including ++ * pause frames. ++ */ ++enum dpmac_counter { ++ DPMAC_CNT_ING_FRAME_64, ++ DPMAC_CNT_ING_FRAME_127, ++ DPMAC_CNT_ING_FRAME_255, ++ DPMAC_CNT_ING_FRAME_511, ++ DPMAC_CNT_ING_FRAME_1023, ++ DPMAC_CNT_ING_FRAME_1518, ++ DPMAC_CNT_ING_FRAME_1519_MAX, ++ DPMAC_CNT_ING_FRAG, ++ DPMAC_CNT_ING_JABBER, ++ DPMAC_CNT_ING_FRAME_DISCARD, ++ DPMAC_CNT_ING_ALIGN_ERR, ++ DPMAC_CNT_EGR_UNDERSIZED, ++ DPMAC_CNT_ING_OVERSIZED, ++ DPMAC_CNT_ING_VALID_PAUSE_FRAME, ++ DPMAC_CNT_EGR_VALID_PAUSE_FRAME, ++ DPMAC_CNT_ING_BYTE, ++ DPMAC_CNT_ING_MCAST_FRAME, ++ DPMAC_CNT_ING_BCAST_FRAME, ++ DPMAC_CNT_ING_ALL_FRAME, ++ DPMAC_CNT_ING_UCAST_FRAME, ++ DPMAC_CNT_ING_ERR_FRAME, ++ DPMAC_CNT_EGR_BYTE, ++ DPMAC_CNT_EGR_MCAST_FRAME, ++ DPMAC_CNT_EGR_BCAST_FRAME, ++ DPMAC_CNT_EGR_UCAST_FRAME, ++ DPMAC_CNT_EGR_ERR_FRAME, ++ DPMAC_CNT_ING_GOOD_FRAME, ++ DPMAC_CNT_ENG_GOOD_FRAME ++}; ++ ++/** ++ * dpmac_get_counter() - Read a specific DPMAC counter ++ * @mc_io: Pointer to opaque I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMAC object ++ * @type: The requested counter ++ * @counter: Returned counter value ++ * ++ * Return: The requested counter; '0' otherwise. ++ */ ++int dpmac_get_counter(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ enum dpmac_counter type, ++ uint64_t *counter); ++ ++#endif /* __FSL_DPMAC_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpmac_cmd.h b/drivers/net/dpaa2/mc/fsl_dpmac_cmd.h +new file mode 100644 +index 0000000..dc00590 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpmac_cmd.h +@@ -0,0 +1,195 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_DPMAC_CMD_H ++#define _FSL_DPMAC_CMD_H ++ ++/* DPMAC Version */ ++#define DPMAC_VER_MAJOR 3 ++#define DPMAC_VER_MINOR 2 ++ ++/* Command IDs */ ++#define DPMAC_CMDID_CLOSE 0x800 ++#define DPMAC_CMDID_OPEN 0x80c ++#define DPMAC_CMDID_CREATE 0x90c ++#define DPMAC_CMDID_DESTROY 0x900 ++ ++#define DPMAC_CMDID_GET_ATTR 0x004 ++#define DPMAC_CMDID_RESET 0x005 ++ ++#define DPMAC_CMDID_SET_IRQ 0x010 ++#define DPMAC_CMDID_GET_IRQ 0x011 ++#define DPMAC_CMDID_SET_IRQ_ENABLE 0x012 ++#define DPMAC_CMDID_GET_IRQ_ENABLE 0x013 ++#define DPMAC_CMDID_SET_IRQ_MASK 0x014 ++#define DPMAC_CMDID_GET_IRQ_MASK 0x015 ++#define DPMAC_CMDID_GET_IRQ_STATUS 0x016 ++#define DPMAC_CMDID_CLEAR_IRQ_STATUS 0x017 ++ ++#define DPMAC_CMDID_MDIO_READ 0x0c0 ++#define DPMAC_CMDID_MDIO_WRITE 0x0c1 ++#define DPMAC_CMDID_GET_LINK_CFG 0x0c2 ++#define DPMAC_CMDID_SET_LINK_STATE 0x0c3 ++#define DPMAC_CMDID_GET_COUNTER 0x0c4 ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_CMD_CREATE(cmd, cfg) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, cfg->mac_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_CMD_OPEN(cmd, dpmac_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpmac_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, irq_index);\ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, irq_cfg->val);\ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr); \ ++ MC_CMD_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_CMD_GET_IRQ(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_RSP_GET_IRQ(cmd, type, irq_cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr); \ ++ MC_RSP_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, type); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_CMD_SET_IRQ_ENABLE(cmd, irq_index, en) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, en); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_CMD_GET_IRQ_ENABLE(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_RSP_GET_IRQ_ENABLE(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 8, uint8_t, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, mask);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_CMD_GET_IRQ_MASK(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_RSP_GET_IRQ_MASK(cmd, mask) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mask) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_RSP_GET_IRQ_STATUS(cmd, status) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, status) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_RSP_GET_ATTRIBUTES(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, attr->phy_id);\ ++ MC_RSP_OP(cmd, 0, 32, 32, int, attr->id);\ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->version.major);\ ++ MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->version.minor);\ ++ MC_RSP_OP(cmd, 1, 32, 8, enum dpmac_link_type, attr->link_type);\ ++ MC_RSP_OP(cmd, 1, 40, 8, enum dpmac_eth_if, attr->eth_if);\ ++ MC_RSP_OP(cmd, 2, 0, 32, uint32_t, attr->max_rate);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_CMD_MDIO_READ(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, cfg->phy_addr); \ ++ MC_CMD_OP(cmd, 0, 8, 8, uint8_t, cfg->reg); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_RSP_MDIO_READ(cmd, data) \ ++ MC_RSP_OP(cmd, 0, 16, 16, uint16_t, data) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_CMD_MDIO_WRITE(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, cfg->phy_addr); \ ++ MC_CMD_OP(cmd, 0, 8, 8, uint8_t, cfg->reg); \ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->data); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_RSP_GET_LINK_CFG(cmd, cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 64, uint64_t, cfg->options); \ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, cfg->rate); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_CMD_SET_LINK_STATE(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 64, uint64_t, cfg->options); \ ++ MC_CMD_OP(cmd, 1, 0, 32, uint32_t, cfg->rate); \ ++ MC_CMD_OP(cmd, 2, 0, 1, int, cfg->up); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_CMD_GET_COUNTER(cmd, type) \ ++ MC_CMD_OP(cmd, 0, 0, 8, enum dpmac_counter, type) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMAC_RSP_GET_COUNTER(cmd, counter) \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, counter) ++ ++#endif /* _FSL_DPMAC_CMD_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpmcp.h b/drivers/net/dpaa2/mc/fsl_dpmcp.h +new file mode 100644 +index 0000000..80f238e +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpmcp.h +@@ -0,0 +1,332 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPMCP_H ++#define __FSL_DPMCP_H ++ ++/* Data Path Management Command Portal API ++ * Contains initialization APIs and runtime control APIs for DPMCP ++ */ ++ ++struct fsl_mc_io; ++ ++/** ++ * dpmcp_open() - Open a control session for the specified object. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @dpmcp_id: DPMCP unique ID ++ * @token: Returned token; use in subsequent API calls ++ * ++ * This function can be used to open a control session for an ++ * already created object; an object may have been declared in ++ * the DPL or by calling the dpmcp_create function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent commands for ++ * this specific object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmcp_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpmcp_id, ++ uint16_t *token); ++ ++/** ++ * Get portal ID from pool ++ */ ++#define DPMCP_GET_PORTAL_ID_FROM_POOL (-1) ++ ++/** ++ * dpmcp_close() - Close the control session of the object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMCP object ++ * ++ * After this function is called, no further operations are ++ * allowed on the object without opening a new control session. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmcp_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * struct dpmcp_cfg - Structure representing DPMCP configuration ++ * @portal_id: Portal ID; 'DPMCP_GET_PORTAL_ID_FROM_POOL' to get the portal ID ++ * from pool ++ */ ++struct dpmcp_cfg { ++ int portal_id; ++}; ++ ++/** ++ * dpmcp_create() - Create the DPMCP object. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @cfg: Configuration structure ++ * @token: Returned token; use in subsequent API calls ++ * ++ * Create the DPMCP object, allocate required resources and ++ * perform required initialization. ++ * ++ * The object can be created either by declaring it in the ++ * DPL file, or by calling this function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent calls to ++ * this specific object. For objects that are created using the ++ * DPL file, call dpmcp_open function to get an authentication ++ * token first. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmcp_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpmcp_cfg *cfg, ++ uint16_t *token); ++ ++/** ++ * dpmcp_destroy() - Destroy the DPMCP object and release all its resources. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMCP object ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpmcp_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpmcp_reset() - Reset the DPMCP, returns the object to initial state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMCP object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmcp_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * IRQ ++ */ ++ ++/** ++ * IRQ Index ++ */ ++#define DPMCP_IRQ_INDEX 0 ++/** ++ * irq event - Indicates that the link state changed ++ */ ++#define DPMCP_IRQ_EVENT_CMD_DONE 0x00000001 ++ ++/** ++ * struct dpmcp_irq_cfg - IRQ configuration ++ * @addr: Address that must be written to signal a message-based interrupt ++ * @val: Value to write into irq_addr address ++ * @irq_num: A user defined number associated with this IRQ ++ */ ++struct dpmcp_irq_cfg { ++ uint64_t addr; ++ uint32_t val; ++ int irq_num; ++}; ++ ++/** ++ * dpmcp_set_irq() - Set IRQ information for the DPMCP to trigger an interrupt. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMCP object ++ * @irq_index: Identifies the interrupt index to configure ++ * @irq_cfg: IRQ configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmcp_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpmcp_irq_cfg *irq_cfg); ++ ++/** ++ * dpmcp_get_irq() - Get IRQ information from the DPMCP. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMCP object ++ * @irq_index: The interrupt index to configure ++ * @type: Interrupt type: 0 represents message interrupt ++ * type (both irq_addr and irq_val are valid) ++ * @irq_cfg: IRQ attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmcp_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpmcp_irq_cfg *irq_cfg); ++ ++/** ++ * dpmcp_set_irq_enable() - Set overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMCP object ++ * @irq_index: The interrupt index to configure ++ * @en: Interrupt state - enable = 1, disable = 0 ++ * ++ * Allows GPP software to control when interrupts are generated. ++ * Each interrupt can have up to 32 causes. The enable/disable control's the ++ * overall interrupt state. if the interrupt is disabled no causes will cause ++ * an interrupt. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmcp_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en); ++ ++/** ++ * dpmcp_get_irq_enable() - Get overall interrupt state ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMCP object ++ * @irq_index: The interrupt index to configure ++ * @en: Returned interrupt state - enable = 1, disable = 0 ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmcp_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en); ++ ++/** ++ * dpmcp_set_irq_mask() - Set interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMCP object ++ * @irq_index: The interrupt index to configure ++ * @mask: Event mask to trigger interrupt; ++ * each bit: ++ * 0 = ignore event ++ * 1 = consider event for asserting IRQ ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmcp_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask); ++ ++/** ++ * dpmcp_get_irq_mask() - Get interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMCP object ++ * @irq_index: The interrupt index to configure ++ * @mask: Returned event mask to trigger interrupt ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmcp_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask); ++ ++/** ++ * dpmcp_get_irq_status() - Get the current status of any pending interrupts. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMCP object ++ * @irq_index: The interrupt index to configure ++ * @status: Returned interrupts status - one bit per cause: ++ * 0 = no interrupt pending ++ * 1 = interrupt pending ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmcp_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status); ++ ++/** ++ * struct dpmcp_attr - Structure representing DPMCP attributes ++ * @id: DPMCP object ID ++ * @version: DPMCP version ++ */ ++struct dpmcp_attr { ++ int id; ++ /** ++ * struct version - Structure representing DPMCP version ++ * @major: DPMCP major version ++ * @minor: DPMCP minor version ++ */ ++ struct { ++ uint16_t major; ++ uint16_t minor; ++ } version; ++}; ++ ++/** ++ * dpmcp_get_attributes - Retrieve DPMCP attributes. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPMCP object ++ * @attr: Returned object's attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpmcp_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpmcp_attr *attr); ++ ++#endif /* __FSL_DPMCP_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpmcp_cmd.h b/drivers/net/dpaa2/mc/fsl_dpmcp_cmd.h +new file mode 100644 +index 0000000..8f710bd +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpmcp_cmd.h +@@ -0,0 +1,135 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_DPMCP_CMD_H ++#define _FSL_DPMCP_CMD_H ++ ++/* DPMCP Version */ ++#define DPMCP_VER_MAJOR 3 ++#define DPMCP_VER_MINOR 0 ++ ++/* Command IDs */ ++#define DPMCP_CMDID_CLOSE 0x800 ++#define DPMCP_CMDID_OPEN 0x80b ++#define DPMCP_CMDID_CREATE 0x90b ++#define DPMCP_CMDID_DESTROY 0x900 ++ ++#define DPMCP_CMDID_GET_ATTR 0x004 ++#define DPMCP_CMDID_RESET 0x005 ++ ++#define DPMCP_CMDID_SET_IRQ 0x010 ++#define DPMCP_CMDID_GET_IRQ 0x011 ++#define DPMCP_CMDID_SET_IRQ_ENABLE 0x012 ++#define DPMCP_CMDID_GET_IRQ_ENABLE 0x013 ++#define DPMCP_CMDID_SET_IRQ_MASK 0x014 ++#define DPMCP_CMDID_GET_IRQ_MASK 0x015 ++#define DPMCP_CMDID_GET_IRQ_STATUS 0x016 ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMCP_CMD_OPEN(cmd, dpmcp_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpmcp_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMCP_CMD_CREATE(cmd, cfg) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, cfg->portal_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMCP_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, irq_index);\ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, irq_cfg->val);\ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr); \ ++ MC_CMD_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMCP_CMD_GET_IRQ(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMCP_RSP_GET_IRQ(cmd, type, irq_cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr); \ ++ MC_RSP_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, type); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMCP_CMD_SET_IRQ_ENABLE(cmd, irq_index, en) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, en); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMCP_CMD_GET_IRQ_ENABLE(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMCP_RSP_GET_IRQ_ENABLE(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 8, uint8_t, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMCP_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, mask);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMCP_CMD_GET_IRQ_MASK(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMCP_RSP_GET_IRQ_MASK(cmd, mask) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mask) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMCP_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMCP_RSP_GET_IRQ_STATUS(cmd, status) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, status) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMCP_RSP_GET_ATTRIBUTES(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 32, 32, int, attr->id);\ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->version.major);\ ++ MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->version.minor);\ ++} while (0) ++ ++#endif /* _FSL_DPMCP_CMD_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpmng.h b/drivers/net/dpaa2/mc/fsl_dpmng.h +new file mode 100644 +index 0000000..4468dea +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpmng.h +@@ -0,0 +1,74 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPMNG_H ++#define __FSL_DPMNG_H ++ ++/* Management Complex General API ++ * Contains general API for the Management Complex firmware ++ */ ++ ++struct fsl_mc_io; ++ ++/** ++ * Management Complex firmware version information ++ */ ++#define MC_VER_MAJOR 9 ++#define MC_VER_MINOR 0 ++ ++/** ++ * struct mc_versoin ++ * @major: Major version number: incremented on API compatibility changes ++ * @minor: Minor version number: incremented on API additions (that are ++ * backward compatible); reset when major version is incremented ++ * @revision: Internal revision number: incremented on implementation changes ++ * and/or bug fixes that have no impact on API ++ */ ++struct mc_version { ++ uint32_t major; ++ uint32_t minor; ++ uint32_t revision; ++}; ++ ++/** ++ * mc_get_version() - Retrieves the Management Complex firmware ++ * version information ++ * @mc_io: Pointer to opaque I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @mc_ver_info: Returned version information structure ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int mc_get_version(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ struct mc_version *mc_ver_info); ++ ++#endif /* __FSL_DPMNG_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpmng_cmd.h b/drivers/net/dpaa2/mc/fsl_dpmng_cmd.h +new file mode 100644 +index 0000000..c34ca3a +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpmng_cmd.h +@@ -0,0 +1,46 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPMNG_CMD_H ++#define __FSL_DPMNG_CMD_H ++ ++/* Command IDs */ ++#define DPMNG_CMDID_GET_VERSION 0x831 ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPMNG_RSP_GET_VERSION(cmd, mc_ver_info) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mc_ver_info->revision); \ ++ MC_RSP_OP(cmd, 0, 32, 32, uint32_t, mc_ver_info->major); \ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, mc_ver_info->minor); \ ++} while (0) ++ ++#endif /* __FSL_DPMNG_CMD_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpni.h b/drivers/net/dpaa2/mc/fsl_dpni.h +new file mode 100644 +index 0000000..c820086 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpni.h +@@ -0,0 +1,2581 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPNI_H ++#define __FSL_DPNI_H ++ ++#include ++ ++struct fsl_mc_io; ++ ++/** ++ * Data Path Network Interface API ++ * Contains initialization APIs and runtime control APIs for DPNI ++ */ ++ ++/** General DPNI macros */ ++ ++/** ++ * Maximum number of traffic classes ++ */ ++#define DPNI_MAX_TC 8 ++/** ++ * Maximum number of buffer pools per DPNI ++ */ ++#define DPNI_MAX_DPBP 8 ++/** ++ * Maximum number of storage-profiles per DPNI ++ */ ++#define DPNI_MAX_SP 2 ++ ++/** ++ * All traffic classes considered; see dpni_set_rx_flow() ++ */ ++#define DPNI_ALL_TCS (uint8_t)(-1) ++/** ++ * All flows within traffic class considered; see dpni_set_rx_flow() ++ */ ++#define DPNI_ALL_TC_FLOWS (uint16_t)(-1) ++/** ++ * Generate new flow ID; see dpni_set_tx_flow() ++ */ ++#define DPNI_NEW_FLOW_ID (uint16_t)(-1) ++/* use for common tx-conf queue; see dpni_set_tx_conf_() */ ++#define DPNI_COMMON_TX_CONF (uint16_t)(-1) ++ ++/** ++ * dpni_open() - Open a control session for the specified object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @dpni_id: DPNI unique ID ++ * @token: Returned token; use in subsequent API calls ++ * ++ * This function can be used to open a control session for an ++ * already created object; an object may have been declared in ++ * the DPL or by calling the dpni_create() function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent commands for ++ * this specific object. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpni_id, ++ uint16_t *token); ++ ++/** ++ * dpni_close() - Close the control session of the object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * ++ * After this function is called, no further operations are ++ * allowed on the object without opening a new control session. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/* DPNI configuration options */ ++ ++/** ++ * Allow different distribution key profiles for different traffic classes; ++ * if not set, a single key profile is assumed ++ */ ++#define DPNI_OPT_ALLOW_DIST_KEY_PER_TC 0x00000001 ++ ++/** ++ * Disable all non-error transmit confirmation; error frames are reported ++ * back to a common Tx error queue ++ */ ++#define DPNI_OPT_TX_CONF_DISABLED 0x00000002 ++ ++/** ++ * Disable per-sender private Tx confirmation/error queue ++ */ ++#define DPNI_OPT_PRIVATE_TX_CONF_ERROR_DISABLED 0x00000004 ++ ++/** ++ * Support distribution based on hashed key; ++ * allows statistical distribution over receive queues in a traffic class ++ */ ++#define DPNI_OPT_DIST_HASH 0x00000010 ++ ++/** ++ * DEPRECATED - if this flag is selected and and all new 'max_fs_entries' are ++ * '0' then backward compatibility is preserved; ++ * Support distribution based on flow steering; ++ * allows explicit control of distribution over receive queues in a traffic ++ * class ++ */ ++#define DPNI_OPT_DIST_FS 0x00000020 ++ ++/** ++ * Unicast filtering support ++ */ ++#define DPNI_OPT_UNICAST_FILTER 0x00000080 ++/** ++ * Multicast filtering support ++ */ ++#define DPNI_OPT_MULTICAST_FILTER 0x00000100 ++/** ++ * VLAN filtering support ++ */ ++#define DPNI_OPT_VLAN_FILTER 0x00000200 ++/** ++ * Support IP reassembly on received packets ++ */ ++#define DPNI_OPT_IPR 0x00000800 ++/** ++ * Support IP fragmentation on transmitted packets ++ */ ++#define DPNI_OPT_IPF 0x00001000 ++/** ++ * VLAN manipulation support ++ */ ++#define DPNI_OPT_VLAN_MANIPULATION 0x00010000 ++/** ++ * Support masking of QoS lookup keys ++ */ ++#define DPNI_OPT_QOS_MASK_SUPPORT 0x00020000 ++/** ++ * Support masking of Flow Steering lookup keys ++ */ ++#define DPNI_OPT_FS_MASK_SUPPORT 0x00040000 ++ ++/** ++ * struct dpni_extended_cfg - Structure representing extended DPNI configuration ++ * @tc_cfg: TCs configuration ++ * @ipr_cfg: IP reassembly configuration ++ */ ++struct dpni_extended_cfg { ++ /** ++ * struct tc_cfg - TC configuration ++ * @max_dist: Maximum distribution size for Rx traffic class; ++ * supported values: 1,2,3,4,6,7,8,12,14,16,24,28,32,48,56,64,96, ++ * 112,128,192,224,256,384,448,512,768,896,1024; ++ * value '0' will be treated as '1'. ++ * other unsupported values will be round down to the nearest ++ * supported value. ++ * @max_fs_entries: Maximum FS entries for Rx traffic class; ++ * '0' means no support for this TC; ++ */ ++ struct { ++ uint16_t max_dist; ++ uint16_t max_fs_entries; ++ } tc_cfg[DPNI_MAX_TC]; ++ /** ++ * struct ipr_cfg - Structure representing IP reassembly configuration ++ * @max_reass_frm_size: Maximum size of the reassembled frame ++ * @min_frag_size_ipv4: Minimum fragment size of IPv4 fragments ++ * @min_frag_size_ipv6: Minimum fragment size of IPv6 fragments ++ * @max_open_frames_ipv4: Maximum concurrent IPv4 packets in reassembly ++ * process ++ * @max_open_frames_ipv6: Maximum concurrent IPv6 packets in reassembly ++ * process ++ */ ++ struct { ++ uint16_t max_reass_frm_size; ++ uint16_t min_frag_size_ipv4; ++ uint16_t min_frag_size_ipv6; ++ uint16_t max_open_frames_ipv4; ++ uint16_t max_open_frames_ipv6; ++ } ipr_cfg; ++}; ++ ++/** ++ * dpni_prepare_extended_cfg() - function prepare extended parameters ++ * @cfg: extended structure ++ * @ext_cfg_buf: Zeroed 256 bytes of memory before mapping it to DMA ++ * ++ * This function has to be called before dpni_create() ++ */ ++int dpni_prepare_extended_cfg(const struct dpni_extended_cfg *cfg, ++ uint8_t *ext_cfg_buf); ++ ++/** ++ * struct dpni_cfg - Structure representing DPNI configuration ++ * @mac_addr: Primary MAC address ++ * @adv: Advanced parameters; default is all zeros; ++ * use this structure to change default settings ++ */ ++struct dpni_cfg { ++ uint8_t mac_addr[6]; ++ /** ++ * struct adv - Advanced parameters ++ * @options: Mask of available options; use 'DPNI_OPT_' values ++ * @start_hdr: Selects the packet starting header for parsing; ++ * 'NET_PROT_NONE' is treated as default: 'NET_PROT_ETH' ++ * @max_senders: Maximum number of different senders; used as the number ++ * of dedicated Tx flows; Non-power-of-2 values are rounded ++ * up to the next power-of-2 value as hardware demands it; ++ * '0' will be treated as '1' ++ * @max_tcs: Maximum number of traffic classes (for both Tx and Rx); ++ * '0' will e treated as '1' ++ * @max_unicast_filters: Maximum number of unicast filters; ++ * '0' is treated as '16' ++ * @max_multicast_filters: Maximum number of multicast filters; ++ * '0' is treated as '64' ++ * @max_qos_entries: if 'max_tcs > 1', declares the maximum entries in ++ * the QoS table; '0' is treated as '64' ++ * @max_qos_key_size: Maximum key size for the QoS look-up; ++ * '0' is treated as '24' which is enough for IPv4 ++ * 5-tuple ++ * @max_dist_key_size: Maximum key size for the distribution; ++ * '0' is treated as '24' which is enough for IPv4 5-tuple ++ * @max_policers: Maximum number of policers; ++ * should be between '0' and max_tcs ++ * @max_congestion_ctrl: Maximum number of congestion control groups ++ * (CGs); covers early drop and congestion notification ++ * requirements; ++ * should be between '0' and ('max_tcs' + 'max_senders') ++ * @ext_cfg_iova: I/O virtual address of 256 bytes DMA-able memory ++ * filled with the extended configuration by calling ++ * dpni_prepare_extended_cfg() ++ */ ++ struct { ++ uint32_t options; ++ enum net_prot start_hdr; ++ uint8_t max_senders; ++ uint8_t max_tcs; ++ uint8_t max_unicast_filters; ++ uint8_t max_multicast_filters; ++ uint8_t max_vlan_filters; ++ uint8_t max_qos_entries; ++ uint8_t max_qos_key_size; ++ uint8_t max_dist_key_size; ++ uint8_t max_policers; ++ uint8_t max_congestion_ctrl; ++ uint64_t ext_cfg_iova; ++ } adv; ++}; ++ ++/** ++ * dpni_create() - Create the DPNI object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @cfg: Configuration structure ++ * @token: Returned token; use in subsequent API calls ++ * ++ * Create the DPNI object, allocate required resources and ++ * perform required initialization. ++ * ++ * The object can be created either by declaring it in the ++ * DPL file, or by calling this function. ++ * ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent calls to ++ * this specific object. For objects that are created using the ++ * DPL file, call dpni_open() function to get an authentication ++ * token first. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpni_cfg *cfg, ++ uint16_t *token); ++ ++/** ++ * dpni_destroy() - Destroy the DPNI object and release all its resources. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpni_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * struct dpni_pools_cfg - Structure representing buffer pools configuration ++ * @num_dpbp: Number of DPBPs ++ * @pools: Array of buffer pools parameters; The number of valid entries ++ * must match 'num_dpbp' value ++ */ ++struct dpni_pools_cfg { ++ uint8_t num_dpbp; ++ /** ++ * struct pools - Buffer pools parameters ++ * @dpbp_id: DPBP object ID ++ * @buffer_size: Buffer size ++ * @backup_pool: Backup pool ++ */ ++ struct { ++ int dpbp_id; ++ uint16_t buffer_size; ++ int backup_pool; ++ } pools[DPNI_MAX_DPBP]; ++}; ++ ++/** ++ * dpni_set_pools() - Set buffer pools configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @cfg: Buffer pools configuration ++ * ++ * mandatory for DPNI operation ++ * warning:Allowed only when DPNI is disabled ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_pools(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_pools_cfg *cfg); ++ ++/** ++ * dpni_enable() - Enable the DPNI, allow sending and receiving frames. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpni_disable() - Disable the DPNI, stop sending and receiving frames. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpni_is_enabled() - Check if the DPNI is enabled. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @en: Returns '1' if object is enabled; '0' otherwise ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en); ++ ++/** ++ * dpni_reset() - Reset the DPNI, returns the object to initial state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * DPNI IRQ Index and Events ++ */ ++ ++/** ++ * IRQ index ++ */ ++#define DPNI_IRQ_INDEX 0 ++/** ++ * IRQ event - indicates a change in link state ++ */ ++#define DPNI_IRQ_EVENT_LINK_CHANGED 0x00000001 ++ ++/** ++ * struct dpni_irq_cfg - IRQ configuration ++ * @addr: Address that must be written to signal a message-based interrupt ++ * @val: Value to write into irq_addr address ++ * @irq_num: A user defined number associated with this IRQ ++ */ ++struct dpni_irq_cfg { ++ uint64_t addr; ++ uint32_t val; ++ int irq_num; ++}; ++ ++/** ++ * dpni_set_irq() - Set IRQ information for the DPNI to trigger an interrupt. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @irq_index: Identifies the interrupt index to configure ++ * @irq_cfg: IRQ configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpni_irq_cfg *irq_cfg); ++ ++/** ++ * dpni_get_irq() - Get IRQ information from the DPNI. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @irq_index: The interrupt index to configure ++ * @type: Interrupt type: 0 represents message interrupt ++ * type (both irq_addr and irq_val are valid) ++ * @irq_cfg: IRQ attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpni_irq_cfg *irq_cfg); ++ ++/** ++ * dpni_set_irq_enable() - Set overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @irq_index: The interrupt index to configure ++ * @en: Interrupt state: - enable = 1, disable = 0 ++ * ++ * Allows GPP software to control when interrupts are generated. ++ * Each interrupt can have up to 32 causes. The enable/disable control's the ++ * overall interrupt state. if the interrupt is disabled no causes will cause ++ * an interrupt. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en); ++ ++/** ++ * dpni_get_irq_enable() - Get overall interrupt state ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @irq_index: The interrupt index to configure ++ * @en: Returned interrupt state - enable = 1, disable = 0 ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en); ++ ++/** ++ * dpni_set_irq_mask() - Set interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @irq_index: The interrupt index to configure ++ * @mask: event mask to trigger interrupt; ++ * each bit: ++ * 0 = ignore event ++ * 1 = consider event for asserting IRQ ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask); ++ ++/** ++ * dpni_get_irq_mask() - Get interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @irq_index: The interrupt index to configure ++ * @mask: Returned event mask to trigger interrupt ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask); ++ ++/** ++ * dpni_get_irq_status() - Get the current status of any pending interrupts. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @irq_index: The interrupt index to configure ++ * @status: Returned interrupts status - one bit per cause: ++ * 0 = no interrupt pending ++ * 1 = interrupt pending ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status); ++ ++/** ++ * dpni_clear_irq_status() - Clear a pending interrupt's status ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @irq_index: The interrupt index to configure ++ * @status: bits to clear (W1C) - one bit per cause: ++ * 0 = don't change ++ * 1 = clear status bit ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status); ++ ++/** ++ * struct dpni_attr - Structure representing DPNI attributes ++ * @id: DPNI object ID ++ * @version: DPNI version ++ * @start_hdr: Indicates the packet starting header for parsing ++ * @options: Mask of available options; reflects the value as was given in ++ * object's creation ++ * @max_senders: Maximum number of different senders; used as the number ++ * of dedicated Tx flows; ++ * @max_tcs: Maximum number of traffic classes (for both Tx and Rx) ++ * @max_unicast_filters: Maximum number of unicast filters ++ * @max_multicast_filters: Maximum number of multicast filters ++ * @max_vlan_filters: Maximum number of VLAN filters ++ * @max_qos_entries: if 'max_tcs > 1', declares the maximum entries in QoS table ++ * @max_qos_key_size: Maximum key size for the QoS look-up ++ * @max_dist_key_size: Maximum key size for the distribution look-up ++ * @max_policers: Maximum number of policers; ++ * @max_congestion_ctrl: Maximum number of congestion control groups (CGs); ++ * @ext_cfg_iova: I/O virtual address of 256 bytes DMA-able memory; ++ * call dpni_extract_extended_cfg() to extract the extended configuration ++ */ ++struct dpni_attr { ++ int id; ++ /** ++ * struct version - DPNI version ++ * @major: DPNI major version ++ * @minor: DPNI minor version ++ */ ++ struct { ++ uint16_t major; ++ uint16_t minor; ++ } version; ++ enum net_prot start_hdr; ++ uint32_t options; ++ uint8_t max_senders; ++ uint8_t max_tcs; ++ uint8_t max_unicast_filters; ++ uint8_t max_multicast_filters; ++ uint8_t max_vlan_filters; ++ uint8_t max_qos_entries; ++ uint8_t max_qos_key_size; ++ uint8_t max_dist_key_size; ++ uint8_t max_policers; ++ uint8_t max_congestion_ctrl; ++ uint64_t ext_cfg_iova; ++}; ++ ++/** ++ * dpni_get_attributes() - Retrieve DPNI attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @attr: Object's attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpni_attr *attr); ++ ++/** ++ * dpni_extract_extended_cfg() - extract the extended parameters ++ * @cfg: extended structure ++ * @ext_cfg_buf: 256 bytes of DMA-able memory ++ * ++ * This function has to be called after dpni_get_attributes() ++ */ ++int dpni_extract_extended_cfg(struct dpni_extended_cfg *cfg, ++ const uint8_t *ext_cfg_buf); ++ ++/** ++ * DPNI errors ++ */ ++ ++/** ++ * Extract out of frame header error ++ */ ++#define DPNI_ERROR_EOFHE 0x00020000 ++/** ++ * Frame length error ++ */ ++#define DPNI_ERROR_FLE 0x00002000 ++/** ++ * Frame physical error ++ */ ++#define DPNI_ERROR_FPE 0x00001000 ++/** ++ * Parsing header error ++ */ ++#define DPNI_ERROR_PHE 0x00000020 ++/** ++ * Parser L3 checksum error ++ */ ++#define DPNI_ERROR_L3CE 0x00000004 ++/** ++ * Parser L3 checksum error ++ */ ++#define DPNI_ERROR_L4CE 0x00000001 ++ ++/** ++ * enum dpni_error_action - Defines DPNI behavior for errors ++ * @DPNI_ERROR_ACTION_DISCARD: Discard the frame ++ * @DPNI_ERROR_ACTION_CONTINUE: Continue with the normal flow ++ * @DPNI_ERROR_ACTION_SEND_TO_ERROR_QUEUE: Send the frame to the error queue ++ */ ++enum dpni_error_action { ++ DPNI_ERROR_ACTION_DISCARD = 0, ++ DPNI_ERROR_ACTION_CONTINUE = 1, ++ DPNI_ERROR_ACTION_SEND_TO_ERROR_QUEUE = 2 ++}; ++ ++/** ++ * struct dpni_error_cfg - Structure representing DPNI errors treatment ++ * @errors: Errors mask; use 'DPNI_ERROR__ ++ * @error_action: The desired action for the errors mask ++ * @set_frame_annotation: Set to '1' to mark the errors in frame annotation ++ * status (FAS); relevant only for the non-discard action ++ */ ++struct dpni_error_cfg { ++ uint32_t errors; ++ enum dpni_error_action error_action; ++ int set_frame_annotation; ++}; ++ ++/** ++ * dpni_set_errors_behavior() - Set errors behavior ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @cfg: Errors configuration ++ * ++ * this function may be called numerous times with different ++ * error masks ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_errors_behavior(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpni_error_cfg *cfg); ++ ++/** ++ * DPNI buffer layout modification options ++ */ ++ ++/** ++ * Select to modify the time-stamp setting ++ */ ++#define DPNI_BUF_LAYOUT_OPT_TIMESTAMP 0x00000001 ++/** ++ * Select to modify the parser-result setting; not applicable for Tx ++ */ ++#define DPNI_BUF_LAYOUT_OPT_PARSER_RESULT 0x00000002 ++/** ++ * Select to modify the frame-status setting ++ */ ++#define DPNI_BUF_LAYOUT_OPT_FRAME_STATUS 0x00000004 ++/** ++ * Select to modify the private-data-size setting ++ */ ++#define DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE 0x00000008 ++/** ++ * Select to modify the data-alignment setting ++ */ ++#define DPNI_BUF_LAYOUT_OPT_DATA_ALIGN 0x00000010 ++/** ++ * Select to modify the data-head-room setting ++ */ ++#define DPNI_BUF_LAYOUT_OPT_DATA_HEAD_ROOM 0x00000020 ++/** ++ * Select to modify the data-tail-room setting ++ */ ++#define DPNI_BUF_LAYOUT_OPT_DATA_TAIL_ROOM 0x00000040 ++ ++/** ++ * struct dpni_buffer_layout - Structure representing DPNI buffer layout ++ * @options: Flags representing the suggested modifications to the buffer ++ * layout; Use any combination of 'DPNI_BUF_LAYOUT_OPT_' flags ++ * @pass_timestamp: Pass timestamp value ++ * @pass_parser_result: Pass parser results ++ * @pass_frame_status: Pass frame status ++ * @private_data_size: Size kept for private data (in bytes) ++ * @data_align: Data alignment ++ * @data_head_room: Data head room ++ * @data_tail_room: Data tail room ++ */ ++struct dpni_buffer_layout { ++ uint32_t options; ++ int pass_timestamp; ++ int pass_parser_result; ++ int pass_frame_status; ++ uint16_t private_data_size; ++ uint16_t data_align; ++ uint16_t data_head_room; ++ uint16_t data_tail_room; ++}; ++ ++/** ++ * dpni_get_rx_buffer_layout() - Retrieve Rx buffer layout attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @layout: Returns buffer layout attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_rx_buffer_layout(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpni_buffer_layout *layout); ++ ++/** ++ * dpni_set_rx_buffer_layout() - Set Rx buffer layout configuration. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @layout: Buffer layout configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ * ++ * @warning Allowed only when DPNI is disabled ++ */ ++int dpni_set_rx_buffer_layout(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_buffer_layout *layout); ++ ++/** ++ * dpni_get_tx_buffer_layout() - Retrieve Tx buffer layout attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @layout: Returns buffer layout attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_tx_buffer_layout(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpni_buffer_layout *layout); ++ ++/** ++ * dpni_set_tx_buffer_layout() - Set Tx buffer layout configuration. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @layout: Buffer layout configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ * ++ * @warning Allowed only when DPNI is disabled ++ */ ++int dpni_set_tx_buffer_layout(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_buffer_layout *layout); ++ ++/** ++ * dpni_get_tx_conf_buffer_layout() - Retrieve Tx confirmation buffer layout ++ * attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @layout: Returns buffer layout attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_tx_conf_buffer_layout(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpni_buffer_layout *layout); ++ ++/** ++ * dpni_set_tx_conf_buffer_layout() - Set Tx confirmation buffer layout ++ * configuration. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @layout: Buffer layout configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ * ++ * @warning Allowed only when DPNI is disabled ++ */ ++int dpni_set_tx_conf_buffer_layout(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_buffer_layout *layout); ++ ++/** ++ * dpni_set_l3_chksum_validation() - Enable/disable L3 checksum validation ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @en: Set to '1' to enable; '0' to disable ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_l3_chksum_validation(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en); ++ ++/** ++ * dpni_get_l3_chksum_validation() - Get L3 checksum validation mode ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @en: Returns '1' if enabled; '0' otherwise ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_l3_chksum_validation(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en); ++ ++/** ++ * dpni_set_l4_chksum_validation() - Enable/disable L4 checksum validation ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @en: Set to '1' to enable; '0' to disable ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_l4_chksum_validation(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en); ++ ++/** ++ * dpni_get_l4_chksum_validation() - Get L4 checksum validation mode ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @en: Returns '1' if enabled; '0' otherwise ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_l4_chksum_validation(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en); ++ ++/** ++ * dpni_get_qdid() - Get the Queuing Destination ID (QDID) that should be used ++ * for enqueue operations ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @qdid: Returned virtual QDID value that should be used as an argument ++ * in all enqueue operations ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_qdid(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t *qdid); ++ ++/** ++ * struct dpni_sp_info - Structure representing DPNI storage-profile information ++ * (relevant only for DPNI owned by AIOP) ++ * @spids: array of storage-profiles ++ */ ++struct dpni_sp_info { ++ uint16_t spids[DPNI_MAX_SP]; ++}; ++ ++/** ++ * dpni_get_spids() - Get the AIOP storage profile IDs associated with the DPNI ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @sp_info: Returned AIOP storage-profile information ++ * ++ * Return: '0' on Success; Error code otherwise. ++ * ++ * @warning Only relevant for DPNI that belongs to AIOP container. ++ */ ++int dpni_get_sp_info(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpni_sp_info *sp_info); ++ ++/** ++ * dpni_get_tx_data_offset() - Get the Tx data offset (from start of buffer) ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @data_offset: Tx data offset (from start of buffer) ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_tx_data_offset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t *data_offset); ++ ++/** ++ * enum dpni_counter - DPNI counter types ++ * @DPNI_CNT_ING_FRAME: Counts ingress frames ++ * @DPNI_CNT_ING_BYTE: Counts ingress bytes ++ * @DPNI_CNT_ING_FRAME_DROP: Counts ingress frames dropped due to explicit ++ * 'drop' setting ++ * @DPNI_CNT_ING_FRAME_DISCARD: Counts ingress frames discarded due to errors ++ * @DPNI_CNT_ING_MCAST_FRAME: Counts ingress multicast frames ++ * @DPNI_CNT_ING_MCAST_BYTE: Counts ingress multicast bytes ++ * @DPNI_CNT_ING_BCAST_FRAME: Counts ingress broadcast frames ++ * @DPNI_CNT_ING_BCAST_BYTES: Counts ingress broadcast bytes ++ * @DPNI_CNT_EGR_FRAME: Counts egress frames ++ * @DPNI_CNT_EGR_BYTE: Counts egress bytes ++ * @DPNI_CNT_EGR_FRAME_DISCARD: Counts egress frames discarded due to errors ++ */ ++enum dpni_counter { ++ DPNI_CNT_ING_FRAME = 0x0, ++ DPNI_CNT_ING_BYTE = 0x1, ++ DPNI_CNT_ING_FRAME_DROP = 0x2, ++ DPNI_CNT_ING_FRAME_DISCARD = 0x3, ++ DPNI_CNT_ING_MCAST_FRAME = 0x4, ++ DPNI_CNT_ING_MCAST_BYTE = 0x5, ++ DPNI_CNT_ING_BCAST_FRAME = 0x6, ++ DPNI_CNT_ING_BCAST_BYTES = 0x7, ++ DPNI_CNT_EGR_FRAME = 0x8, ++ DPNI_CNT_EGR_BYTE = 0x9, ++ DPNI_CNT_EGR_FRAME_DISCARD = 0xa ++}; ++ ++/** ++ * dpni_get_counter() - Read a specific DPNI counter ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @counter: The requested counter ++ * @value: Returned counter's current value ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_counter(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ enum dpni_counter counter, ++ uint64_t *value); ++ ++/** ++ * dpni_set_counter() - Set (or clear) a specific DPNI counter ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @counter: The requested counter ++ * @value: New counter value; typically pass '0' for resetting ++ * the counter. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_counter(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ enum dpni_counter counter, ++ uint64_t value); ++ ++/** ++ * Enable auto-negotiation ++ */ ++#define DPNI_LINK_OPT_AUTONEG 0x0000000000000001ULL ++/** ++ * Enable half-duplex mode ++ */ ++#define DPNI_LINK_OPT_HALF_DUPLEX 0x0000000000000002ULL ++/** ++ * Enable pause frames ++ */ ++#define DPNI_LINK_OPT_PAUSE 0x0000000000000004ULL ++/** ++ * Enable a-symmetric pause frames ++ */ ++#define DPNI_LINK_OPT_ASYM_PAUSE 0x0000000000000008ULL ++ ++/** ++ * struct - Structure representing DPNI link configuration ++ * @rate: Rate ++ * @options: Mask of available options; use 'DPNI_LINK_OPT_' values ++ */ ++struct dpni_link_cfg { ++ uint32_t rate; ++ uint64_t options; ++}; ++ ++/** ++ * dpni_set_link_cfg() - set the link configuration. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @cfg: Link configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_link_cfg(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_link_cfg *cfg); ++ ++/** ++ * struct dpni_link_state - Structure representing DPNI link state ++ * @rate: Rate ++ * @options: Mask of available options; use 'DPNI_LINK_OPT_' values ++ * @up: Link state; '0' for down, '1' for up ++ */ ++struct dpni_link_state { ++ uint32_t rate; ++ uint64_t options; ++ int up; ++}; ++ ++/** ++ * dpni_get_link_state() - Return the link state (either up or down) ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @state: Returned link state; ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_link_state(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpni_link_state *state); ++ ++/** ++ * struct dpni_tx_shaping - Structure representing DPNI tx shaping configuration ++ * @rate_limit: rate in Mbps ++ * @max_burst_size: burst size in bytes (up to 64KB) ++ */ ++struct dpni_tx_shaping_cfg { ++ uint32_t rate_limit; ++ uint16_t max_burst_size; ++}; ++ ++/** ++ * dpni_set_tx_shaping() - Set the transmit shaping ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @tx_shaper: tx shaping configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_tx_shaping(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_tx_shaping_cfg *tx_shaper); ++ ++/** ++ * dpni_set_max_frame_length() - Set the maximum received frame length. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @max_frame_length: Maximum received frame length (in ++ * bytes); frame is discarded if its ++ * length exceeds this value ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_max_frame_length(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t max_frame_length); ++ ++/** ++ * dpni_get_max_frame_length() - Get the maximum received frame length. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @max_frame_length: Maximum received frame length (in ++ * bytes); frame is discarded if its ++ * length exceeds this value ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_max_frame_length(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t *max_frame_length); ++ ++/** ++ * dpni_set_mtu() - Set the MTU for the interface. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @mtu: MTU length (in bytes) ++ * ++ * MTU determines the maximum fragment size for performing IP ++ * fragmentation on egress packets. ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_mtu(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t mtu); ++ ++/** ++ * dpni_get_mtu() - Get the MTU. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @mtu: Returned MTU length (in bytes) ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_mtu(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t *mtu); ++ ++/** ++ * dpni_set_multicast_promisc() - Enable/disable multicast promiscuous mode ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @en: Set to '1' to enable; '0' to disable ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_multicast_promisc(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en); ++ ++/** ++ * dpni_get_multicast_promisc() - Get multicast promiscuous mode ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @en: Returns '1' if enabled; '0' otherwise ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_multicast_promisc(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en); ++ ++/** ++ * dpni_set_unicast_promisc() - Enable/disable unicast promiscuous mode ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @en: Set to '1' to enable; '0' to disable ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_unicast_promisc(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en); ++ ++/** ++ * dpni_get_unicast_promisc() - Get unicast promiscuous mode ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @en: Returns '1' if enabled; '0' otherwise ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_unicast_promisc(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en); ++ ++/** ++ * dpni_set_primary_mac_addr() - Set the primary MAC address ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @mac_addr: MAC address to set as primary address ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_primary_mac_addr(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const uint8_t mac_addr[6]); ++ ++/** ++ * dpni_get_primary_mac_addr() - Get the primary MAC address ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @mac_addr: Returned MAC address ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_primary_mac_addr(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t mac_addr[6]); ++ ++/** ++ * dpni_add_mac_addr() - Add MAC address filter ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @mac_addr: MAC address to add ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_add_mac_addr(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const uint8_t mac_addr[6]); ++ ++/** ++ * dpni_remove_mac_addr() - Remove MAC address filter ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @mac_addr: MAC address to remove ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_remove_mac_addr(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const uint8_t mac_addr[6]); ++ ++/** ++ * dpni_clear_mac_filters() - Clear all unicast and/or multicast MAC filters ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @unicast: Set to '1' to clear unicast addresses ++ * @multicast: Set to '1' to clear multicast addresses ++ * ++ * The primary MAC address is not cleared by this operation. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_clear_mac_filters(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int unicast, ++ int multicast); ++ ++/** ++ * dpni_set_vlan_filters() - Enable/disable VLAN filtering mode ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @en: Set to '1' to enable; '0' to disable ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_vlan_filters(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en); ++ ++/** ++ * dpni_add_vlan_id() - Add VLAN ID filter ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @vlan_id: VLAN ID to add ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_add_vlan_id(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id); ++ ++/** ++ * dpni_remove_vlan_id() - Remove VLAN ID filter ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @vlan_id: VLAN ID to remove ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_remove_vlan_id(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id); ++ ++/** ++ * dpni_clear_vlan_filters() - Clear all VLAN filters ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_clear_vlan_filters(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * enum dpni_tx_schedule_mode - DPNI Tx scheduling mode ++ * @DPNI_TX_SCHED_STRICT_PRIORITY: strict priority ++ * @DPNI_TX_SCHED_WEIGHTED: weighted based scheduling ++ */ ++enum dpni_tx_schedule_mode { ++ DPNI_TX_SCHED_STRICT_PRIORITY, ++ DPNI_TX_SCHED_WEIGHTED, ++}; ++ ++/** ++ * struct dpni_tx_schedule_cfg - Structure representing Tx ++ * scheduling configuration ++ * @mode: scheduling mode ++ * @delta_bandwidth: Bandwidth represented in weights from 100 to 10000; ++ * not applicable for 'strict-priority' mode; ++ */ ++struct dpni_tx_schedule_cfg { ++ enum dpni_tx_schedule_mode mode; ++ uint16_t delta_bandwidth; ++}; ++ ++/** ++ * struct dpni_tx_selection_cfg - Structure representing transmission ++ * selection configuration ++ * @tc_sched: an array of traffic-classes ++ */ ++struct dpni_tx_selection_cfg { ++ struct dpni_tx_schedule_cfg tc_sched[DPNI_MAX_TC]; ++}; ++ ++/** ++ * dpni_set_tx_selection() - Set transmission selection configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @cfg: transmission selection configuration ++ * ++ * warning: Allowed only when DPNI is disabled ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_tx_selection(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_tx_selection_cfg *cfg); ++ ++/** ++ * enum dpni_dist_mode - DPNI distribution mode ++ * @DPNI_DIST_MODE_NONE: No distribution ++ * @DPNI_DIST_MODE_HASH: Use hash distribution; only relevant if ++ * the 'DPNI_OPT_DIST_HASH' option was set at DPNI creation ++ * @DPNI_DIST_MODE_FS: Use explicit flow steering; only relevant if ++ * the 'DPNI_OPT_DIST_FS' option was set at DPNI creation ++ */ ++enum dpni_dist_mode { ++ DPNI_DIST_MODE_NONE = 0, ++ DPNI_DIST_MODE_HASH = 1, ++ DPNI_DIST_MODE_FS = 2 ++}; ++ ++/** ++ * enum dpni_fs_miss_action - DPNI Flow Steering miss action ++ * @DPNI_FS_MISS_DROP: In case of no-match, drop the frame ++ * @DPNI_FS_MISS_EXPLICIT_FLOWID: In case of no-match, use explicit flow-id ++ * @DPNI_FS_MISS_HASH: In case of no-match, distribute using hash ++ */ ++enum dpni_fs_miss_action { ++ DPNI_FS_MISS_DROP = 0, ++ DPNI_FS_MISS_EXPLICIT_FLOWID = 1, ++ DPNI_FS_MISS_HASH = 2 ++}; ++ ++/** ++ * struct dpni_fs_tbl_cfg - Flow Steering table configuration ++ * @miss_action: Miss action selection ++ * @default_flow_id: Used when 'miss_action = DPNI_FS_MISS_EXPLICIT_FLOWID' ++ */ ++struct dpni_fs_tbl_cfg { ++ enum dpni_fs_miss_action miss_action; ++ uint16_t default_flow_id; ++}; ++ ++/** ++ * dpni_prepare_key_cfg() - function prepare extract parameters ++ * @cfg: defining a full Key Generation profile (rule) ++ * @key_cfg_buf: Zeroed 256 bytes of memory before mapping it to DMA ++ * ++ * This function has to be called before the following functions: ++ * - dpni_set_rx_tc_dist() ++ * - dpni_set_qos_table() ++ */ ++int dpni_prepare_key_cfg(const struct dpkg_profile_cfg *cfg, ++ uint8_t *key_cfg_buf); ++ ++/** ++ * struct dpni_rx_tc_dist_cfg - Rx traffic class distribution configuration ++ * @dist_size: Set the distribution size; ++ * supported values: 1,2,3,4,6,7,8,12,14,16,24,28,32,48,56,64,96, ++ * 112,128,192,224,256,384,448,512,768,896,1024 ++ * @dist_mode: Distribution mode ++ * @key_cfg_iova: I/O virtual address of 256 bytes DMA-able memory filled with ++ * the extractions to be used for the distribution key by calling ++ * dpni_prepare_key_cfg() relevant only when ++ * 'dist_mode != DPNI_DIST_MODE_NONE', otherwise it can be '0' ++ * @fs_cfg: Flow Steering table configuration; only relevant if ++ * 'dist_mode = DPNI_DIST_MODE_FS' ++ */ ++struct dpni_rx_tc_dist_cfg { ++ uint16_t dist_size; ++ enum dpni_dist_mode dist_mode; ++ uint64_t key_cfg_iova; ++ struct dpni_fs_tbl_cfg fs_cfg; ++}; ++ ++/** ++ * dpni_set_rx_tc_dist() - Set Rx traffic class distribution configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @tc_id: Traffic class selection (0-7) ++ * @cfg: Traffic class distribution configuration ++ * ++ * warning: if 'dist_mode != DPNI_DIST_MODE_NONE', call dpni_prepare_key_cfg() ++ * first to prepare the key_cfg_iova parameter ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpni_set_rx_tc_dist(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ const struct dpni_rx_tc_dist_cfg *cfg); ++ ++/** ++ * Set to select color aware mode (otherwise - color blind) ++ */ ++#define DPNI_POLICER_OPT_COLOR_AWARE 0x00000001 ++/** ++ * Set to discard frame with RED color ++ */ ++#define DPNI_POLICER_OPT_DISCARD_RED 0x00000002 ++ ++/** ++ * enum dpni_policer_mode - selecting the policer mode ++ * @DPNI_POLICER_MODE_NONE: Policer is disabled ++ * @DPNI_POLICER_MODE_PASS_THROUGH: Policer pass through ++ * @DPNI_POLICER_MODE_RFC_2698: Policer algorithm RFC 2698 ++ * @DPNI_POLICER_MODE_RFC_4115: Policer algorithm RFC 4115 ++ */ ++enum dpni_policer_mode { ++ DPNI_POLICER_MODE_NONE = 0, ++ DPNI_POLICER_MODE_PASS_THROUGH, ++ DPNI_POLICER_MODE_RFC_2698, ++ DPNI_POLICER_MODE_RFC_4115 ++}; ++ ++/** ++ * enum dpni_policer_unit - DPNI policer units ++ * @DPNI_POLICER_UNIT_BYTES: bytes units ++ * @DPNI_POLICER_UNIT_FRAMES: frames units ++ */ ++enum dpni_policer_unit { ++ DPNI_POLICER_UNIT_BYTES = 0, ++ DPNI_POLICER_UNIT_FRAMES ++}; ++ ++/** ++ * enum dpni_policer_color - selecting the policer color ++ * @DPNI_POLICER_COLOR_GREEN: Green color ++ * @DPNI_POLICER_COLOR_YELLOW: Yellow color ++ * @DPNI_POLICER_COLOR_RED: Red color ++ */ ++enum dpni_policer_color { ++ DPNI_POLICER_COLOR_GREEN = 0, ++ DPNI_POLICER_COLOR_YELLOW, ++ DPNI_POLICER_COLOR_RED ++}; ++ ++/** ++ * struct dpni_rx_tc_policing_cfg - Policer configuration ++ * @options: Mask of available options; use 'DPNI_POLICER_OPT_' values ++ * @mode: policer mode ++ * @default_color: For pass-through mode the policer re-colors with this ++ * color any incoming packets. For Color aware non-pass-through mode: ++ * policer re-colors with this color all packets with FD[DROPP]>2. ++ * @units: Bytes or Packets ++ * @cir: Committed information rate (CIR) in Kbps or packets/second ++ * @cbs: Committed burst size (CBS) in bytes or packets ++ * @eir: Peak information rate (PIR, rfc2698) in Kbps or packets/second ++ * Excess information rate (EIR, rfc4115) in Kbps or packets/second ++ * @ebs: Peak burst size (PBS, rfc2698) in bytes or packets ++ * Excess burst size (EBS, rfc4115) in bytes or packets ++ */ ++struct dpni_rx_tc_policing_cfg { ++ uint32_t options; ++ enum dpni_policer_mode mode; ++ enum dpni_policer_unit units; ++ enum dpni_policer_color default_color; ++ uint32_t cir; ++ uint32_t cbs; ++ uint32_t eir; ++ uint32_t ebs; ++}; ++ ++/** ++ * dpni_set_rx_tc_policing() - Set Rx traffic class policing configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @tc_id: Traffic class selection (0-7) ++ * @cfg: Traffic class policing configuration ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpni_set_rx_tc_policing(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ const struct dpni_rx_tc_policing_cfg *cfg); ++ ++/** ++ * dpni_get_rx_tc_policing() - Get Rx traffic class policing configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @tc_id: Traffic class selection (0-7) ++ * @cfg: Traffic class policing configuration ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpni_get_rx_tc_policing(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ struct dpni_rx_tc_policing_cfg *cfg); ++ ++/** ++ * enum dpni_congestion_unit - DPNI congestion units ++ * @DPNI_CONGESTION_UNIT_BYTES: bytes units ++ * @DPNI_CONGESTION_UNIT_FRAMES: frames units ++ */ ++enum dpni_congestion_unit { ++ DPNI_CONGESTION_UNIT_BYTES = 0, ++ DPNI_CONGESTION_UNIT_FRAMES ++}; ++ ++/** ++ * enum dpni_early_drop_mode - DPNI early drop mode ++ * @DPNI_EARLY_DROP_MODE_NONE: early drop is disabled ++ * @DPNI_EARLY_DROP_MODE_TAIL: early drop in taildrop mode ++ * @DPNI_EARLY_DROP_MODE_WRED: early drop in WRED mode ++ */ ++enum dpni_early_drop_mode { ++ DPNI_EARLY_DROP_MODE_NONE = 0, ++ DPNI_EARLY_DROP_MODE_TAIL, ++ DPNI_EARLY_DROP_MODE_WRED ++}; ++ ++/** ++ * struct dpni_wred_cfg - WRED configuration ++ * @max_threshold: maximum threshold that packets may be discarded. Above this ++ * threshold all packets are discarded; must be less than 2^39; ++ * approximated to be expressed as (x+256)*2^(y-1) due to HW ++ * implementation. ++ * @min_threshold: minimum threshold that packets may be discarded at ++ * @drop_probability: probability that a packet will be discarded (1-100, ++ * associated with the max_threshold). ++ */ ++struct dpni_wred_cfg { ++ uint64_t max_threshold; ++ uint64_t min_threshold; ++ uint8_t drop_probability; ++}; ++ ++/** ++ * struct dpni_early_drop_cfg - early-drop configuration ++ * @mode: drop mode ++ * @units: units type ++ * @green: WRED - 'green' configuration ++ * @yellow: WRED - 'yellow' configuration ++ * @red: WRED - 'red' configuration ++ * @tail_drop_threshold: tail drop threshold ++ */ ++struct dpni_early_drop_cfg { ++ enum dpni_early_drop_mode mode; ++ enum dpni_congestion_unit units; ++ ++ struct dpni_wred_cfg green; ++ struct dpni_wred_cfg yellow; ++ struct dpni_wred_cfg red; ++ ++ uint32_t tail_drop_threshold; ++}; ++ ++/** ++ * dpni_prepare_early_drop() - prepare an early drop. ++ * @cfg: Early-drop configuration ++ * @early_drop_buf: Zeroed 256 bytes of memory before mapping it to DMA ++ * ++ * This function has to be called before dpni_set_rx_tc_early_drop or ++ * dpni_set_tx_tc_early_drop ++ * ++ */ ++void dpni_prepare_early_drop(const struct dpni_early_drop_cfg *cfg, ++ uint8_t *early_drop_buf); ++ ++/** ++ * dpni_extract_early_drop() - extract the early drop configuration. ++ * @cfg: Early-drop configuration ++ * @early_drop_buf: Zeroed 256 bytes of memory before mapping it to DMA ++ * ++ * This function has to be called after dpni_get_rx_tc_early_drop or ++ * dpni_get_tx_tc_early_drop ++ * ++ */ ++void dpni_extract_early_drop(struct dpni_early_drop_cfg *cfg, ++ const uint8_t *early_drop_buf); ++ ++/** ++ * dpni_set_rx_tc_early_drop() - Set Rx traffic class early-drop configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @tc_id: Traffic class selection (0-7) ++ * @early_drop_iova: I/O virtual address of 256 bytes DMA-able memory filled ++ * with the early-drop configuration by calling dpni_prepare_early_drop() ++ * ++ * warning: Before calling this function, call dpni_prepare_early_drop() to ++ * prepare the early_drop_iova parameter ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpni_set_rx_tc_early_drop(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ uint64_t early_drop_iova); ++ ++/** ++ * dpni_get_rx_tc_early_drop() - Get Rx traffic class early-drop configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @tc_id: Traffic class selection (0-7) ++ * @early_drop_iova: I/O virtual address of 256 bytes DMA-able memory ++ * ++ * warning: After calling this function, call dpni_extract_early_drop() to ++ * get the early drop configuration ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpni_get_rx_tc_early_drop(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ uint64_t early_drop_iova); ++ ++/** ++ * dpni_set_tx_tc_early_drop() - Set Tx traffic class early-drop configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @tc_id: Traffic class selection (0-7) ++ * @early_drop_iova: I/O virtual address of 256 bytes DMA-able memory filled ++ * with the early-drop configuration by calling dpni_prepare_early_drop() ++ * ++ * warning: Before calling this function, call dpni_prepare_early_drop() to ++ * prepare the early_drop_iova parameter ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpni_set_tx_tc_early_drop(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ uint64_t early_drop_iova); ++ ++/** ++ * dpni_get_tx_tc_early_drop() - Get Tx traffic class early-drop configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @tc_id: Traffic class selection (0-7) ++ * @early_drop_iova: I/O virtual address of 256 bytes DMA-able memory ++ * ++ * warning: After calling this function, call dpni_extract_early_drop() to ++ * get the early drop configuration ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpni_get_tx_tc_early_drop(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ uint64_t early_drop_iova); ++ ++/** ++ * enum dpni_dest - DPNI destination types ++ * @DPNI_DEST_NONE: Unassigned destination; The queue is set in parked mode and ++ * does not generate FQDAN notifications; user is expected to ++ * dequeue from the queue based on polling or other user-defined ++ * method ++ * @DPNI_DEST_DPIO: The queue is set in schedule mode and generates FQDAN ++ * notifications to the specified DPIO; user is expected to dequeue ++ * from the queue only after notification is received ++ * @DPNI_DEST_DPCON: The queue is set in schedule mode and does not generate ++ * FQDAN notifications, but is connected to the specified DPCON ++ * object; user is expected to dequeue from the DPCON channel ++ */ ++enum dpni_dest { ++ DPNI_DEST_NONE = 0, ++ DPNI_DEST_DPIO = 1, ++ DPNI_DEST_DPCON = 2 ++}; ++ ++/** ++ * struct dpni_dest_cfg - Structure representing DPNI destination parameters ++ * @dest_type: Destination type ++ * @dest_id: Either DPIO ID or DPCON ID, depending on the destination type ++ * @priority: Priority selection within the DPIO or DPCON channel; valid values ++ * are 0-1 or 0-7, depending on the number of priorities in that ++ * channel; not relevant for 'DPNI_DEST_NONE' option ++ */ ++struct dpni_dest_cfg { ++ enum dpni_dest dest_type; ++ int dest_id; ++ uint8_t priority; ++}; ++ ++/* DPNI congestion options */ ++ ++/** ++ * CSCN message is written to message_iova once entering a ++ * congestion state (see 'threshold_entry') ++ */ ++#define DPNI_CONG_OPT_WRITE_MEM_ON_ENTER 0x00000001 ++/** ++ * CSCN message is written to message_iova once exiting a ++ * congestion state (see 'threshold_exit') ++ */ ++#define DPNI_CONG_OPT_WRITE_MEM_ON_EXIT 0x00000002 ++/** ++ * CSCN write will attempt to allocate into a cache (coherent write); ++ * valid only if 'DPNI_CONG_OPT_WRITE_MEM_' is selected ++ */ ++#define DPNI_CONG_OPT_COHERENT_WRITE 0x00000004 ++/** ++ * if 'dest_cfg.dest_type != DPNI_DEST_NONE' CSCN message is sent to ++ * DPIO/DPCON's WQ channel once entering a congestion state ++ * (see 'threshold_entry') ++ */ ++#define DPNI_CONG_OPT_NOTIFY_DEST_ON_ENTER 0x00000008 ++/** ++ * if 'dest_cfg.dest_type != DPNI_DEST_NONE' CSCN message is sent to ++ * DPIO/DPCON's WQ channel once exiting a congestion state ++ * (see 'threshold_exit') ++ */ ++#define DPNI_CONG_OPT_NOTIFY_DEST_ON_EXIT 0x00000010 ++/** ++ * if 'dest_cfg.dest_type != DPNI_DEST_NONE' when the CSCN is written to the ++ * sw-portal's DQRR, the DQRI interrupt is asserted immediately (if enabled) ++ */ ++#define DPNI_CONG_OPT_INTR_COALESCING_DISABLED 0x00000020 ++ ++/** ++ * struct dpni_congestion_notification_cfg - congestion notification ++ * configuration ++ * @units: units type ++ * @threshold_entry: above this threshold we enter a congestion state. ++ * set it to '0' to disable it ++ * @threshold_exit: below this threshold we exit the congestion state. ++ * @message_ctx: The context that will be part of the CSCN message ++ * @message_iova: I/O virtual address (must be in DMA-able memory), ++ * must be 16B aligned; valid only if 'DPNI_CONG_OPT_WRITE_MEM_' is ++ * contained in 'options' ++ * @dest_cfg: CSCN can be send to either DPIO or DPCON WQ channel ++ * @options: Mask of available options; use 'DPNI_CONG_OPT_' values ++ */ ++ ++struct dpni_congestion_notification_cfg { ++ enum dpni_congestion_unit units; ++ uint32_t threshold_entry; ++ uint32_t threshold_exit; ++ uint64_t message_ctx; ++ uint64_t message_iova; ++ struct dpni_dest_cfg dest_cfg; ++ uint16_t options; ++}; ++ ++/** ++ * dpni_set_rx_tc_congestion_notification() - Set Rx traffic class congestion ++ * notification configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @tc_id: Traffic class selection (0-7) ++ * @cfg: congestion notification configuration ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpni_set_rx_tc_congestion_notification(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ const struct dpni_congestion_notification_cfg *cfg); ++ ++/** ++ * dpni_get_rx_tc_congestion_notification() - Get Rx traffic class congestion ++ * notification configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @tc_id: Traffic class selection (0-7) ++ * @cfg: congestion notification configuration ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpni_get_rx_tc_congestion_notification(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ struct dpni_congestion_notification_cfg *cfg); ++ ++/** ++ * dpni_set_tx_tc_congestion_notification() - Set Tx traffic class congestion ++ * notification configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @tc_id: Traffic class selection (0-7) ++ * @cfg: congestion notification configuration ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpni_set_tx_tc_congestion_notification(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ const struct dpni_congestion_notification_cfg *cfg); ++ ++/** ++ * dpni_get_tx_tc_congestion_notification() - Get Tx traffic class congestion ++ * notification configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @tc_id: Traffic class selection (0-7) ++ * @cfg: congestion notification configuration ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpni_get_tx_tc_congestion_notification(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ struct dpni_congestion_notification_cfg *cfg); ++ ++/** ++ * enum dpni_flc_type - DPNI FLC types ++ * @DPNI_FLC_USER_DEFINED: select the FLC to be used for user defined value ++ * @DPNI_FLC_STASH: select the FLC to be used for stash control ++ */ ++enum dpni_flc_type { ++ DPNI_FLC_USER_DEFINED = 0, ++ DPNI_FLC_STASH = 1, ++}; ++ ++/** ++ * enum dpni_stash_size - DPNI FLC stashing size ++ * @DPNI_STASH_SIZE_0B: no stash ++ * @DPNI_STASH_SIZE_64B: stashes 64 bytes ++ * @DPNI_STASH_SIZE_128B: stashes 128 bytes ++ * @DPNI_STASH_SIZE_192B: stashes 192 bytes ++ */ ++enum dpni_stash_size { ++ DPNI_STASH_SIZE_0B = 0, ++ DPNI_STASH_SIZE_64B = 1, ++ DPNI_STASH_SIZE_128B = 2, ++ DPNI_STASH_SIZE_192B = 3, ++}; ++ ++/* DPNI FLC stash options */ ++ ++/** ++ * stashes the whole annotation area (up to 192 bytes) ++ */ ++#define DPNI_FLC_STASH_FRAME_ANNOTATION 0x00000001 ++ ++/** ++ * struct dpni_flc_cfg - Structure representing DPNI FLC configuration ++ * @flc_type: FLC type ++ * @options: Mask of available options; ++ * use 'DPNI_FLC_STASH_' values ++ * @frame_data_size: Size of frame data to be stashed ++ * @flow_context_size: Size of flow context to be stashed ++ * @flow_context: 1. In case flc_type is 'DPNI_FLC_USER_DEFINED': ++ * this value will be provided in the frame descriptor ++ * (FD[FLC]) ++ * 2. In case flc_type is 'DPNI_FLC_STASH': ++ * this value will be I/O virtual address of the ++ * flow-context; ++ * Must be cacheline-aligned and DMA-able memory ++ */ ++struct dpni_flc_cfg { ++ enum dpni_flc_type flc_type; ++ uint32_t options; ++ enum dpni_stash_size frame_data_size; ++ enum dpni_stash_size flow_context_size; ++ uint64_t flow_context; ++}; ++ ++/** ++ * DPNI queue modification options ++ */ ++ ++/** ++ * Select to modify the user's context associated with the queue ++ */ ++#define DPNI_QUEUE_OPT_USER_CTX 0x00000001 ++/** ++ * Select to modify the queue's destination ++ */ ++#define DPNI_QUEUE_OPT_DEST 0x00000002 ++/** Select to modify the flow-context parameters; ++ * not applicable for Tx-conf/Err queues as the FD comes from the user ++ */ ++#define DPNI_QUEUE_OPT_FLC 0x00000004 ++/** ++ * Select to modify the queue's order preservation ++ */ ++#define DPNI_QUEUE_OPT_ORDER_PRESERVATION 0x00000008 ++/* Select to modify the queue's tail-drop threshold */ ++#define DPNI_QUEUE_OPT_TAILDROP_THRESHOLD 0x00000010 ++ ++/** ++ * struct dpni_queue_cfg - Structure representing queue configuration ++ * @options: Flags representing the suggested modifications to the queue; ++ * Use any combination of 'DPNI_QUEUE_OPT_' flags ++ * @user_ctx: User context value provided in the frame descriptor of each ++ * dequeued frame; valid only if 'DPNI_QUEUE_OPT_USER_CTX' ++ * is contained in 'options' ++ * @dest_cfg: Queue destination parameters; ++ * valid only if 'DPNI_QUEUE_OPT_DEST' is contained in 'options' ++ * @flc_cfg: Flow context configuration; in case the TC's distribution ++ * is either NONE or HASH the FLC's settings of flow#0 are used. ++ * in the case of FS (flow-steering) the flow's FLC settings ++ * are used. ++ * valid only if 'DPNI_QUEUE_OPT_FLC' is contained in 'options' ++ * @order_preservation_en: enable/disable order preservation; ++ * valid only if 'DPNI_QUEUE_OPT_ORDER_PRESERVATION' is contained ++ * in 'options' ++ * @tail_drop_threshold: set the queue's tail drop threshold in bytes; ++ * '0' value disable the threshold; maximum value is 0xE000000; ++ * valid only if 'DPNI_QUEUE_OPT_TAILDROP_THRESHOLD' is contained ++ * in 'options' ++ */ ++struct dpni_queue_cfg { ++ uint32_t options; ++ uint64_t user_ctx; ++ struct dpni_dest_cfg dest_cfg; ++ struct dpni_flc_cfg flc_cfg; ++ int order_preservation_en; ++ uint32_t tail_drop_threshold; ++}; ++ ++/** ++ * struct dpni_queue_attr - Structure representing queue attributes ++ * @user_ctx: User context value provided in the frame descriptor of each ++ * dequeued frame ++ * @dest_cfg: Queue destination configuration ++ * @flc_cfg: Flow context configuration ++ * @order_preservation_en: enable/disable order preservation ++ * @tail_drop_threshold: queue's tail drop threshold in bytes; ++ * @fqid: Virtual fqid value to be used for dequeue operations ++ */ ++struct dpni_queue_attr { ++ uint64_t user_ctx; ++ struct dpni_dest_cfg dest_cfg; ++ struct dpni_flc_cfg flc_cfg; ++ int order_preservation_en; ++ uint32_t tail_drop_threshold; ++ ++ uint32_t fqid; ++}; ++ ++/** ++ * DPNI Tx flow modification options ++ */ ++ ++/** ++ * Select to modify the settings for dedicate Tx confirmation/error ++ */ ++#define DPNI_TX_FLOW_OPT_TX_CONF_ERROR 0x00000001 ++/** ++ * Select to modify the L3 checksum generation setting ++ */ ++#define DPNI_TX_FLOW_OPT_L3_CHKSUM_GEN 0x00000010 ++/** ++ * Select to modify the L4 checksum generation setting ++ */ ++#define DPNI_TX_FLOW_OPT_L4_CHKSUM_GEN 0x00000020 ++ ++/** ++ * struct dpni_tx_flow_cfg - Structure representing Tx flow configuration ++ * @options: Flags representing the suggested modifications to the Tx flow; ++ * Use any combination 'DPNI_TX_FLOW_OPT_' flags ++ * @use_common_tx_conf_queue: Set to '1' to use the common (default) Tx ++ * confirmation and error queue; Set to '0' to use the private ++ * Tx confirmation and error queue; valid only if ++ * 'DPNI_OPT_PRIVATE_TX_CONF_ERROR_DISABLED' wasn't set at DPNI creation ++ * and 'DPNI_TX_FLOW_OPT_TX_CONF_ERROR' is contained in 'options' ++ * @l3_chksum_gen: Set to '1' to enable L3 checksum generation; '0' to disable; ++ * valid only if 'DPNI_TX_FLOW_OPT_L3_CHKSUM_GEN' is contained in 'options' ++ * @l4_chksum_gen: Set to '1' to enable L4 checksum generation; '0' to disable; ++ * valid only if 'DPNI_TX_FLOW_OPT_L4_CHKSUM_GEN' is contained in 'options' ++ */ ++struct dpni_tx_flow_cfg { ++ uint32_t options; ++ int use_common_tx_conf_queue; ++ int l3_chksum_gen; ++ int l4_chksum_gen; ++}; ++ ++/** ++ * dpni_set_tx_flow() - Set Tx flow configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @flow_id: Provides (or returns) the sender's flow ID; ++ * for each new sender set (*flow_id) to 'DPNI_NEW_FLOW_ID' to generate ++ * a new flow_id; this ID should be used as the QDBIN argument ++ * in enqueue operations ++ * @cfg: Tx flow configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_tx_flow(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t *flow_id, ++ const struct dpni_tx_flow_cfg *cfg); ++ ++/** ++ * struct dpni_tx_flow_attr - Structure representing Tx flow attributes ++ * @use_common_tx_conf_queue: '1' if using common (default) Tx confirmation and ++ * error queue; '0' if using private Tx confirmation and error queue ++ * @l3_chksum_gen: '1' if L3 checksum generation is enabled; '0' if disabled ++ * @l4_chksum_gen: '1' if L4 checksum generation is enabled; '0' if disabled ++ */ ++struct dpni_tx_flow_attr { ++ int use_common_tx_conf_queue; ++ int l3_chksum_gen; ++ int l4_chksum_gen; ++}; ++ ++/** ++ * dpni_get_tx_flow() - Get Tx flow attributes ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @flow_id: The sender's flow ID, as returned by the ++ * dpni_set_tx_flow() function ++ * @attr: Returned Tx flow attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_tx_flow(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t flow_id, ++ struct dpni_tx_flow_attr *attr); ++ ++/** ++ * struct dpni_tx_conf_cfg - Structure representing Tx conf configuration ++ * @errors_only: Set to '1' to report back only error frames; ++ * Set to '0' to confirm transmission/error for all transmitted frames; ++ * @queue_cfg: Queue configuration ++ */ ++struct dpni_tx_conf_cfg { ++ int errors_only; ++ struct dpni_queue_cfg queue_cfg; ++}; ++ ++/** ++ * dpni_set_tx_conf() - Set Tx confirmation and error queue configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @flow_id: The sender's flow ID, as returned by the ++ * dpni_set_tx_flow() function; ++ * use 'DPNI_COMMON_TX_CONF' for common tx-conf ++ * @cfg: Queue configuration ++ * ++ * If either 'DPNI_OPT_TX_CONF_DISABLED' or ++ * 'DPNI_OPT_PRIVATE_TX_CONF_ERROR_DISABLED' were selected at DPNI creation, ++ * this function can ONLY be used with 'flow_id == DPNI_COMMON_TX_CONF'; ++ * i.e. only serve the common tx-conf-err queue; ++ * if 'DPNI_OPT_TX_CONF_DISABLED' was selected, only error frames are reported ++ * back - successfully transmitted frames are not confirmed. Otherwise, all ++ * transmitted frames are sent for confirmation. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_tx_conf(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t flow_id, ++ const struct dpni_tx_conf_cfg *cfg); ++ ++/** ++ * struct dpni_tx_conf_attr - Structure representing Tx conf attributes ++ * @errors_only: '1' if only error frames are reported back; '0' if all ++ * transmitted frames are confirmed ++ * @queue_attr: Queue attributes ++ */ ++struct dpni_tx_conf_attr { ++ int errors_only; ++ struct dpni_queue_attr queue_attr; ++}; ++ ++/** ++ * dpni_get_tx_conf() - Get Tx confirmation and error queue attributes ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @flow_id: The sender's flow ID, as returned by the ++ * dpni_set_tx_flow() function; ++ * use 'DPNI_COMMON_TX_CONF' for common tx-conf ++ * @attr: Returned tx-conf attributes ++ * ++ * If either 'DPNI_OPT_TX_CONF_DISABLED' or ++ * 'DPNI_OPT_PRIVATE_TX_CONF_ERROR_DISABLED' were selected at DPNI creation, ++ * this function can ONLY be used with 'flow_id == DPNI_COMMON_TX_CONF'; ++ * i.e. only serve the common tx-conf-err queue; ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_tx_conf(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t flow_id, ++ struct dpni_tx_conf_attr *attr); ++ ++/** ++ * dpni_set_tx_conf_congestion_notification() - Set Tx conf congestion ++ * notification configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @flow_id: The sender's flow ID, as returned by the ++ * dpni_set_tx_flow() function; ++ * use 'DPNI_COMMON_TX_CONF' for common tx-conf ++ * @cfg: congestion notification configuration ++ * ++ * If either 'DPNI_OPT_TX_CONF_DISABLED' or ++ * 'DPNI_OPT_PRIVATE_TX_CONF_ERROR_DISABLED' were selected at DPNI creation, ++ * this function can ONLY be used with 'flow_id == DPNI_COMMON_TX_CONF'; ++ * i.e. only serve the common tx-conf-err queue; ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpni_set_tx_conf_congestion_notification(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t flow_id, ++ const struct dpni_congestion_notification_cfg *cfg); ++ ++/** ++ * dpni_get_tx_conf_congestion_notification() - Get Tx conf congestion ++ * notification configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @flow_id: The sender's flow ID, as returned by the ++ * dpni_set_tx_flow() function; ++ * use 'DPNI_COMMON_TX_CONF' for common tx-conf ++ * @cfg: congestion notification ++ * ++ * If either 'DPNI_OPT_TX_CONF_DISABLED' or ++ * 'DPNI_OPT_PRIVATE_TX_CONF_ERROR_DISABLED' were selected at DPNI creation, ++ * this function can ONLY be used with 'flow_id == DPNI_COMMON_TX_CONF'; ++ * i.e. only serve the common tx-conf-err queue; ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpni_get_tx_conf_congestion_notification(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t flow_id, ++ struct dpni_congestion_notification_cfg *cfg); ++ ++/** ++ * dpni_set_tx_conf_revoke() - Tx confirmation revocation ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @revoke: revoke or not ++ * ++ * This function is useful only when 'DPNI_OPT_TX_CONF_DISABLED' is not ++ * selected at DPNI creation. ++ * Calling this function with 'revoke' set to '1' disables all transmit ++ * confirmation (including the private confirmation queues), regardless of ++ * previous settings; Note that in this case, Tx error frames are still ++ * enqueued to the general transmit errors queue. ++ * Calling this function with 'revoke' set to '0' restores the previous ++ * settings for both general and private transmit confirmation. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_tx_conf_revoke(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int revoke); ++ ++/** ++ * dpni_set_rx_flow() - Set Rx flow configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @tc_id: Traffic class selection (0-7); ++ * use 'DPNI_ALL_TCS' to set all TCs and all flows ++ * @flow_id: Rx flow id within the traffic class; use ++ * 'DPNI_ALL_TC_FLOWS' to set all flows within ++ * this tc_id; ignored if tc_id is set to ++ * 'DPNI_ALL_TCS'; ++ * @cfg: Rx flow configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_rx_flow(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ uint16_t flow_id, ++ const struct dpni_queue_cfg *cfg); ++ ++/** ++ * dpni_get_rx_flow() - Get Rx flow attributes ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @tc_id: Traffic class selection (0-7) ++ * @flow_id: Rx flow id within the traffic class ++ * @attr: Returned Rx flow attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_rx_flow(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ uint16_t flow_id, ++ struct dpni_queue_attr *attr); ++ ++/** ++ * dpni_set_rx_err_queue() - Set Rx error queue configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @cfg: Queue configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_rx_err_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_queue_cfg *cfg); ++ ++/** ++ * dpni_get_rx_err_queue() - Get Rx error queue attributes ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @attr: Returned Queue attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_get_rx_err_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpni_queue_attr *attr); ++ ++/** ++ * struct dpni_qos_tbl_cfg - Structure representing QOS table configuration ++ * @key_cfg_iova: I/O virtual address of 256 bytes DMA-able memory filled with ++ * key extractions to be used as the QoS criteria by calling ++ * dpni_prepare_key_cfg() ++ * @discard_on_miss: Set to '1' to discard frames in case of no match (miss); ++ * '0' to use the 'default_tc' in such cases ++ * @default_tc: Used in case of no-match and 'discard_on_miss'= 0 ++ */ ++struct dpni_qos_tbl_cfg { ++ uint64_t key_cfg_iova; ++ int discard_on_miss; ++ uint8_t default_tc; ++}; ++ ++/** ++ * dpni_set_qos_table() - Set QoS mapping table ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @cfg: QoS table configuration ++ * ++ * This function and all QoS-related functions require that ++ *'max_tcs > 1' was set at DPNI creation. ++ * ++ * warning: Before calling this function, call dpni_prepare_key_cfg() to ++ * prepare the key_cfg_iova parameter ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_qos_table(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_qos_tbl_cfg *cfg); ++ ++/** ++ * struct dpni_rule_cfg - Rule configuration for table lookup ++ * @key_iova: I/O virtual address of the key (must be in DMA-able memory) ++ * @mask_iova: I/O virtual address of the mask (must be in DMA-able memory) ++ * @key_size: key and mask size (in bytes) ++ */ ++struct dpni_rule_cfg { ++ uint64_t key_iova; ++ uint64_t mask_iova; ++ uint8_t key_size; ++}; ++ ++/** ++ * dpni_add_qos_entry() - Add QoS mapping entry (to select a traffic class) ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @cfg: QoS rule to add ++ * @tc_id: Traffic class selection (0-7) ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_add_qos_entry(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_rule_cfg *cfg, ++ uint8_t tc_id); ++ ++/** ++ * dpni_remove_qos_entry() - Remove QoS mapping entry ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @cfg: QoS rule to remove ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_remove_qos_entry(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpni_rule_cfg *cfg); ++ ++/** ++ * dpni_clear_qos_table() - Clear all QoS mapping entries ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * ++ * Following this function call, all frames are directed to ++ * the default traffic class (0) ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_clear_qos_table(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpni_add_fs_entry() - Add Flow Steering entry for a specific traffic class ++ * (to select a flow ID) ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @tc_id: Traffic class selection (0-7) ++ * @cfg: Flow steering rule to add ++ * @flow_id: Flow id selection (must be smaller than the ++ * distribution size of the traffic class) ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_add_fs_entry(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ const struct dpni_rule_cfg *cfg, ++ uint16_t flow_id); ++ ++/** ++ * dpni_remove_fs_entry() - Remove Flow Steering entry from a specific ++ * traffic class ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @tc_id: Traffic class selection (0-7) ++ * @cfg: Flow steering rule to remove ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_remove_fs_entry(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id, ++ const struct dpni_rule_cfg *cfg); ++ ++/** ++ * dpni_clear_fs_entries() - Clear all Flow Steering entries of a specific ++ * traffic class ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @tc_id: Traffic class selection (0-7) ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_clear_fs_entries(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t tc_id); ++ ++/** ++ * dpni_set_vlan_insertion() - Enable/disable VLAN insertion for egress frames ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @en: Set to '1' to enable; '0' to disable ++ * ++ * Requires that the 'DPNI_OPT_VLAN_MANIPULATION' option is set ++ * at DPNI creation. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_vlan_insertion(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en); ++ ++/** ++ * dpni_set_vlan_removal() - Enable/disable VLAN removal for ingress frames ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @en: Set to '1' to enable; '0' to disable ++ * ++ * Requires that the 'DPNI_OPT_VLAN_MANIPULATION' option is set ++ * at DPNI creation. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_vlan_removal(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en); ++ ++/** ++ * dpni_set_ipr() - Enable/disable IP reassembly of ingress frames ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @en: Set to '1' to enable; '0' to disable ++ * ++ * Requires that the 'DPNI_OPT_IPR' option is set at DPNI creation. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_ipr(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en); ++ ++/** ++ * dpni_set_ipf() - Enable/disable IP fragmentation of egress frames ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPNI object ++ * @en: Set to '1' to enable; '0' to disable ++ * ++ * Requires that the 'DPNI_OPT_IPF' option is set at DPNI ++ * creation. Fragmentation is performed according to MTU value ++ * set by dpni_set_mtu() function ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpni_set_ipf(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en); ++ ++#endif /* __FSL_DPNI_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpni_cmd.h b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h +new file mode 100644 +index 0000000..c0f8af0 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpni_cmd.h +@@ -0,0 +1,1058 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_DPNI_CMD_H ++#define _FSL_DPNI_CMD_H ++ ++/* DPNI Version */ ++#define DPNI_VER_MAJOR 6 ++#define DPNI_VER_MINOR 0 ++ ++/* Command IDs */ ++#define DPNI_CMDID_OPEN 0x801 ++#define DPNI_CMDID_CLOSE 0x800 ++#define DPNI_CMDID_CREATE 0x901 ++#define DPNI_CMDID_DESTROY 0x900 ++ ++#define DPNI_CMDID_ENABLE 0x002 ++#define DPNI_CMDID_DISABLE 0x003 ++#define DPNI_CMDID_GET_ATTR 0x004 ++#define DPNI_CMDID_RESET 0x005 ++#define DPNI_CMDID_IS_ENABLED 0x006 ++ ++#define DPNI_CMDID_SET_IRQ 0x010 ++#define DPNI_CMDID_GET_IRQ 0x011 ++#define DPNI_CMDID_SET_IRQ_ENABLE 0x012 ++#define DPNI_CMDID_GET_IRQ_ENABLE 0x013 ++#define DPNI_CMDID_SET_IRQ_MASK 0x014 ++#define DPNI_CMDID_GET_IRQ_MASK 0x015 ++#define DPNI_CMDID_GET_IRQ_STATUS 0x016 ++#define DPNI_CMDID_CLEAR_IRQ_STATUS 0x017 ++ ++#define DPNI_CMDID_SET_POOLS 0x200 ++#define DPNI_CMDID_GET_RX_BUFFER_LAYOUT 0x201 ++#define DPNI_CMDID_SET_RX_BUFFER_LAYOUT 0x202 ++#define DPNI_CMDID_GET_TX_BUFFER_LAYOUT 0x203 ++#define DPNI_CMDID_SET_TX_BUFFER_LAYOUT 0x204 ++#define DPNI_CMDID_SET_TX_CONF_BUFFER_LAYOUT 0x205 ++#define DPNI_CMDID_GET_TX_CONF_BUFFER_LAYOUT 0x206 ++#define DPNI_CMDID_SET_L3_CHKSUM_VALIDATION 0x207 ++#define DPNI_CMDID_GET_L3_CHKSUM_VALIDATION 0x208 ++#define DPNI_CMDID_SET_L4_CHKSUM_VALIDATION 0x209 ++#define DPNI_CMDID_GET_L4_CHKSUM_VALIDATION 0x20A ++#define DPNI_CMDID_SET_ERRORS_BEHAVIOR 0x20B ++#define DPNI_CMDID_SET_TX_CONF_REVOKE 0x20C ++ ++#define DPNI_CMDID_GET_QDID 0x210 ++#define DPNI_CMDID_GET_SP_INFO 0x211 ++#define DPNI_CMDID_GET_TX_DATA_OFFSET 0x212 ++#define DPNI_CMDID_GET_COUNTER 0x213 ++#define DPNI_CMDID_SET_COUNTER 0x214 ++#define DPNI_CMDID_GET_LINK_STATE 0x215 ++#define DPNI_CMDID_SET_MAX_FRAME_LENGTH 0x216 ++#define DPNI_CMDID_GET_MAX_FRAME_LENGTH 0x217 ++#define DPNI_CMDID_SET_MTU 0x218 ++#define DPNI_CMDID_GET_MTU 0x219 ++#define DPNI_CMDID_SET_LINK_CFG 0x21A ++#define DPNI_CMDID_SET_TX_SHAPING 0x21B ++ ++#define DPNI_CMDID_SET_MCAST_PROMISC 0x220 ++#define DPNI_CMDID_GET_MCAST_PROMISC 0x221 ++#define DPNI_CMDID_SET_UNICAST_PROMISC 0x222 ++#define DPNI_CMDID_GET_UNICAST_PROMISC 0x223 ++#define DPNI_CMDID_SET_PRIM_MAC 0x224 ++#define DPNI_CMDID_GET_PRIM_MAC 0x225 ++#define DPNI_CMDID_ADD_MAC_ADDR 0x226 ++#define DPNI_CMDID_REMOVE_MAC_ADDR 0x227 ++#define DPNI_CMDID_CLR_MAC_FILTERS 0x228 ++ ++#define DPNI_CMDID_SET_VLAN_FILTERS 0x230 ++#define DPNI_CMDID_ADD_VLAN_ID 0x231 ++#define DPNI_CMDID_REMOVE_VLAN_ID 0x232 ++#define DPNI_CMDID_CLR_VLAN_FILTERS 0x233 ++ ++#define DPNI_CMDID_SET_RX_TC_DIST 0x235 ++#define DPNI_CMDID_SET_TX_FLOW 0x236 ++#define DPNI_CMDID_GET_TX_FLOW 0x237 ++#define DPNI_CMDID_SET_RX_FLOW 0x238 ++#define DPNI_CMDID_GET_RX_FLOW 0x239 ++#define DPNI_CMDID_SET_RX_ERR_QUEUE 0x23A ++#define DPNI_CMDID_GET_RX_ERR_QUEUE 0x23B ++ ++#define DPNI_CMDID_SET_RX_TC_POLICING 0x23E ++#define DPNI_CMDID_SET_RX_TC_EARLY_DROP 0x23F ++ ++#define DPNI_CMDID_SET_QOS_TBL 0x240 ++#define DPNI_CMDID_ADD_QOS_ENT 0x241 ++#define DPNI_CMDID_REMOVE_QOS_ENT 0x242 ++#define DPNI_CMDID_CLR_QOS_TBL 0x243 ++#define DPNI_CMDID_ADD_FS_ENT 0x244 ++#define DPNI_CMDID_REMOVE_FS_ENT 0x245 ++#define DPNI_CMDID_CLR_FS_ENT 0x246 ++#define DPNI_CMDID_SET_VLAN_INSERTION 0x247 ++#define DPNI_CMDID_SET_VLAN_REMOVAL 0x248 ++#define DPNI_CMDID_SET_IPR 0x249 ++#define DPNI_CMDID_SET_IPF 0x24A ++ ++#define DPNI_CMDID_SET_TX_SELECTION 0x250 ++#define DPNI_CMDID_GET_RX_TC_POLICING 0x251 ++#define DPNI_CMDID_GET_RX_TC_EARLY_DROP 0x252 ++#define DPNI_CMDID_SET_RX_TC_CONGESTION_NOTIFICATION 0x253 ++#define DPNI_CMDID_GET_RX_TC_CONGESTION_NOTIFICATION 0x254 ++#define DPNI_CMDID_SET_TX_TC_CONGESTION_NOTIFICATION 0x255 ++#define DPNI_CMDID_GET_TX_TC_CONGESTION_NOTIFICATION 0x256 ++#define DPNI_CMDID_SET_TX_CONF 0x257 ++#define DPNI_CMDID_GET_TX_CONF 0x258 ++#define DPNI_CMDID_SET_TX_CONF_CONGESTION_NOTIFICATION 0x259 ++#define DPNI_CMDID_GET_TX_CONF_CONGESTION_NOTIFICATION 0x25A ++#define DPNI_CMDID_SET_TX_TC_EARLY_DROP 0x25B ++#define DPNI_CMDID_GET_TX_TC_EARLY_DROP 0x25C ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_OPEN(cmd, dpni_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpni_id) ++ ++#define DPNI_PREP_EXTENDED_CFG(ext, cfg) \ ++do { \ ++ MC_PREP_OP(ext, 0, 0, 16, uint16_t, cfg->tc_cfg[0].max_dist); \ ++ MC_PREP_OP(ext, 0, 16, 16, uint16_t, cfg->tc_cfg[0].max_fs_entries); \ ++ MC_PREP_OP(ext, 0, 32, 16, uint16_t, cfg->tc_cfg[1].max_dist); \ ++ MC_PREP_OP(ext, 0, 48, 16, uint16_t, cfg->tc_cfg[1].max_fs_entries); \ ++ MC_PREP_OP(ext, 1, 0, 16, uint16_t, cfg->tc_cfg[2].max_dist); \ ++ MC_PREP_OP(ext, 1, 16, 16, uint16_t, cfg->tc_cfg[2].max_fs_entries); \ ++ MC_PREP_OP(ext, 1, 32, 16, uint16_t, cfg->tc_cfg[3].max_dist); \ ++ MC_PREP_OP(ext, 1, 48, 16, uint16_t, cfg->tc_cfg[3].max_fs_entries); \ ++ MC_PREP_OP(ext, 2, 0, 16, uint16_t, cfg->tc_cfg[4].max_dist); \ ++ MC_PREP_OP(ext, 2, 16, 16, uint16_t, cfg->tc_cfg[4].max_fs_entries); \ ++ MC_PREP_OP(ext, 2, 32, 16, uint16_t, cfg->tc_cfg[5].max_dist); \ ++ MC_PREP_OP(ext, 2, 48, 16, uint16_t, cfg->tc_cfg[5].max_fs_entries); \ ++ MC_PREP_OP(ext, 3, 0, 16, uint16_t, cfg->tc_cfg[6].max_dist); \ ++ MC_PREP_OP(ext, 3, 16, 16, uint16_t, cfg->tc_cfg[6].max_fs_entries); \ ++ MC_PREP_OP(ext, 3, 32, 16, uint16_t, cfg->tc_cfg[7].max_dist); \ ++ MC_PREP_OP(ext, 3, 48, 16, uint16_t, cfg->tc_cfg[7].max_fs_entries); \ ++ MC_PREP_OP(ext, 4, 0, 16, uint16_t, \ ++ cfg->ipr_cfg.max_open_frames_ipv4); \ ++ MC_PREP_OP(ext, 4, 16, 16, uint16_t, \ ++ cfg->ipr_cfg.max_open_frames_ipv6); \ ++ MC_PREP_OP(ext, 4, 32, 16, uint16_t, \ ++ cfg->ipr_cfg.max_reass_frm_size); \ ++ MC_PREP_OP(ext, 5, 0, 16, uint16_t, \ ++ cfg->ipr_cfg.min_frag_size_ipv4); \ ++ MC_PREP_OP(ext, 5, 16, 16, uint16_t, \ ++ cfg->ipr_cfg.min_frag_size_ipv6); \ ++} while (0) ++ ++#define DPNI_EXT_EXTENDED_CFG(ext, cfg) \ ++do { \ ++ MC_EXT_OP(ext, 0, 0, 16, uint16_t, cfg->tc_cfg[0].max_dist); \ ++ MC_EXT_OP(ext, 0, 16, 16, uint16_t, cfg->tc_cfg[0].max_fs_entries); \ ++ MC_EXT_OP(ext, 0, 32, 16, uint16_t, cfg->tc_cfg[1].max_dist); \ ++ MC_EXT_OP(ext, 0, 48, 16, uint16_t, cfg->tc_cfg[1].max_fs_entries); \ ++ MC_EXT_OP(ext, 1, 0, 16, uint16_t, cfg->tc_cfg[2].max_dist); \ ++ MC_EXT_OP(ext, 1, 16, 16, uint16_t, cfg->tc_cfg[2].max_fs_entries); \ ++ MC_EXT_OP(ext, 1, 32, 16, uint16_t, cfg->tc_cfg[3].max_dist); \ ++ MC_EXT_OP(ext, 1, 48, 16, uint16_t, cfg->tc_cfg[3].max_fs_entries); \ ++ MC_EXT_OP(ext, 2, 0, 16, uint16_t, cfg->tc_cfg[4].max_dist); \ ++ MC_EXT_OP(ext, 2, 16, 16, uint16_t, cfg->tc_cfg[4].max_fs_entries); \ ++ MC_EXT_OP(ext, 2, 32, 16, uint16_t, cfg->tc_cfg[5].max_dist); \ ++ MC_EXT_OP(ext, 2, 48, 16, uint16_t, cfg->tc_cfg[5].max_fs_entries); \ ++ MC_EXT_OP(ext, 3, 0, 16, uint16_t, cfg->tc_cfg[6].max_dist); \ ++ MC_EXT_OP(ext, 3, 16, 16, uint16_t, cfg->tc_cfg[6].max_fs_entries); \ ++ MC_EXT_OP(ext, 3, 32, 16, uint16_t, cfg->tc_cfg[7].max_dist); \ ++ MC_EXT_OP(ext, 3, 48, 16, uint16_t, cfg->tc_cfg[7].max_fs_entries); \ ++ MC_EXT_OP(ext, 4, 0, 16, uint16_t, \ ++ cfg->ipr_cfg.max_open_frames_ipv4); \ ++ MC_EXT_OP(ext, 4, 16, 16, uint16_t, \ ++ cfg->ipr_cfg.max_open_frames_ipv6); \ ++ MC_EXT_OP(ext, 4, 32, 16, uint16_t, \ ++ cfg->ipr_cfg.max_reass_frm_size); \ ++ MC_EXT_OP(ext, 5, 0, 16, uint16_t, \ ++ cfg->ipr_cfg.min_frag_size_ipv4); \ ++ MC_EXT_OP(ext, 5, 16, 16, uint16_t, \ ++ cfg->ipr_cfg.min_frag_size_ipv6); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_CREATE(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, cfg->adv.max_tcs); \ ++ MC_CMD_OP(cmd, 0, 8, 8, uint8_t, cfg->adv.max_senders); \ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, cfg->mac_addr[5]); \ ++ MC_CMD_OP(cmd, 0, 24, 8, uint8_t, cfg->mac_addr[4]); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->mac_addr[3]); \ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, cfg->mac_addr[2]); \ ++ MC_CMD_OP(cmd, 0, 48, 8, uint8_t, cfg->mac_addr[1]); \ ++ MC_CMD_OP(cmd, 0, 56, 8, uint8_t, cfg->mac_addr[0]); \ ++ MC_CMD_OP(cmd, 1, 0, 32, uint32_t, cfg->adv.options); \ ++ MC_CMD_OP(cmd, 2, 0, 8, uint8_t, cfg->adv.max_unicast_filters); \ ++ MC_CMD_OP(cmd, 2, 8, 8, uint8_t, cfg->adv.max_multicast_filters); \ ++ MC_CMD_OP(cmd, 2, 16, 8, uint8_t, cfg->adv.max_vlan_filters); \ ++ MC_CMD_OP(cmd, 2, 24, 8, uint8_t, cfg->adv.max_qos_entries); \ ++ MC_CMD_OP(cmd, 2, 32, 8, uint8_t, cfg->adv.max_qos_key_size); \ ++ MC_CMD_OP(cmd, 2, 48, 8, uint8_t, cfg->adv.max_dist_key_size); \ ++ MC_CMD_OP(cmd, 2, 56, 8, enum net_prot, cfg->adv.start_hdr); \ ++ MC_CMD_OP(cmd, 4, 48, 8, uint8_t, cfg->adv.max_policers); \ ++ MC_CMD_OP(cmd, 4, 56, 8, uint8_t, cfg->adv.max_congestion_ctrl); \ ++ MC_CMD_OP(cmd, 5, 0, 64, uint64_t, cfg->adv.ext_cfg_iova); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_POOLS(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, cfg->num_dpbp); \ ++ MC_CMD_OP(cmd, 0, 8, 1, int, cfg->pools[0].backup_pool); \ ++ MC_CMD_OP(cmd, 0, 9, 1, int, cfg->pools[1].backup_pool); \ ++ MC_CMD_OP(cmd, 0, 10, 1, int, cfg->pools[2].backup_pool); \ ++ MC_CMD_OP(cmd, 0, 11, 1, int, cfg->pools[3].backup_pool); \ ++ MC_CMD_OP(cmd, 0, 12, 1, int, cfg->pools[4].backup_pool); \ ++ MC_CMD_OP(cmd, 0, 13, 1, int, cfg->pools[5].backup_pool); \ ++ MC_CMD_OP(cmd, 0, 14, 1, int, cfg->pools[6].backup_pool); \ ++ MC_CMD_OP(cmd, 0, 15, 1, int, cfg->pools[7].backup_pool); \ ++ MC_CMD_OP(cmd, 0, 32, 32, int, cfg->pools[0].dpbp_id); \ ++ MC_CMD_OP(cmd, 4, 32, 16, uint16_t, cfg->pools[0].buffer_size);\ ++ MC_CMD_OP(cmd, 1, 0, 32, int, cfg->pools[1].dpbp_id); \ ++ MC_CMD_OP(cmd, 4, 48, 16, uint16_t, cfg->pools[1].buffer_size);\ ++ MC_CMD_OP(cmd, 1, 32, 32, int, cfg->pools[2].dpbp_id); \ ++ MC_CMD_OP(cmd, 5, 0, 16, uint16_t, cfg->pools[2].buffer_size);\ ++ MC_CMD_OP(cmd, 2, 0, 32, int, cfg->pools[3].dpbp_id); \ ++ MC_CMD_OP(cmd, 5, 16, 16, uint16_t, cfg->pools[3].buffer_size);\ ++ MC_CMD_OP(cmd, 2, 32, 32, int, cfg->pools[4].dpbp_id); \ ++ MC_CMD_OP(cmd, 5, 32, 16, uint16_t, cfg->pools[4].buffer_size);\ ++ MC_CMD_OP(cmd, 3, 0, 32, int, cfg->pools[5].dpbp_id); \ ++ MC_CMD_OP(cmd, 5, 48, 16, uint16_t, cfg->pools[5].buffer_size);\ ++ MC_CMD_OP(cmd, 3, 32, 32, int, cfg->pools[6].dpbp_id); \ ++ MC_CMD_OP(cmd, 6, 0, 16, uint16_t, cfg->pools[6].buffer_size);\ ++ MC_CMD_OP(cmd, 4, 0, 32, int, cfg->pools[7].dpbp_id); \ ++ MC_CMD_OP(cmd, 6, 16, 16, uint16_t, cfg->pools[7].buffer_size);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_IS_ENABLED(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr); \ ++ MC_CMD_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_GET_IRQ(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_IRQ(cmd, type, irq_cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr); \ ++ MC_RSP_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, type); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_IRQ_ENABLE(cmd, irq_index, en) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, en); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_GET_IRQ_ENABLE(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_IRQ_ENABLE(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 8, uint8_t, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, mask); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_GET_IRQ_MASK(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_IRQ_MASK(cmd, mask) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mask) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_IRQ_STATUS(cmd, status) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, status) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_GET_ATTR(cmd, attr) \ ++ MC_CMD_OP(cmd, 6, 0, 64, uint64_t, attr->ext_cfg_iova) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_ATTR(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, attr->id);\ ++ MC_RSP_OP(cmd, 0, 32, 8, uint8_t, attr->max_tcs); \ ++ MC_RSP_OP(cmd, 0, 40, 8, uint8_t, attr->max_senders); \ ++ MC_RSP_OP(cmd, 0, 48, 8, enum net_prot, attr->start_hdr); \ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, attr->options); \ ++ MC_RSP_OP(cmd, 2, 0, 8, uint8_t, attr->max_unicast_filters); \ ++ MC_RSP_OP(cmd, 2, 8, 8, uint8_t, attr->max_multicast_filters);\ ++ MC_RSP_OP(cmd, 2, 16, 8, uint8_t, attr->max_vlan_filters); \ ++ MC_RSP_OP(cmd, 2, 24, 8, uint8_t, attr->max_qos_entries); \ ++ MC_RSP_OP(cmd, 2, 32, 8, uint8_t, attr->max_qos_key_size); \ ++ MC_RSP_OP(cmd, 2, 40, 8, uint8_t, attr->max_dist_key_size); \ ++ MC_RSP_OP(cmd, 4, 48, 8, uint8_t, attr->max_policers); \ ++ MC_RSP_OP(cmd, 4, 56, 8, uint8_t, attr->max_congestion_ctrl); \ ++ MC_RSP_OP(cmd, 5, 32, 16, uint16_t, attr->version.major);\ ++ MC_RSP_OP(cmd, 5, 48, 16, uint16_t, attr->version.minor);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_ERRORS_BEHAVIOR(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, cfg->errors); \ ++ MC_CMD_OP(cmd, 0, 32, 4, enum dpni_error_action, cfg->error_action); \ ++ MC_CMD_OP(cmd, 0, 36, 1, int, cfg->set_frame_annotation); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_RX_BUFFER_LAYOUT(cmd, layout) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 16, uint16_t, layout->private_data_size); \ ++ MC_RSP_OP(cmd, 0, 16, 16, uint16_t, layout->data_align); \ ++ MC_RSP_OP(cmd, 1, 0, 1, int, layout->pass_timestamp); \ ++ MC_RSP_OP(cmd, 1, 1, 1, int, layout->pass_parser_result); \ ++ MC_RSP_OP(cmd, 1, 2, 1, int, layout->pass_frame_status); \ ++ MC_RSP_OP(cmd, 1, 16, 16, uint16_t, layout->data_head_room); \ ++ MC_RSP_OP(cmd, 1, 32, 16, uint16_t, layout->data_tail_room); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_RX_BUFFER_LAYOUT(cmd, layout) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, layout->private_data_size); \ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, layout->data_align); \ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, layout->options); \ ++ MC_CMD_OP(cmd, 1, 0, 1, int, layout->pass_timestamp); \ ++ MC_CMD_OP(cmd, 1, 1, 1, int, layout->pass_parser_result); \ ++ MC_CMD_OP(cmd, 1, 2, 1, int, layout->pass_frame_status); \ ++ MC_CMD_OP(cmd, 1, 16, 16, uint16_t, layout->data_head_room); \ ++ MC_CMD_OP(cmd, 1, 32, 16, uint16_t, layout->data_tail_room); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_TX_BUFFER_LAYOUT(cmd, layout) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 16, uint16_t, layout->private_data_size); \ ++ MC_RSP_OP(cmd, 0, 16, 16, uint16_t, layout->data_align); \ ++ MC_RSP_OP(cmd, 1, 0, 1, int, layout->pass_timestamp); \ ++ MC_RSP_OP(cmd, 1, 1, 1, int, layout->pass_parser_result); \ ++ MC_RSP_OP(cmd, 1, 2, 1, int, layout->pass_frame_status); \ ++ MC_RSP_OP(cmd, 1, 16, 16, uint16_t, layout->data_head_room); \ ++ MC_RSP_OP(cmd, 1, 32, 16, uint16_t, layout->data_tail_room); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_TX_BUFFER_LAYOUT(cmd, layout) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, layout->private_data_size); \ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, layout->data_align); \ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, layout->options); \ ++ MC_CMD_OP(cmd, 1, 0, 1, int, layout->pass_timestamp); \ ++ MC_CMD_OP(cmd, 1, 1, 1, int, layout->pass_parser_result); \ ++ MC_CMD_OP(cmd, 1, 2, 1, int, layout->pass_frame_status); \ ++ MC_CMD_OP(cmd, 1, 16, 16, uint16_t, layout->data_head_room); \ ++ MC_CMD_OP(cmd, 1, 32, 16, uint16_t, layout->data_tail_room); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_TX_CONF_BUFFER_LAYOUT(cmd, layout) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 16, uint16_t, layout->private_data_size); \ ++ MC_RSP_OP(cmd, 0, 16, 16, uint16_t, layout->data_align); \ ++ MC_RSP_OP(cmd, 1, 0, 1, int, layout->pass_timestamp); \ ++ MC_RSP_OP(cmd, 1, 1, 1, int, layout->pass_parser_result); \ ++ MC_RSP_OP(cmd, 1, 2, 1, int, layout->pass_frame_status); \ ++ MC_RSP_OP(cmd, 1, 16, 16, uint16_t, layout->data_head_room); \ ++ MC_RSP_OP(cmd, 1, 32, 16, uint16_t, layout->data_tail_room); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_TX_CONF_BUFFER_LAYOUT(cmd, layout) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, layout->private_data_size); \ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, layout->data_align); \ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, layout->options); \ ++ MC_CMD_OP(cmd, 1, 0, 1, int, layout->pass_timestamp); \ ++ MC_CMD_OP(cmd, 1, 1, 1, int, layout->pass_parser_result); \ ++ MC_CMD_OP(cmd, 1, 2, 1, int, layout->pass_frame_status); \ ++ MC_CMD_OP(cmd, 1, 16, 16, uint16_t, layout->data_head_room); \ ++ MC_CMD_OP(cmd, 1, 32, 16, uint16_t, layout->data_tail_room); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_L3_CHKSUM_VALIDATION(cmd, en) \ ++ MC_CMD_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_L3_CHKSUM_VALIDATION(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_L4_CHKSUM_VALIDATION(cmd, en) \ ++ MC_CMD_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_L4_CHKSUM_VALIDATION(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_QDID(cmd, qdid) \ ++ MC_RSP_OP(cmd, 0, 0, 16, uint16_t, qdid) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_SP_INFO(cmd, sp_info) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 16, uint16_t, sp_info->spids[0]); \ ++ MC_RSP_OP(cmd, 0, 16, 16, uint16_t, sp_info->spids[1]); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_TX_DATA_OFFSET(cmd, data_offset) \ ++ MC_RSP_OP(cmd, 0, 0, 16, uint16_t, data_offset) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_GET_COUNTER(cmd, counter) \ ++ MC_CMD_OP(cmd, 0, 0, 16, enum dpni_counter, counter) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_COUNTER(cmd, value) \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, value) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_COUNTER(cmd, counter, value) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, enum dpni_counter, counter); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, value); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_LINK_CFG(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 1, 0, 32, uint32_t, cfg->rate);\ ++ MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->options);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_LINK_STATE(cmd, state) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 32, 1, int, state->up);\ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, state->rate);\ ++ MC_RSP_OP(cmd, 2, 0, 64, uint64_t, state->options);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_TX_SHAPING(cmd, tx_shaper) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, tx_shaper->max_burst_size);\ ++ MC_CMD_OP(cmd, 1, 0, 32, uint32_t, tx_shaper->rate_limit);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_MAX_FRAME_LENGTH(cmd, max_frame_length) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, max_frame_length) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_MAX_FRAME_LENGTH(cmd, max_frame_length) \ ++ MC_RSP_OP(cmd, 0, 0, 16, uint16_t, max_frame_length) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_MTU(cmd, mtu) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, mtu) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_MTU(cmd, mtu) \ ++ MC_RSP_OP(cmd, 0, 0, 16, uint16_t, mtu) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_MULTICAST_PROMISC(cmd, en) \ ++ MC_CMD_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_MULTICAST_PROMISC(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_UNICAST_PROMISC(cmd, en) \ ++ MC_CMD_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_UNICAST_PROMISC(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_PRIMARY_MAC_ADDR(cmd, mac_addr) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, mac_addr[5]); \ ++ MC_CMD_OP(cmd, 0, 24, 8, uint8_t, mac_addr[4]); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, mac_addr[3]); \ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, mac_addr[2]); \ ++ MC_CMD_OP(cmd, 0, 48, 8, uint8_t, mac_addr[1]); \ ++ MC_CMD_OP(cmd, 0, 56, 8, uint8_t, mac_addr[0]); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_PRIMARY_MAC_ADDR(cmd, mac_addr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 16, 8, uint8_t, mac_addr[5]); \ ++ MC_RSP_OP(cmd, 0, 24, 8, uint8_t, mac_addr[4]); \ ++ MC_RSP_OP(cmd, 0, 32, 8, uint8_t, mac_addr[3]); \ ++ MC_RSP_OP(cmd, 0, 40, 8, uint8_t, mac_addr[2]); \ ++ MC_RSP_OP(cmd, 0, 48, 8, uint8_t, mac_addr[1]); \ ++ MC_RSP_OP(cmd, 0, 56, 8, uint8_t, mac_addr[0]); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_ADD_MAC_ADDR(cmd, mac_addr) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, mac_addr[5]); \ ++ MC_CMD_OP(cmd, 0, 24, 8, uint8_t, mac_addr[4]); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, mac_addr[3]); \ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, mac_addr[2]); \ ++ MC_CMD_OP(cmd, 0, 48, 8, uint8_t, mac_addr[1]); \ ++ MC_CMD_OP(cmd, 0, 56, 8, uint8_t, mac_addr[0]); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_REMOVE_MAC_ADDR(cmd, mac_addr) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, mac_addr[5]); \ ++ MC_CMD_OP(cmd, 0, 24, 8, uint8_t, mac_addr[4]); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, mac_addr[3]); \ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, mac_addr[2]); \ ++ MC_CMD_OP(cmd, 0, 48, 8, uint8_t, mac_addr[1]); \ ++ MC_CMD_OP(cmd, 0, 56, 8, uint8_t, mac_addr[0]); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_CLEAR_MAC_FILTERS(cmd, unicast, multicast) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 1, int, unicast); \ ++ MC_CMD_OP(cmd, 0, 1, 1, int, multicast); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_VLAN_FILTERS(cmd, en) \ ++ MC_CMD_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_ADD_VLAN_ID(cmd, vlan_id) \ ++ MC_CMD_OP(cmd, 0, 32, 16, uint16_t, vlan_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_REMOVE_VLAN_ID(cmd, vlan_id) \ ++ MC_CMD_OP(cmd, 0, 32, 16, uint16_t, vlan_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_TX_SELECTION(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, cfg->tc_sched[0].delta_bandwidth);\ ++ MC_CMD_OP(cmd, 0, 16, 4, enum dpni_tx_schedule_mode, \ ++ cfg->tc_sched[0].mode); \ ++ MC_CMD_OP(cmd, 0, 32, 16, uint16_t, cfg->tc_sched[1].delta_bandwidth);\ ++ MC_CMD_OP(cmd, 0, 48, 4, enum dpni_tx_schedule_mode, \ ++ cfg->tc_sched[1].mode); \ ++ MC_CMD_OP(cmd, 1, 0, 16, uint16_t, cfg->tc_sched[2].delta_bandwidth);\ ++ MC_CMD_OP(cmd, 1, 16, 4, enum dpni_tx_schedule_mode, \ ++ cfg->tc_sched[2].mode); \ ++ MC_CMD_OP(cmd, 1, 32, 16, uint16_t, cfg->tc_sched[3].delta_bandwidth);\ ++ MC_CMD_OP(cmd, 1, 48, 4, enum dpni_tx_schedule_mode, \ ++ cfg->tc_sched[3].mode); \ ++ MC_CMD_OP(cmd, 2, 0, 16, uint16_t, cfg->tc_sched[4].delta_bandwidth);\ ++ MC_CMD_OP(cmd, 2, 16, 4, enum dpni_tx_schedule_mode, \ ++ cfg->tc_sched[4].mode); \ ++ MC_CMD_OP(cmd, 2, 32, 16, uint16_t, cfg->tc_sched[5].delta_bandwidth);\ ++ MC_CMD_OP(cmd, 2, 48, 4, enum dpni_tx_schedule_mode, \ ++ cfg->tc_sched[5].mode); \ ++ MC_CMD_OP(cmd, 3, 0, 16, uint16_t, cfg->tc_sched[6].delta_bandwidth);\ ++ MC_CMD_OP(cmd, 3, 16, 4, enum dpni_tx_schedule_mode, \ ++ cfg->tc_sched[6].mode); \ ++ MC_CMD_OP(cmd, 3, 32, 16, uint16_t, cfg->tc_sched[7].delta_bandwidth);\ ++ MC_CMD_OP(cmd, 3, 48, 4, enum dpni_tx_schedule_mode, \ ++ cfg->tc_sched[7].mode); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_RX_TC_DIST(cmd, tc_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, cfg->dist_size); \ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, tc_id); \ ++ MC_CMD_OP(cmd, 0, 24, 4, enum dpni_dist_mode, cfg->dist_mode); \ ++ MC_CMD_OP(cmd, 0, 28, 4, enum dpni_fs_miss_action, \ ++ cfg->fs_cfg.miss_action); \ ++ MC_CMD_OP(cmd, 0, 48, 16, uint16_t, cfg->fs_cfg.default_flow_id); \ ++ MC_CMD_OP(cmd, 6, 0, 64, uint64_t, cfg->key_cfg_iova); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_TX_FLOW(cmd, flow_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 43, 1, int, cfg->l3_chksum_gen);\ ++ MC_CMD_OP(cmd, 0, 44, 1, int, cfg->l4_chksum_gen);\ ++ MC_CMD_OP(cmd, 0, 45, 1, int, cfg->use_common_tx_conf_queue);\ ++ MC_CMD_OP(cmd, 0, 48, 16, uint16_t, flow_id);\ ++ MC_CMD_OP(cmd, 2, 0, 32, uint32_t, cfg->options);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_SET_TX_FLOW(cmd, flow_id) \ ++ MC_RSP_OP(cmd, 0, 48, 16, uint16_t, flow_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_GET_TX_FLOW(cmd, flow_id) \ ++ MC_CMD_OP(cmd, 0, 48, 16, uint16_t, flow_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_TX_FLOW(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 43, 1, int, attr->l3_chksum_gen);\ ++ MC_RSP_OP(cmd, 0, 44, 1, int, attr->l4_chksum_gen);\ ++ MC_RSP_OP(cmd, 0, 45, 1, int, attr->use_common_tx_conf_queue);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_RX_FLOW(cmd, tc_id, flow_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, cfg->dest_cfg.dest_id); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->dest_cfg.priority);\ ++ MC_CMD_OP(cmd, 0, 40, 2, enum dpni_dest, cfg->dest_cfg.dest_type);\ ++ MC_CMD_OP(cmd, 0, 42, 1, int, cfg->order_preservation_en);\ ++ MC_CMD_OP(cmd, 0, 48, 16, uint16_t, flow_id); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->user_ctx); \ ++ MC_CMD_OP(cmd, 2, 16, 8, uint8_t, tc_id); \ ++ MC_CMD_OP(cmd, 2, 32, 32, uint32_t, cfg->options); \ ++ MC_CMD_OP(cmd, 3, 0, 4, enum dpni_flc_type, cfg->flc_cfg.flc_type); \ ++ MC_CMD_OP(cmd, 3, 4, 4, enum dpni_stash_size, \ ++ cfg->flc_cfg.frame_data_size);\ ++ MC_CMD_OP(cmd, 3, 8, 4, enum dpni_stash_size, \ ++ cfg->flc_cfg.flow_context_size);\ ++ MC_CMD_OP(cmd, 3, 32, 32, uint32_t, cfg->flc_cfg.options);\ ++ MC_CMD_OP(cmd, 4, 0, 64, uint64_t, cfg->flc_cfg.flow_context);\ ++ MC_CMD_OP(cmd, 5, 0, 32, uint32_t, cfg->tail_drop_threshold); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_GET_RX_FLOW(cmd, tc_id, flow_id) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, tc_id); \ ++ MC_CMD_OP(cmd, 0, 48, 16, uint16_t, flow_id); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_RX_FLOW(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, attr->dest_cfg.dest_id); \ ++ MC_RSP_OP(cmd, 0, 32, 8, uint8_t, attr->dest_cfg.priority);\ ++ MC_RSP_OP(cmd, 0, 40, 2, enum dpni_dest, attr->dest_cfg.dest_type); \ ++ MC_RSP_OP(cmd, 0, 42, 1, int, attr->order_preservation_en);\ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, attr->user_ctx); \ ++ MC_RSP_OP(cmd, 2, 0, 32, uint32_t, attr->tail_drop_threshold); \ ++ MC_RSP_OP(cmd, 2, 32, 32, uint32_t, attr->fqid); \ ++ MC_RSP_OP(cmd, 3, 0, 4, enum dpni_flc_type, attr->flc_cfg.flc_type); \ ++ MC_RSP_OP(cmd, 3, 4, 4, enum dpni_stash_size, \ ++ attr->flc_cfg.frame_data_size);\ ++ MC_RSP_OP(cmd, 3, 8, 4, enum dpni_stash_size, \ ++ attr->flc_cfg.flow_context_size);\ ++ MC_RSP_OP(cmd, 3, 32, 32, uint32_t, attr->flc_cfg.options);\ ++ MC_RSP_OP(cmd, 4, 0, 64, uint64_t, attr->flc_cfg.flow_context);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_RX_ERR_QUEUE(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, cfg->dest_cfg.dest_id); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->dest_cfg.priority);\ ++ MC_CMD_OP(cmd, 0, 40, 2, enum dpni_dest, cfg->dest_cfg.dest_type);\ ++ MC_CMD_OP(cmd, 0, 42, 1, int, cfg->order_preservation_en);\ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->user_ctx); \ ++ MC_CMD_OP(cmd, 2, 0, 32, uint32_t, cfg->options); \ ++ MC_CMD_OP(cmd, 2, 32, 32, uint32_t, cfg->tail_drop_threshold); \ ++ MC_CMD_OP(cmd, 3, 0, 4, enum dpni_flc_type, cfg->flc_cfg.flc_type); \ ++ MC_CMD_OP(cmd, 3, 4, 4, enum dpni_stash_size, \ ++ cfg->flc_cfg.frame_data_size);\ ++ MC_CMD_OP(cmd, 3, 8, 4, enum dpni_stash_size, \ ++ cfg->flc_cfg.flow_context_size);\ ++ MC_CMD_OP(cmd, 3, 32, 32, uint32_t, cfg->flc_cfg.options);\ ++ MC_CMD_OP(cmd, 4, 0, 64, uint64_t, cfg->flc_cfg.flow_context);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_RX_ERR_QUEUE(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, attr->dest_cfg.dest_id); \ ++ MC_RSP_OP(cmd, 0, 32, 8, uint8_t, attr->dest_cfg.priority);\ ++ MC_RSP_OP(cmd, 0, 40, 2, enum dpni_dest, attr->dest_cfg.dest_type);\ ++ MC_RSP_OP(cmd, 0, 42, 1, int, attr->order_preservation_en);\ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, attr->user_ctx); \ ++ MC_RSP_OP(cmd, 2, 0, 32, uint32_t, attr->tail_drop_threshold); \ ++ MC_RSP_OP(cmd, 2, 32, 32, uint32_t, attr->fqid); \ ++ MC_RSP_OP(cmd, 3, 0, 4, enum dpni_flc_type, attr->flc_cfg.flc_type); \ ++ MC_RSP_OP(cmd, 3, 4, 4, enum dpni_stash_size, \ ++ attr->flc_cfg.frame_data_size);\ ++ MC_RSP_OP(cmd, 3, 8, 4, enum dpni_stash_size, \ ++ attr->flc_cfg.flow_context_size);\ ++ MC_RSP_OP(cmd, 3, 32, 32, uint32_t, attr->flc_cfg.options);\ ++ MC_RSP_OP(cmd, 4, 0, 64, uint64_t, attr->flc_cfg.flow_context);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_TX_CONF_REVOKE(cmd, revoke) \ ++ MC_CMD_OP(cmd, 0, 0, 1, int, revoke) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_QOS_TABLE(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->default_tc); \ ++ MC_CMD_OP(cmd, 0, 40, 1, int, cfg->discard_on_miss); \ ++ MC_CMD_OP(cmd, 6, 0, 64, uint64_t, cfg->key_cfg_iova); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_ADD_QOS_ENTRY(cmd, cfg, tc_id) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, tc_id); \ ++ MC_CMD_OP(cmd, 0, 24, 8, uint8_t, cfg->key_size); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->key_iova); \ ++ MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->mask_iova); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_REMOVE_QOS_ENTRY(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 24, 8, uint8_t, cfg->key_size); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->key_iova); \ ++ MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->mask_iova); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_ADD_FS_ENTRY(cmd, tc_id, cfg, flow_id) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, tc_id); \ ++ MC_CMD_OP(cmd, 0, 48, 16, uint16_t, flow_id); \ ++ MC_CMD_OP(cmd, 0, 24, 8, uint8_t, cfg->key_size); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->key_iova); \ ++ MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->mask_iova); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_REMOVE_FS_ENTRY(cmd, tc_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, tc_id); \ ++ MC_CMD_OP(cmd, 0, 24, 8, uint8_t, cfg->key_size); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->key_iova); \ ++ MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->mask_iova); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_CLEAR_FS_ENTRIES(cmd, tc_id) \ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, tc_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_VLAN_INSERTION(cmd, en) \ ++ MC_CMD_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_VLAN_REMOVAL(cmd, en) \ ++ MC_CMD_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_IPR(cmd, en) \ ++ MC_CMD_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_IPF(cmd, en) \ ++ MC_CMD_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_RX_TC_POLICING(cmd, tc_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 4, enum dpni_policer_mode, cfg->mode); \ ++ MC_CMD_OP(cmd, 0, 4, 4, enum dpni_policer_color, cfg->default_color); \ ++ MC_CMD_OP(cmd, 0, 8, 4, enum dpni_policer_unit, cfg->units); \ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, tc_id); \ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, cfg->options); \ ++ MC_CMD_OP(cmd, 1, 0, 32, uint32_t, cfg->cir); \ ++ MC_CMD_OP(cmd, 1, 32, 32, uint32_t, cfg->cbs); \ ++ MC_CMD_OP(cmd, 2, 0, 32, uint32_t, cfg->eir); \ ++ MC_CMD_OP(cmd, 2, 32, 32, uint32_t, cfg->ebs);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_GET_RX_TC_POLICING(cmd, tc_id) \ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, tc_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_RSP_GET_RX_TC_POLICING(cmd, cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 4, enum dpni_policer_mode, cfg->mode); \ ++ MC_RSP_OP(cmd, 0, 4, 4, enum dpni_policer_color, cfg->default_color); \ ++ MC_RSP_OP(cmd, 0, 8, 4, enum dpni_policer_unit, cfg->units); \ ++ MC_RSP_OP(cmd, 0, 32, 32, uint32_t, cfg->options); \ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, cfg->cir); \ ++ MC_RSP_OP(cmd, 1, 32, 32, uint32_t, cfg->cbs); \ ++ MC_RSP_OP(cmd, 2, 0, 32, uint32_t, cfg->eir); \ ++ MC_RSP_OP(cmd, 2, 32, 32, uint32_t, cfg->ebs);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_PREP_EARLY_DROP(ext, cfg) \ ++do { \ ++ MC_PREP_OP(ext, 0, 0, 2, enum dpni_early_drop_mode, cfg->mode); \ ++ MC_PREP_OP(ext, 0, 2, 2, \ ++ enum dpni_congestion_unit, cfg->units); \ ++ MC_PREP_OP(ext, 0, 32, 32, uint32_t, cfg->tail_drop_threshold); \ ++ MC_PREP_OP(ext, 1, 0, 8, uint8_t, cfg->green.drop_probability); \ ++ MC_PREP_OP(ext, 2, 0, 64, uint64_t, cfg->green.max_threshold); \ ++ MC_PREP_OP(ext, 3, 0, 64, uint64_t, cfg->green.min_threshold); \ ++ MC_PREP_OP(ext, 5, 0, 8, uint8_t, cfg->yellow.drop_probability);\ ++ MC_PREP_OP(ext, 6, 0, 64, uint64_t, cfg->yellow.max_threshold); \ ++ MC_PREP_OP(ext, 7, 0, 64, uint64_t, cfg->yellow.min_threshold); \ ++ MC_PREP_OP(ext, 9, 0, 8, uint8_t, cfg->red.drop_probability); \ ++ MC_PREP_OP(ext, 10, 0, 64, uint64_t, cfg->red.max_threshold); \ ++ MC_PREP_OP(ext, 11, 0, 64, uint64_t, cfg->red.min_threshold); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_EXT_EARLY_DROP(ext, cfg) \ ++do { \ ++ MC_EXT_OP(ext, 0, 0, 2, enum dpni_early_drop_mode, cfg->mode); \ ++ MC_EXT_OP(ext, 0, 2, 2, \ ++ enum dpni_congestion_unit, cfg->units); \ ++ MC_EXT_OP(ext, 0, 32, 32, uint32_t, cfg->tail_drop_threshold); \ ++ MC_EXT_OP(ext, 1, 0, 8, uint8_t, cfg->green.drop_probability); \ ++ MC_EXT_OP(ext, 2, 0, 64, uint64_t, cfg->green.max_threshold); \ ++ MC_EXT_OP(ext, 3, 0, 64, uint64_t, cfg->green.min_threshold); \ ++ MC_EXT_OP(ext, 5, 0, 8, uint8_t, cfg->yellow.drop_probability);\ ++ MC_EXT_OP(ext, 6, 0, 64, uint64_t, cfg->yellow.max_threshold); \ ++ MC_EXT_OP(ext, 7, 0, 64, uint64_t, cfg->yellow.min_threshold); \ ++ MC_EXT_OP(ext, 9, 0, 8, uint8_t, cfg->red.drop_probability); \ ++ MC_EXT_OP(ext, 10, 0, 64, uint64_t, cfg->red.max_threshold); \ ++ MC_EXT_OP(ext, 11, 0, 64, uint64_t, cfg->red.min_threshold); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_RX_TC_EARLY_DROP(cmd, tc_id, early_drop_iova) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 8, 8, uint8_t, tc_id); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, early_drop_iova); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_GET_RX_TC_EARLY_DROP(cmd, tc_id, early_drop_iova) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 8, 8, uint8_t, tc_id); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, early_drop_iova); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_SET_TX_TC_EARLY_DROP(cmd, tc_id, early_drop_iova) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 8, 8, uint8_t, tc_id); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, early_drop_iova); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPNI_CMD_GET_TX_TC_EARLY_DROP(cmd, tc_id, early_drop_iova) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 8, 8, uint8_t, tc_id); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, early_drop_iova); \ ++} while (0) ++ ++#define DPNI_CMD_SET_RX_TC_CONGESTION_NOTIFICATION(cmd, tc_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 2, enum dpni_congestion_unit, cfg->units); \ ++ MC_CMD_OP(cmd, 0, 4, 4, enum dpni_dest, cfg->dest_cfg.dest_type); \ ++ MC_CMD_OP(cmd, 0, 8, 8, uint8_t, tc_id); \ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, cfg->dest_cfg.priority); \ ++ MC_CMD_OP(cmd, 1, 0, 32, uint32_t, cfg->threshold_entry); \ ++ MC_CMD_OP(cmd, 1, 32, 32, uint32_t, cfg->threshold_exit); \ ++ MC_CMD_OP(cmd, 2, 0, 16, uint16_t, cfg->options); \ ++ MC_CMD_OP(cmd, 2, 32, 32, int, cfg->dest_cfg.dest_id); \ ++ MC_CMD_OP(cmd, 3, 0, 64, uint64_t, cfg->message_ctx); \ ++ MC_CMD_OP(cmd, 4, 0, 64, uint64_t, cfg->message_iova); \ ++} while (0) ++ ++#define DPNI_CMD_GET_RX_TC_CONGESTION_NOTIFICATION(cmd, tc_id) \ ++ MC_CMD_OP(cmd, 0, 8, 8, uint8_t, tc_id) ++ ++#define DPNI_RSP_GET_RX_TC_CONGESTION_NOTIFICATION(cmd, cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 2, enum dpni_congestion_unit, cfg->units); \ ++ MC_RSP_OP(cmd, 0, 4, 4, enum dpni_dest, cfg->dest_cfg.dest_type); \ ++ MC_RSP_OP(cmd, 0, 16, 8, uint8_t, cfg->dest_cfg.priority); \ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, cfg->threshold_entry); \ ++ MC_RSP_OP(cmd, 1, 32, 32, uint32_t, cfg->threshold_exit); \ ++ MC_RSP_OP(cmd, 2, 0, 16, uint16_t, cfg->options); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, cfg->dest_cfg.dest_id); \ ++ MC_RSP_OP(cmd, 3, 0, 64, uint64_t, cfg->message_ctx); \ ++ MC_RSP_OP(cmd, 4, 0, 64, uint64_t, cfg->message_iova); \ ++} while (0) ++ ++#define DPNI_CMD_SET_TX_TC_CONGESTION_NOTIFICATION(cmd, tc_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 2, enum dpni_congestion_unit, cfg->units); \ ++ MC_CMD_OP(cmd, 0, 4, 4, enum dpni_dest, cfg->dest_cfg.dest_type); \ ++ MC_CMD_OP(cmd, 0, 8, 8, uint8_t, tc_id); \ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, cfg->dest_cfg.priority); \ ++ MC_CMD_OP(cmd, 1, 0, 32, uint32_t, cfg->threshold_entry); \ ++ MC_CMD_OP(cmd, 1, 32, 32, uint32_t, cfg->threshold_exit); \ ++ MC_CMD_OP(cmd, 2, 0, 16, uint16_t, cfg->options); \ ++ MC_CMD_OP(cmd, 2, 32, 32, int, cfg->dest_cfg.dest_id); \ ++ MC_CMD_OP(cmd, 3, 0, 64, uint64_t, cfg->message_ctx); \ ++ MC_CMD_OP(cmd, 4, 0, 64, uint64_t, cfg->message_iova); \ ++} while (0) ++ ++#define DPNI_CMD_GET_TX_TC_CONGESTION_NOTIFICATION(cmd, tc_id) \ ++ MC_CMD_OP(cmd, 0, 8, 8, uint8_t, tc_id) ++ ++#define DPNI_RSP_GET_TX_TC_CONGESTION_NOTIFICATION(cmd, cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 2, enum dpni_congestion_unit, cfg->units); \ ++ MC_RSP_OP(cmd, 0, 4, 4, enum dpni_dest, cfg->dest_cfg.dest_type); \ ++ MC_RSP_OP(cmd, 0, 16, 8, uint8_t, cfg->dest_cfg.priority); \ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, cfg->threshold_entry); \ ++ MC_RSP_OP(cmd, 1, 32, 32, uint32_t, cfg->threshold_exit); \ ++ MC_RSP_OP(cmd, 2, 0, 16, uint16_t, cfg->options); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, cfg->dest_cfg.dest_id); \ ++ MC_RSP_OP(cmd, 3, 0, 64, uint64_t, cfg->message_ctx); \ ++ MC_RSP_OP(cmd, 4, 0, 64, uint64_t, cfg->message_iova); \ ++} while (0) ++ ++#define DPNI_CMD_SET_TX_CONF(cmd, flow_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->queue_cfg.dest_cfg.priority); \ ++ MC_CMD_OP(cmd, 0, 40, 2, enum dpni_dest, \ ++ cfg->queue_cfg.dest_cfg.dest_type); \ ++ MC_CMD_OP(cmd, 0, 42, 1, int, cfg->errors_only); \ ++ MC_CMD_OP(cmd, 0, 46, 1, int, cfg->queue_cfg.order_preservation_en); \ ++ MC_CMD_OP(cmd, 0, 48, 16, uint16_t, flow_id); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->queue_cfg.user_ctx); \ ++ MC_CMD_OP(cmd, 2, 0, 32, uint32_t, cfg->queue_cfg.options); \ ++ MC_CMD_OP(cmd, 2, 32, 32, int, cfg->queue_cfg.dest_cfg.dest_id); \ ++ MC_CMD_OP(cmd, 3, 0, 32, uint32_t, \ ++ cfg->queue_cfg.tail_drop_threshold); \ ++ MC_CMD_OP(cmd, 4, 0, 4, enum dpni_flc_type, \ ++ cfg->queue_cfg.flc_cfg.flc_type); \ ++ MC_CMD_OP(cmd, 4, 4, 4, enum dpni_stash_size, \ ++ cfg->queue_cfg.flc_cfg.frame_data_size); \ ++ MC_CMD_OP(cmd, 4, 8, 4, enum dpni_stash_size, \ ++ cfg->queue_cfg.flc_cfg.flow_context_size); \ ++ MC_CMD_OP(cmd, 4, 32, 32, uint32_t, cfg->queue_cfg.flc_cfg.options); \ ++ MC_CMD_OP(cmd, 5, 0, 64, uint64_t, \ ++ cfg->queue_cfg.flc_cfg.flow_context); \ ++} while (0) ++ ++#define DPNI_CMD_GET_TX_CONF(cmd, flow_id) \ ++ MC_CMD_OP(cmd, 0, 48, 16, uint16_t, flow_id) ++ ++#define DPNI_RSP_GET_TX_CONF(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 32, 8, uint8_t, \ ++ attr->queue_attr.dest_cfg.priority); \ ++ MC_RSP_OP(cmd, 0, 40, 2, enum dpni_dest, \ ++ attr->queue_attr.dest_cfg.dest_type); \ ++ MC_RSP_OP(cmd, 0, 42, 1, int, attr->errors_only); \ ++ MC_RSP_OP(cmd, 0, 46, 1, int, \ ++ attr->queue_attr.order_preservation_en); \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, attr->queue_attr.user_ctx); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, attr->queue_attr.dest_cfg.dest_id); \ ++ MC_RSP_OP(cmd, 3, 0, 32, uint32_t, \ ++ attr->queue_attr.tail_drop_threshold); \ ++ MC_RSP_OP(cmd, 3, 32, 32, uint32_t, attr->queue_attr.fqid); \ ++ MC_RSP_OP(cmd, 4, 0, 4, enum dpni_flc_type, \ ++ attr->queue_attr.flc_cfg.flc_type); \ ++ MC_RSP_OP(cmd, 4, 4, 4, enum dpni_stash_size, \ ++ attr->queue_attr.flc_cfg.frame_data_size); \ ++ MC_RSP_OP(cmd, 4, 8, 4, enum dpni_stash_size, \ ++ attr->queue_attr.flc_cfg.flow_context_size); \ ++ MC_RSP_OP(cmd, 4, 32, 32, uint32_t, attr->queue_attr.flc_cfg.options); \ ++ MC_RSP_OP(cmd, 5, 0, 64, uint64_t, \ ++ attr->queue_attr.flc_cfg.flow_context); \ ++} while (0) ++ ++#define DPNI_CMD_SET_TX_CONF_CONGESTION_NOTIFICATION(cmd, flow_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 2, enum dpni_congestion_unit, cfg->units); \ ++ MC_CMD_OP(cmd, 0, 4, 4, enum dpni_dest, cfg->dest_cfg.dest_type); \ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, cfg->dest_cfg.priority); \ ++ MC_CMD_OP(cmd, 0, 48, 16, uint16_t, flow_id); \ ++ MC_CMD_OP(cmd, 1, 0, 32, uint32_t, cfg->threshold_entry); \ ++ MC_CMD_OP(cmd, 1, 32, 32, uint32_t, cfg->threshold_exit); \ ++ MC_CMD_OP(cmd, 2, 0, 16, uint16_t, cfg->options); \ ++ MC_CMD_OP(cmd, 2, 32, 32, int, cfg->dest_cfg.dest_id); \ ++ MC_CMD_OP(cmd, 3, 0, 64, uint64_t, cfg->message_ctx); \ ++ MC_CMD_OP(cmd, 4, 0, 64, uint64_t, cfg->message_iova); \ ++} while (0) ++ ++#define DPNI_CMD_GET_TX_CONF_CONGESTION_NOTIFICATION(cmd, flow_id) \ ++ MC_CMD_OP(cmd, 0, 48, 16, uint16_t, flow_id) ++ ++#define DPNI_RSP_GET_TX_CONF_CONGESTION_NOTIFICATION(cmd, cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 2, enum dpni_congestion_unit, cfg->units); \ ++ MC_RSP_OP(cmd, 0, 4, 4, enum dpni_dest, cfg->dest_cfg.dest_type); \ ++ MC_RSP_OP(cmd, 0, 16, 8, uint8_t, cfg->dest_cfg.priority); \ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, cfg->threshold_entry); \ ++ MC_RSP_OP(cmd, 1, 32, 32, uint32_t, cfg->threshold_exit); \ ++ MC_RSP_OP(cmd, 2, 0, 16, uint16_t, cfg->options); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, cfg->dest_cfg.dest_id); \ ++ MC_RSP_OP(cmd, 3, 0, 64, uint64_t, cfg->message_ctx); \ ++ MC_RSP_OP(cmd, 4, 0, 64, uint64_t, cfg->message_iova); \ ++} while (0) ++ ++#endif /* _FSL_DPNI_CMD_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dprc.h b/drivers/net/dpaa2/mc/fsl_dprc.h +new file mode 100644 +index 0000000..c831f46 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dprc.h +@@ -0,0 +1,1032 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_DPRC_H ++#define _FSL_DPRC_H ++ ++/* Data Path Resource Container API ++ * Contains DPRC API for managing and querying DPAA resources ++ */ ++ ++struct fsl_mc_io; ++ ++/** ++ * Set this value as the icid value in dprc_cfg structure when creating a ++ * container, in case the ICID is not selected by the user and should be ++ * allocated by the DPRC from the pool of ICIDs. ++ */ ++#define DPRC_GET_ICID_FROM_POOL (uint16_t)(~(0)) ++ ++/** ++ * Set this value as the portal_id value in dprc_cfg structure when creating a ++ * container, in case the portal ID is not specifically selected by the ++ * user and should be allocated by the DPRC from the pool of portal ids. ++ */ ++#define DPRC_GET_PORTAL_ID_FROM_POOL (int)(~(0)) ++ ++/** ++ * dprc_get_container_id() - Get container ID associated with a given portal. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @container_id: Requested container ID ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_get_container_id(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int *container_id); ++ ++/** ++ * dprc_open() - Open DPRC object for use ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @container_id: Container ID to open ++ * @token: Returned token of DPRC object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ * ++ * @warning Required before any operation on the object. ++ */ ++int dprc_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int container_id, ++ uint16_t *token); ++ ++/** ++ * dprc_close() - Close the control session of the object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * ++ * After this function is called, no further operations are ++ * allowed on the object without opening a new control session. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * Container general options ++ * ++ * These options may be selected at container creation by the container creator ++ * and can be retrieved using dprc_get_attributes() ++ */ ++ ++/** ++ * Spawn Policy Option allowed - Indicates that the new container is allowed ++ * to spawn and have its own child containers. ++ */ ++#define DPRC_CFG_OPT_SPAWN_ALLOWED 0x00000001 ++ ++/** ++ * General Container allocation policy - Indicates that the new container is ++ * allowed to allocate requested resources from its parent container; if not ++ * set, the container is only allowed to use resources in its own pools; Note ++ * that this is a container's global policy, but the parent container may ++ * override it and set specific quota per resource type. ++ */ ++#define DPRC_CFG_OPT_ALLOC_ALLOWED 0x00000002 ++ ++/** ++ * Object initialization allowed - software context associated with this ++ * container is allowed to invoke object initialization operations. ++ */ ++#define DPRC_CFG_OPT_OBJ_CREATE_ALLOWED 0x00000004 ++ ++/** ++ * Topology change allowed - software context associated with this ++ * container is allowed to invoke topology operations, such as attach/detach ++ * of network objects. ++ */ ++#define DPRC_CFG_OPT_TOPOLOGY_CHANGES_ALLOWED 0x00000008 ++ ++/** ++ * AIOP - Indicates that container belongs to AIOP. ++ */ ++#define DPRC_CFG_OPT_AIOP 0x00000020 ++ ++/** ++ * IRQ Config - Indicates that the container allowed to configure its IRQs. ++ */ ++#define DPRC_CFG_OPT_IRQ_CFG_ALLOWED 0x00000040 ++ ++/** ++ * struct dprc_cfg - Container configuration options ++ * @icid: Container's ICID; if set to 'DPRC_GET_ICID_FROM_POOL', a free ++ * ICID value is allocated by the DPRC ++ * @portal_id: Portal ID; if set to 'DPRC_GET_PORTAL_ID_FROM_POOL', a free ++ * portal ID is allocated by the DPRC ++ * @options: Combination of 'DPRC_CFG_OPT_' options ++ * @label: Object's label ++ */ ++struct dprc_cfg { ++ uint16_t icid; ++ int portal_id; ++ uint64_t options; ++ char label[16]; ++}; ++ ++/** ++ * dprc_create_container() - Create child container ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @cfg: Child container configuration ++ * @child_container_id: Returned child container ID ++ * @child_portal_offset: Returned child portal offset from MC portal base ++ * ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_create_container(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dprc_cfg *cfg, ++ int *child_container_id, ++ uint64_t *child_portal_offset); ++ ++/** ++ * dprc_destroy_container() - Destroy child container. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @child_container_id: ID of the container to destroy ++ * ++ * This function terminates the child container, so following this call the ++ * child container ID becomes invalid. ++ * ++ * Notes: ++ * - All resources and objects of the destroyed container are returned to the ++ * parent container or destroyed if were created be the destroyed container. ++ * - This function destroy all the child containers of the specified ++ * container prior to destroying the container itself. ++ * ++ * warning: Only the parent container is allowed to destroy a child policy ++ * Container 0 can't be destroyed ++ * ++ * Return: '0' on Success; Error code otherwise. ++ * ++ */ ++int dprc_destroy_container(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int child_container_id); ++ ++/** ++ * dprc_reset_container - Reset child container. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @child_container_id: ID of the container to reset ++ * ++ * In case a software context crashes or becomes non-responsive, the parent ++ * may wish to reset its resources container before the software context is ++ * restarted. ++ * ++ * This routine informs all objects assigned to the child container that the ++ * container is being reset, so they may perform any cleanup operations that are ++ * needed. All objects handles that were owned by the child container shall be ++ * closed. ++ * ++ * Note that such request may be submitted even if the child software context ++ * has not crashed, but the resulting object cleanup operations will not be ++ * aware of that. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_reset_container(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int child_container_id); ++ ++/** ++ * DPRC IRQ Index and Events ++ */ ++ ++/** ++ * IRQ index ++ */ ++#define DPRC_IRQ_INDEX 0 ++ ++/** ++ * Number of dprc's IRQs ++ */ ++#define DPRC_NUM_OF_IRQS 1 ++ ++/* DPRC IRQ events */ ++/** ++ * IRQ event - Indicates that a new object added to the container ++ */ ++#define DPRC_IRQ_EVENT_OBJ_ADDED 0x00000001 ++/** ++ * IRQ event - Indicates that an object was removed from the container ++ */ ++#define DPRC_IRQ_EVENT_OBJ_REMOVED 0x00000002 ++/** ++ * IRQ event - Indicates that resources added to the container ++ */ ++#define DPRC_IRQ_EVENT_RES_ADDED 0x00000004 ++/** ++ * IRQ event - Indicates that resources removed from the container ++ */ ++#define DPRC_IRQ_EVENT_RES_REMOVED 0x00000008 ++/** ++ * IRQ event - Indicates that one of the descendant containers that opened by ++ * this container is destroyed ++ */ ++#define DPRC_IRQ_EVENT_CONTAINER_DESTROYED 0x00000010 ++/** ++ * IRQ event - Indicates that on one of the container's opened object is ++ * destroyed ++ */ ++#define DPRC_IRQ_EVENT_OBJ_DESTROYED 0x00000020 ++/** ++ * Irq event - Indicates that object is created at the container ++ */ ++#define DPRC_IRQ_EVENT_OBJ_CREATED 0x00000040 ++ ++/** ++ * struct dprc_irq_cfg - IRQ configuration ++ * @addr: Address that must be written to signal a message-based interrupt ++ * @val: Value to write into irq_addr address ++ * @irq_num: A user defined number associated with this IRQ ++ */ ++struct dprc_irq_cfg { ++ uint64_t addr; ++ uint32_t val; ++ int irq_num; ++}; ++ ++/** ++ * dprc_set_irq() - Set IRQ information for the DPRC to trigger an interrupt. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @irq_index: Identifies the interrupt index to configure ++ * @irq_cfg: IRQ configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dprc_irq_cfg *irq_cfg); ++ ++/** ++ * dprc_get_irq() - Get IRQ information from the DPRC. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @irq_index: The interrupt index to configure ++ * @type: Interrupt type: 0 represents message interrupt ++ * type (both irq_addr and irq_val are valid) ++ * @irq_cfg: IRQ attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dprc_irq_cfg *irq_cfg); ++ ++/** ++ * dprc_set_irq_enable() - Set overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @irq_index: The interrupt index to configure ++ * @en: Interrupt state - enable = 1, disable = 0 ++ * ++ * Allows GPP software to control when interrupts are generated. ++ * Each interrupt can have up to 32 causes. The enable/disable control's the ++ * overall interrupt state. if the interrupt is disabled no causes will cause ++ * an interrupt. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en); ++ ++/** ++ * dprc_get_irq_enable() - Get overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @irq_index: The interrupt index to configure ++ * @en: Returned interrupt state - enable = 1, disable = 0 ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en); ++ ++/** ++ * dprc_set_irq_mask() - Set interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @irq_index: The interrupt index to configure ++ * @mask: event mask to trigger interrupt; ++ * each bit: ++ * 0 = ignore event ++ * 1 = consider event for asserting IRQ ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask); ++ ++/** ++ * dprc_get_irq_mask() - Get interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @irq_index: The interrupt index to configure ++ * @mask: Returned event mask to trigger interrupt ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask); ++ ++/** ++ * dprc_get_irq_status() - Get the current status of any pending interrupts. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @irq_index: The interrupt index to configure ++ * @status: Returned interrupts status - one bit per cause: ++ * 0 = no interrupt pending ++ * 1 = interrupt pending ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status); ++ ++/** ++ * dprc_clear_irq_status() - Clear a pending interrupt's status ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @irq_index: The interrupt index to configure ++ * @status: bits to clear (W1C) - one bit per cause: ++ * 0 = don't change ++ * 1 = clear status bit ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status); ++ ++/** ++ * struct dprc_attributes - Container attributes ++ * @container_id: Container's ID ++ * @icid: Container's ICID ++ * @portal_id: Container's portal ID ++ * @options: Container's options as set at container's creation ++ * @version: DPRC version ++ */ ++struct dprc_attributes { ++ int container_id; ++ uint16_t icid; ++ int portal_id; ++ uint64_t options; ++ /** ++ * struct version - DPRC version ++ * @major: DPRC major version ++ * @minor: DPRC minor version ++ */ ++ struct { ++ uint16_t major; ++ uint16_t minor; ++ } version; ++}; ++ ++/** ++ * dprc_get_attributes() - Obtains container attributes ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @attributes: Returned container attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dprc_attributes *attributes); ++ ++/** ++ * dprc_set_res_quota() - Set allocation policy for a specific resource/object ++ * type in a child container ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @child_container_id: ID of the child container ++ * @type: Resource/object type ++ * @quota: Sets the maximum number of resources of the selected type ++ * that the child container is allowed to allocate from its parent; ++ * when quota is set to -1, the policy is the same as container's ++ * general policy. ++ * ++ * Allocation policy determines whether or not a container may allocate ++ * resources from its parent. Each container has a 'global' allocation policy ++ * that is set when the container is created. ++ * ++ * This function sets allocation policy for a specific resource type. ++ * The default policy for all resource types matches the container's 'global' ++ * allocation policy. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ * ++ * @warning Only the parent container is allowed to change a child policy. ++ */ ++int dprc_set_res_quota(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int child_container_id, ++ char *type, ++ uint16_t quota); ++ ++/** ++ * dprc_get_res_quota() - Gets the allocation policy of a specific ++ * resource/object type in a child container ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @child_container_id: ID of the child container ++ * @type: resource/object type ++ * @quota: Returnes the maximum number of resources of the selected type ++ * that the child container is allowed to allocate from the parent; ++ * when quota is set to -1, the policy is the same as container's ++ * general policy. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_get_res_quota(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int child_container_id, ++ char *type, ++ uint16_t *quota); ++ ++/* Resource request options */ ++ ++/** ++ * Explicit resource ID request - The requested objects/resources ++ * are explicit and sequential (in case of resources). ++ * The base ID is given at res_req at base_align field ++ */ ++#define DPRC_RES_REQ_OPT_EXPLICIT 0x00000001 ++ ++/** ++ * Aligned resources request - Relevant only for resources ++ * request (and not objects). Indicates that resources base ID should be ++ * sequential and aligned to the value given at dprc_res_req base_align field ++ */ ++#define DPRC_RES_REQ_OPT_ALIGNED 0x00000002 ++ ++/** ++ * Plugged Flag - Relevant only for object assignment request. ++ * Indicates that after all objects assigned. An interrupt will be invoked at ++ * the relevant GPP. The assigned object will be marked as plugged. ++ * plugged objects can't be assigned from their container ++ */ ++#define DPRC_RES_REQ_OPT_PLUGGED 0x00000004 ++ ++/** ++ * struct dprc_res_req - Resource request descriptor, to be used in assignment ++ * or un-assignment of resources and objects. ++ * @type: Resource/object type: Represent as a NULL terminated string. ++ * This string may received by using dprc_get_pool() to get resource ++ * type and dprc_get_obj() to get object type; ++ * Note: it is not possible to assign/un-assign DPRC objects ++ * @num: Number of resources ++ * @options: Request options: combination of DPRC_RES_REQ_OPT_ options ++ * @id_base_align: In case of explicit assignment (DPRC_RES_REQ_OPT_EXPLICIT ++ * is set at option), this field represents the required base ID ++ * for resource allocation; In case of aligned assignment ++ * (DPRC_RES_REQ_OPT_ALIGNED is set at option), this field ++ * indicates the required alignment for the resource ID(s) - ++ * use 0 if there is no alignment or explicit ID requirements ++ */ ++struct dprc_res_req { ++ char type[16]; ++ uint32_t num; ++ uint32_t options; ++ int id_base_align; ++}; ++ ++/** ++ * dprc_assign() - Assigns objects or resource to a child container. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @container_id: ID of the child container ++ * @res_req: Describes the type and amount of resources to ++ * assign to the given container ++ * ++ * Assignment is usually done by a parent (this DPRC) to one of its child ++ * containers. ++ * ++ * According to the DPRC allocation policy, the assigned resources may be taken ++ * (allocated) from the container's ancestors, if not enough resources are ++ * available in the container itself. ++ * ++ * The type of assignment depends on the dprc_res_req options, as follows: ++ * - DPRC_RES_REQ_OPT_EXPLICIT: indicates that assigned resources should have ++ * the explicit base ID specified at the id_base_align field of res_req. ++ * - DPRC_RES_REQ_OPT_ALIGNED: indicates that the assigned resources should be ++ * aligned to the value given at id_base_align field of res_req. ++ * - DPRC_RES_REQ_OPT_PLUGGED: Relevant only for object assignment, ++ * and indicates that the object must be set to the plugged state. ++ * ++ * A container may use this function with its own ID in order to change a ++ * object state to plugged or unplugged. ++ * ++ * If IRQ information has been set in the child DPRC, it will signal an ++ * interrupt following every change in its object assignment. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_assign(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int container_id, ++ struct dprc_res_req *res_req); ++ ++/** ++ * dprc_unassign() - Un-assigns objects or resources from a child container ++ * and moves them into this (parent) DPRC. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @child_container_id: ID of the child container ++ * @res_req: Describes the type and amount of resources to un-assign from ++ * the child container ++ * ++ * Un-assignment of objects can succeed only if the object is not in the ++ * plugged or opened state. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_unassign(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int child_container_id, ++ struct dprc_res_req *res_req); ++ ++/** ++ * dprc_get_pool_count() - Get the number of dprc's pools ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @pool_count: Returned number of resource pools in the dprc ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_get_pool_count(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *pool_count); ++ ++/** ++ * dprc_get_pool() - Get the type (string) of a certain dprc's pool ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @pool_index: Index of the pool to be queried (< pool_count) ++ * @type: The type of the pool ++ * ++ * The pool types retrieved one by one by incrementing ++ * pool_index up to (not including) the value of pool_count returned ++ * from dprc_get_pool_count(). dprc_get_pool_count() must ++ * be called prior to dprc_get_pool(). ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_get_pool(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int pool_index, ++ char *type); ++ ++/** ++ * dprc_get_obj_count() - Obtains the number of objects in the DPRC ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @obj_count: Number of objects assigned to the DPRC ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_get_obj_count(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *obj_count); ++ ++/** ++ * Objects Attributes Flags ++ */ ++ ++/** ++ * Opened state - Indicates that an object is open by at least one owner ++ */ ++#define DPRC_OBJ_STATE_OPEN 0x00000001 ++/** ++ * Plugged state - Indicates that the object is plugged ++ */ ++#define DPRC_OBJ_STATE_PLUGGED 0x00000002 ++ ++/** ++ * Shareability flag - Object flag indicating no memory shareability. ++ * the object generates memory accesses that are non coherent with other ++ * masters; ++ * user is responsible for proper memory handling through IOMMU configuration. ++ */ ++#define DPRC_OBJ_FLAG_NO_MEM_SHAREABILITY 0x0001 ++ ++/** ++ * struct dprc_obj_desc - Object descriptor, returned from dprc_get_obj() ++ * @type: Type of object: NULL terminated string ++ * @id: ID of logical object resource ++ * @vendor: Object vendor identifier ++ * @ver_major: Major version number ++ * @ver_minor: Minor version number ++ * @irq_count: Number of interrupts supported by the object ++ * @region_count: Number of mappable regions supported by the object ++ * @state: Object state: combination of DPRC_OBJ_STATE_ states ++ * @label: Object label ++ * @flags: Object's flags ++ */ ++struct dprc_obj_desc { ++ char type[16]; ++ int id; ++ uint16_t vendor; ++ uint16_t ver_major; ++ uint16_t ver_minor; ++ uint8_t irq_count; ++ uint8_t region_count; ++ uint32_t state; ++ char label[16]; ++ uint16_t flags; ++}; ++ ++/** ++ * dprc_get_obj() - Get general information on an object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @obj_index: Index of the object to be queried (< obj_count) ++ * @obj_desc: Returns the requested object descriptor ++ * ++ * The object descriptors are retrieved one by one by incrementing ++ * obj_index up to (not including) the value of obj_count returned ++ * from dprc_get_obj_count(). dprc_get_obj_count() must ++ * be called prior to dprc_get_obj(). ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_get_obj(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int obj_index, ++ struct dprc_obj_desc *obj_desc); ++ ++/** ++ * dprc_get_obj_desc() - Get object descriptor. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @obj_type: The type of the object to get its descriptor. ++ * @obj_id: The id of the object to get its descriptor ++ * @obj_desc: The returned descriptor to fill and return to the user ++ * ++ * Return: '0' on Success; Error code otherwise. ++ * ++ */ ++int dprc_get_obj_desc(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ char *obj_type, ++ int obj_id, ++ struct dprc_obj_desc *obj_desc); ++ ++/** ++ * dprc_set_obj_irq() - Set IRQ information for object to trigger an interrupt. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @obj_type: Type of the object to set its IRQ ++ * @obj_id: ID of the object to set its IRQ ++ * @irq_index: The interrupt index to configure ++ * @irq_cfg: IRQ configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_set_obj_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ char *obj_type, ++ int obj_id, ++ uint8_t irq_index, ++ struct dprc_irq_cfg *irq_cfg); ++ ++/** ++ * dprc_get_obj_irq() - Get IRQ information from object. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @obj_type: Type od the object to get its IRQ ++ * @obj_id: ID of the object to get its IRQ ++ * @irq_index: The interrupt index to configure ++ * @type: Interrupt type: 0 represents message interrupt ++ * type (both irq_addr and irq_val are valid) ++ * @irq_cfg: The returned IRQ attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_get_obj_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ char *obj_type, ++ int obj_id, ++ uint8_t irq_index, ++ int *type, ++ struct dprc_irq_cfg *irq_cfg); ++ ++/** ++ * dprc_get_res_count() - Obtains the number of free resources that are ++ * assigned to this container, by pool type ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @type: pool type ++ * @res_count: Returned number of free resources of the given ++ * resource type that are assigned to this DPRC ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_get_res_count(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ char *type, ++ int *res_count); ++ ++/** ++ * enum dprc_iter_status - Iteration status ++ * @DPRC_ITER_STATUS_FIRST: Perform first iteration ++ * @DPRC_ITER_STATUS_MORE: Indicates more/next iteration is needed ++ * @DPRC_ITER_STATUS_LAST: Indicates last iteration ++ */ ++enum dprc_iter_status { ++ DPRC_ITER_STATUS_FIRST = 0, ++ DPRC_ITER_STATUS_MORE = 1, ++ DPRC_ITER_STATUS_LAST = 2 ++}; ++ ++/** ++ * struct dprc_res_ids_range_desc - Resource ID range descriptor ++ * @base_id: Base resource ID of this range ++ * @last_id: Last resource ID of this range ++ * @iter_status: Iteration status - should be set to DPRC_ITER_STATUS_FIRST at ++ * first iteration; while the returned marker is DPRC_ITER_STATUS_MORE, ++ * additional iterations are needed, until the returned marker is ++ * DPRC_ITER_STATUS_LAST ++ */ ++struct dprc_res_ids_range_desc { ++ int base_id; ++ int last_id; ++ enum dprc_iter_status iter_status; ++}; ++ ++/** ++ * dprc_get_res_ids() - Obtains IDs of free resources in the container ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @type: pool type ++ * @range_desc: range descriptor ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_get_res_ids(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ char *type, ++ struct dprc_res_ids_range_desc *range_desc); ++ ++/** ++ * Region flags ++ */ ++/** ++ * Cacheable - Indicates that region should be mapped as cacheable ++ */ ++#define DPRC_REGION_CACHEABLE 0x00000001 ++ ++/** ++ * enum dprc_region_type - Region type ++ * @DPRC_REGION_TYPE_MC_PORTAL: MC portal region ++ * @DPRC_REGION_TYPE_QBMAN_PORTAL: Qbman portal region ++ */ ++enum dprc_region_type { ++ DPRC_REGION_TYPE_MC_PORTAL, ++ DPRC_REGION_TYPE_QBMAN_PORTAL ++}; ++ ++/** ++ * struct dprc_region_desc - Mappable region descriptor ++ * @base_offset: Region offset from region's base address. ++ * For DPMCP and DPRC objects, region base is offset from SoC MC portals ++ * base address; For DPIO, region base is offset from SoC QMan portals ++ * base address ++ * @size: Region size (in bytes) ++ * @flags: Region attributes ++ * @type: Portal region type ++ */ ++struct dprc_region_desc { ++ uint32_t base_offset; ++ uint32_t size; ++ uint32_t flags; ++ enum dprc_region_type type; ++}; ++ ++/** ++ * dprc_get_obj_region() - Get region information for a specified object. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @obj_type: Object type as returned in dprc_get_obj() ++ * @obj_id: Unique object instance as returned in dprc_get_obj() ++ * @region_index: The specific region to query ++ * @region_desc: Returns the requested region descriptor ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_get_obj_region(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ char *obj_type, ++ int obj_id, ++ uint8_t region_index, ++ struct dprc_region_desc *region_desc); ++ ++/** ++ * dprc_set_obj_label() - Set object label. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @obj_type: Object's type ++ * @obj_id: Object's ID ++ * @label: The required label. The maximum length is 16 chars. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_set_obj_label(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ char *obj_type, ++ int obj_id, ++ char *label); ++ ++/** ++ * struct dprc_endpoint - Endpoint description for link connect/disconnect ++ * operations ++ * @type: Endpoint object type: NULL terminated string ++ * @id: Endpoint object ID ++ * @if_id: Interface ID; should be set for endpoints with multiple ++ * interfaces ("dpsw", "dpdmux"); for others, always set to 0 ++ */ ++struct dprc_endpoint { ++ char type[16]; ++ int id; ++ uint16_t if_id; ++}; ++ ++/** ++ * struct dprc_connection_cfg - Connection configuration. ++ * Used for virtual connections only ++ * @committed_rate: Committed rate (Mbits/s) ++ * @max_rate: Maximum rate (Mbits/s) ++ */ ++struct dprc_connection_cfg { ++ uint32_t committed_rate; ++ uint32_t max_rate; ++}; ++ ++/** ++ * dprc_connect() - Connect two endpoints to create a network link between them ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @endpoint1: Endpoint 1 configuration parameters ++ * @endpoint2: Endpoint 2 configuration parameters ++ * @cfg: Connection configuration. The connection configuration is ignored for ++ * connections made to DPMAC objects, where rate is retrieved from the ++ * MAC configuration. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_connect(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dprc_endpoint *endpoint1, ++ const struct dprc_endpoint *endpoint2, ++ const struct dprc_connection_cfg *cfg); ++ ++/** ++ * dprc_disconnect() - Disconnect one endpoint to remove its network connection ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRC object ++ * @endpoint: Endpoint configuration parameters ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprc_disconnect(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dprc_endpoint *endpoint); ++ ++/** ++* dprc_get_connection() - Get connected endpoint and link status if connection ++* exists. ++* @mc_io: Pointer to MC portal's I/O object ++* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++* @token: Token of DPRC object ++* @endpoint1: Endpoint 1 configuration parameters ++* @endpoint2: Returned endpoint 2 configuration parameters ++* @state: Returned link state: ++* 1 - link is up; ++* 0 - link is down; ++* -1 - no connection (endpoint2 information is irrelevant) ++* ++* Return: '0' on Success; -ENAVAIL if connection does not exist. ++*/ ++int dprc_get_connection(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dprc_endpoint *endpoint1, ++ struct dprc_endpoint *endpoint2, ++ int *state); ++ ++#endif /* _FSL_DPRC_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dprc_cmd.h b/drivers/net/dpaa2/mc/fsl_dprc_cmd.h +new file mode 100644 +index 0000000..469e286 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dprc_cmd.h +@@ -0,0 +1,755 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_DPRC_CMD_H ++#define _FSL_DPRC_CMD_H ++ ++/* DPRC Version */ ++#define DPRC_VER_MAJOR 5 ++#define DPRC_VER_MINOR 1 ++ ++/* Command IDs */ ++#define DPRC_CMDID_CLOSE 0x800 ++#define DPRC_CMDID_OPEN 0x805 ++#define DPRC_CMDID_CREATE 0x905 ++ ++#define DPRC_CMDID_GET_ATTR 0x004 ++#define DPRC_CMDID_RESET_CONT 0x005 ++ ++#define DPRC_CMDID_SET_IRQ 0x010 ++#define DPRC_CMDID_GET_IRQ 0x011 ++#define DPRC_CMDID_SET_IRQ_ENABLE 0x012 ++#define DPRC_CMDID_GET_IRQ_ENABLE 0x013 ++#define DPRC_CMDID_SET_IRQ_MASK 0x014 ++#define DPRC_CMDID_GET_IRQ_MASK 0x015 ++#define DPRC_CMDID_GET_IRQ_STATUS 0x016 ++#define DPRC_CMDID_CLEAR_IRQ_STATUS 0x017 ++ ++#define DPRC_CMDID_CREATE_CONT 0x151 ++#define DPRC_CMDID_DESTROY_CONT 0x152 ++#define DPRC_CMDID_GET_CONT_ID 0x830 ++#define DPRC_CMDID_SET_RES_QUOTA 0x155 ++#define DPRC_CMDID_GET_RES_QUOTA 0x156 ++#define DPRC_CMDID_ASSIGN 0x157 ++#define DPRC_CMDID_UNASSIGN 0x158 ++#define DPRC_CMDID_GET_OBJ_COUNT 0x159 ++#define DPRC_CMDID_GET_OBJ 0x15A ++#define DPRC_CMDID_GET_RES_COUNT 0x15B ++#define DPRC_CMDID_GET_RES_IDS 0x15C ++#define DPRC_CMDID_GET_OBJ_REG 0x15E ++#define DPRC_CMDID_SET_OBJ_IRQ 0x15F ++#define DPRC_CMDID_GET_OBJ_IRQ 0x160 ++#define DPRC_CMDID_SET_OBJ_LABEL 0x161 ++#define DPRC_CMDID_GET_OBJ_DESC 0x162 ++ ++#define DPRC_CMDID_CONNECT 0x167 ++#define DPRC_CMDID_DISCONNECT 0x168 ++#define DPRC_CMDID_GET_POOL 0x169 ++#define DPRC_CMDID_GET_POOL_COUNT 0x16A ++ ++#define DPRC_CMDID_GET_CONNECTION 0x16C ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_RSP_GET_CONTAINER_ID(cmd, container_id) \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, container_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_OPEN(cmd, container_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, container_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_CREATE_CONTAINER(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 32, 16, uint16_t, cfg->icid); \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, cfg->options); \ ++ MC_CMD_OP(cmd, 1, 32, 32, int, cfg->portal_id); \ ++ MC_CMD_OP(cmd, 2, 0, 8, char, cfg->label[0]);\ ++ MC_CMD_OP(cmd, 2, 8, 8, char, cfg->label[1]);\ ++ MC_CMD_OP(cmd, 2, 16, 8, char, cfg->label[2]);\ ++ MC_CMD_OP(cmd, 2, 24, 8, char, cfg->label[3]);\ ++ MC_CMD_OP(cmd, 2, 32, 8, char, cfg->label[4]);\ ++ MC_CMD_OP(cmd, 2, 40, 8, char, cfg->label[5]);\ ++ MC_CMD_OP(cmd, 2, 48, 8, char, cfg->label[6]);\ ++ MC_CMD_OP(cmd, 2, 56, 8, char, cfg->label[7]);\ ++ MC_CMD_OP(cmd, 3, 0, 8, char, cfg->label[8]);\ ++ MC_CMD_OP(cmd, 3, 8, 8, char, cfg->label[9]);\ ++ MC_CMD_OP(cmd, 3, 16, 8, char, cfg->label[10]);\ ++ MC_CMD_OP(cmd, 3, 24, 8, char, cfg->label[11]);\ ++ MC_CMD_OP(cmd, 3, 32, 8, char, cfg->label[12]);\ ++ MC_CMD_OP(cmd, 3, 40, 8, char, cfg->label[13]);\ ++ MC_CMD_OP(cmd, 3, 48, 8, char, cfg->label[14]);\ ++ MC_CMD_OP(cmd, 3, 56, 8, char, cfg->label[15]);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_RSP_CREATE_CONTAINER(cmd, child_container_id, child_portal_offset)\ ++do { \ ++ MC_RSP_OP(cmd, 1, 0, 32, int, child_container_id); \ ++ MC_RSP_OP(cmd, 2, 0, 64, uint64_t, child_portal_offset);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_DESTROY_CONTAINER(cmd, child_container_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, child_container_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_RESET_CONTAINER(cmd, child_container_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, child_container_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index); \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\ ++ MC_CMD_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_GET_IRQ(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_RSP_GET_IRQ(cmd, type, irq_cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\ ++ MC_RSP_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, type); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_SET_IRQ_ENABLE(cmd, irq_index, en) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, en); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_GET_IRQ_ENABLE(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_RSP_GET_IRQ_ENABLE(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 8, uint8_t, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, mask); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_GET_IRQ_MASK(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_RSP_GET_IRQ_MASK(cmd, mask) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mask) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_RSP_GET_IRQ_STATUS(cmd, status) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, status) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_RSP_GET_ATTRIBUTES(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, attr->container_id); \ ++ MC_RSP_OP(cmd, 0, 32, 16, uint16_t, attr->icid); \ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, attr->options);\ ++ MC_RSP_OP(cmd, 1, 32, 32, int, attr->portal_id); \ ++ MC_RSP_OP(cmd, 2, 0, 16, uint16_t, attr->version.major);\ ++ MC_RSP_OP(cmd, 2, 16, 16, uint16_t, attr->version.minor);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_SET_RES_QUOTA(cmd, child_container_id, type, quota) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, child_container_id); \ ++ MC_CMD_OP(cmd, 0, 32, 16, uint16_t, quota);\ ++ MC_CMD_OP(cmd, 1, 0, 8, char, type[0]);\ ++ MC_CMD_OP(cmd, 1, 8, 8, char, type[1]);\ ++ MC_CMD_OP(cmd, 1, 16, 8, char, type[2]);\ ++ MC_CMD_OP(cmd, 1, 24, 8, char, type[3]);\ ++ MC_CMD_OP(cmd, 1, 32, 8, char, type[4]);\ ++ MC_CMD_OP(cmd, 1, 40, 8, char, type[5]);\ ++ MC_CMD_OP(cmd, 1, 48, 8, char, type[6]);\ ++ MC_CMD_OP(cmd, 1, 56, 8, char, type[7]);\ ++ MC_CMD_OP(cmd, 2, 0, 8, char, type[8]);\ ++ MC_CMD_OP(cmd, 2, 8, 8, char, type[9]);\ ++ MC_CMD_OP(cmd, 2, 16, 8, char, type[10]);\ ++ MC_CMD_OP(cmd, 2, 24, 8, char, type[11]);\ ++ MC_CMD_OP(cmd, 2, 32, 8, char, type[12]);\ ++ MC_CMD_OP(cmd, 2, 40, 8, char, type[13]);\ ++ MC_CMD_OP(cmd, 2, 48, 8, char, type[14]);\ ++ MC_CMD_OP(cmd, 2, 56, 8, char, type[15]);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_GET_RES_QUOTA(cmd, child_container_id, type) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, child_container_id); \ ++ MC_CMD_OP(cmd, 1, 0, 8, char, type[0]);\ ++ MC_CMD_OP(cmd, 1, 8, 8, char, type[1]);\ ++ MC_CMD_OP(cmd, 1, 16, 8, char, type[2]);\ ++ MC_CMD_OP(cmd, 1, 24, 8, char, type[3]);\ ++ MC_CMD_OP(cmd, 1, 32, 8, char, type[4]);\ ++ MC_CMD_OP(cmd, 1, 40, 8, char, type[5]);\ ++ MC_CMD_OP(cmd, 1, 48, 8, char, type[6]);\ ++ MC_CMD_OP(cmd, 1, 56, 8, char, type[7]);\ ++ MC_CMD_OP(cmd, 2, 0, 8, char, type[8]);\ ++ MC_CMD_OP(cmd, 2, 8, 8, char, type[9]);\ ++ MC_CMD_OP(cmd, 2, 16, 8, char, type[10]);\ ++ MC_CMD_OP(cmd, 2, 24, 8, char, type[11]);\ ++ MC_CMD_OP(cmd, 2, 32, 8, char, type[12]);\ ++ MC_CMD_OP(cmd, 2, 40, 8, char, type[13]);\ ++ MC_CMD_OP(cmd, 2, 48, 8, char, type[14]);\ ++ MC_CMD_OP(cmd, 2, 56, 8, char, type[15]);\ ++} while (0) ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_RSP_GET_RES_QUOTA(cmd, quota) \ ++ MC_RSP_OP(cmd, 0, 32, 16, uint16_t, quota) ++ ++/* param, offset, width, type, arg_name */ ++#define DPRC_CMD_ASSIGN(cmd, container_id, res_req) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, container_id); \ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, res_req->options);\ ++ MC_CMD_OP(cmd, 1, 0, 32, uint32_t, res_req->num); \ ++ MC_CMD_OP(cmd, 1, 32, 32, int, res_req->id_base_align); \ ++ MC_CMD_OP(cmd, 2, 0, 8, char, res_req->type[0]);\ ++ MC_CMD_OP(cmd, 2, 8, 8, char, res_req->type[1]);\ ++ MC_CMD_OP(cmd, 2, 16, 8, char, res_req->type[2]);\ ++ MC_CMD_OP(cmd, 2, 24, 8, char, res_req->type[3]);\ ++ MC_CMD_OP(cmd, 2, 32, 8, char, res_req->type[4]);\ ++ MC_CMD_OP(cmd, 2, 40, 8, char, res_req->type[5]);\ ++ MC_CMD_OP(cmd, 2, 48, 8, char, res_req->type[6]);\ ++ MC_CMD_OP(cmd, 2, 56, 8, char, res_req->type[7]);\ ++ MC_CMD_OP(cmd, 3, 0, 8, char, res_req->type[8]);\ ++ MC_CMD_OP(cmd, 3, 8, 8, char, res_req->type[9]);\ ++ MC_CMD_OP(cmd, 3, 16, 8, char, res_req->type[10]);\ ++ MC_CMD_OP(cmd, 3, 24, 8, char, res_req->type[11]);\ ++ MC_CMD_OP(cmd, 3, 32, 8, char, res_req->type[12]);\ ++ MC_CMD_OP(cmd, 3, 40, 8, char, res_req->type[13]);\ ++ MC_CMD_OP(cmd, 3, 48, 8, char, res_req->type[14]);\ ++ MC_CMD_OP(cmd, 3, 56, 8, char, res_req->type[15]);\ ++} while (0) ++ ++/* param, offset, width, type, arg_name */ ++#define DPRC_CMD_UNASSIGN(cmd, child_container_id, res_req) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, child_container_id); \ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, res_req->options);\ ++ MC_CMD_OP(cmd, 1, 0, 32, uint32_t, res_req->num); \ ++ MC_CMD_OP(cmd, 1, 32, 32, int, res_req->id_base_align); \ ++ MC_CMD_OP(cmd, 2, 0, 8, char, res_req->type[0]);\ ++ MC_CMD_OP(cmd, 2, 8, 8, char, res_req->type[1]);\ ++ MC_CMD_OP(cmd, 2, 16, 8, char, res_req->type[2]);\ ++ MC_CMD_OP(cmd, 2, 24, 8, char, res_req->type[3]);\ ++ MC_CMD_OP(cmd, 2, 32, 8, char, res_req->type[4]);\ ++ MC_CMD_OP(cmd, 2, 40, 8, char, res_req->type[5]);\ ++ MC_CMD_OP(cmd, 2, 48, 8, char, res_req->type[6]);\ ++ MC_CMD_OP(cmd, 2, 56, 8, char, res_req->type[7]);\ ++ MC_CMD_OP(cmd, 3, 0, 8, char, res_req->type[8]);\ ++ MC_CMD_OP(cmd, 3, 8, 8, char, res_req->type[9]);\ ++ MC_CMD_OP(cmd, 3, 16, 8, char, res_req->type[10]);\ ++ MC_CMD_OP(cmd, 3, 24, 8, char, res_req->type[11]);\ ++ MC_CMD_OP(cmd, 3, 32, 8, char, res_req->type[12]);\ ++ MC_CMD_OP(cmd, 3, 40, 8, char, res_req->type[13]);\ ++ MC_CMD_OP(cmd, 3, 48, 8, char, res_req->type[14]);\ ++ MC_CMD_OP(cmd, 3, 56, 8, char, res_req->type[15]);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_RSP_GET_POOL_COUNT(cmd, pool_count) \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, pool_count) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_GET_POOL(cmd, pool_index) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, pool_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_RSP_GET_POOL(cmd, type) \ ++do { \ ++ MC_RSP_OP(cmd, 1, 0, 8, char, type[0]);\ ++ MC_RSP_OP(cmd, 1, 8, 8, char, type[1]);\ ++ MC_RSP_OP(cmd, 1, 16, 8, char, type[2]);\ ++ MC_RSP_OP(cmd, 1, 24, 8, char, type[3]);\ ++ MC_RSP_OP(cmd, 1, 32, 8, char, type[4]);\ ++ MC_RSP_OP(cmd, 1, 40, 8, char, type[5]);\ ++ MC_RSP_OP(cmd, 1, 48, 8, char, type[6]);\ ++ MC_RSP_OP(cmd, 1, 56, 8, char, type[7]);\ ++ MC_RSP_OP(cmd, 2, 0, 8, char, type[8]);\ ++ MC_RSP_OP(cmd, 2, 8, 8, char, type[9]);\ ++ MC_RSP_OP(cmd, 2, 16, 8, char, type[10]);\ ++ MC_RSP_OP(cmd, 2, 24, 8, char, type[11]);\ ++ MC_RSP_OP(cmd, 2, 32, 8, char, type[12]);\ ++ MC_RSP_OP(cmd, 2, 40, 8, char, type[13]);\ ++ MC_RSP_OP(cmd, 2, 48, 8, char, type[14]);\ ++ MC_RSP_OP(cmd, 2, 56, 8, char, type[15]);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_RSP_GET_OBJ_COUNT(cmd, obj_count) \ ++ MC_RSP_OP(cmd, 0, 32, 32, int, obj_count) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_GET_OBJ(cmd, obj_index) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, obj_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_RSP_GET_OBJ(cmd, obj_desc) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 32, 32, int, obj_desc->id); \ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, obj_desc->vendor); \ ++ MC_RSP_OP(cmd, 1, 16, 8, uint8_t, obj_desc->irq_count); \ ++ MC_RSP_OP(cmd, 1, 24, 8, uint8_t, obj_desc->region_count); \ ++ MC_RSP_OP(cmd, 1, 32, 32, uint32_t, obj_desc->state);\ ++ MC_RSP_OP(cmd, 2, 0, 16, uint16_t, obj_desc->ver_major);\ ++ MC_RSP_OP(cmd, 2, 16, 16, uint16_t, obj_desc->ver_minor);\ ++ MC_RSP_OP(cmd, 2, 32, 16, uint16_t, obj_desc->flags); \ ++ MC_RSP_OP(cmd, 3, 0, 8, char, obj_desc->type[0]);\ ++ MC_RSP_OP(cmd, 3, 8, 8, char, obj_desc->type[1]);\ ++ MC_RSP_OP(cmd, 3, 16, 8, char, obj_desc->type[2]);\ ++ MC_RSP_OP(cmd, 3, 24, 8, char, obj_desc->type[3]);\ ++ MC_RSP_OP(cmd, 3, 32, 8, char, obj_desc->type[4]);\ ++ MC_RSP_OP(cmd, 3, 40, 8, char, obj_desc->type[5]);\ ++ MC_RSP_OP(cmd, 3, 48, 8, char, obj_desc->type[6]);\ ++ MC_RSP_OP(cmd, 3, 56, 8, char, obj_desc->type[7]);\ ++ MC_RSP_OP(cmd, 4, 0, 8, char, obj_desc->type[8]);\ ++ MC_RSP_OP(cmd, 4, 8, 8, char, obj_desc->type[9]);\ ++ MC_RSP_OP(cmd, 4, 16, 8, char, obj_desc->type[10]);\ ++ MC_RSP_OP(cmd, 4, 24, 8, char, obj_desc->type[11]);\ ++ MC_RSP_OP(cmd, 4, 32, 8, char, obj_desc->type[12]);\ ++ MC_RSP_OP(cmd, 4, 40, 8, char, obj_desc->type[13]);\ ++ MC_RSP_OP(cmd, 4, 48, 8, char, obj_desc->type[14]);\ ++ MC_RSP_OP(cmd, 4, 56, 8, char, obj_desc->type[15]);\ ++ MC_RSP_OP(cmd, 5, 0, 8, char, obj_desc->label[0]);\ ++ MC_RSP_OP(cmd, 5, 8, 8, char, obj_desc->label[1]);\ ++ MC_RSP_OP(cmd, 5, 16, 8, char, obj_desc->label[2]);\ ++ MC_RSP_OP(cmd, 5, 24, 8, char, obj_desc->label[3]);\ ++ MC_RSP_OP(cmd, 5, 32, 8, char, obj_desc->label[4]);\ ++ MC_RSP_OP(cmd, 5, 40, 8, char, obj_desc->label[5]);\ ++ MC_RSP_OP(cmd, 5, 48, 8, char, obj_desc->label[6]);\ ++ MC_RSP_OP(cmd, 5, 56, 8, char, obj_desc->label[7]);\ ++ MC_RSP_OP(cmd, 6, 0, 8, char, obj_desc->label[8]);\ ++ MC_RSP_OP(cmd, 6, 8, 8, char, obj_desc->label[9]);\ ++ MC_RSP_OP(cmd, 6, 16, 8, char, obj_desc->label[10]);\ ++ MC_RSP_OP(cmd, 6, 24, 8, char, obj_desc->label[11]);\ ++ MC_RSP_OP(cmd, 6, 32, 8, char, obj_desc->label[12]);\ ++ MC_RSP_OP(cmd, 6, 40, 8, char, obj_desc->label[13]);\ ++ MC_RSP_OP(cmd, 6, 48, 8, char, obj_desc->label[14]);\ ++ MC_RSP_OP(cmd, 6, 56, 8, char, obj_desc->label[15]);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_GET_OBJ_DESC(cmd, obj_type, obj_id) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, obj_id);\ ++ MC_CMD_OP(cmd, 1, 0, 8, char, obj_type[0]);\ ++ MC_CMD_OP(cmd, 1, 8, 8, char, obj_type[1]);\ ++ MC_CMD_OP(cmd, 1, 16, 8, char, obj_type[2]);\ ++ MC_CMD_OP(cmd, 1, 24, 8, char, obj_type[3]);\ ++ MC_CMD_OP(cmd, 1, 32, 8, char, obj_type[4]);\ ++ MC_CMD_OP(cmd, 1, 40, 8, char, obj_type[5]);\ ++ MC_CMD_OP(cmd, 1, 48, 8, char, obj_type[6]);\ ++ MC_CMD_OP(cmd, 1, 56, 8, char, obj_type[7]);\ ++ MC_CMD_OP(cmd, 2, 0, 8, char, obj_type[8]);\ ++ MC_CMD_OP(cmd, 2, 8, 8, char, obj_type[9]);\ ++ MC_CMD_OP(cmd, 2, 16, 8, char, obj_type[10]);\ ++ MC_CMD_OP(cmd, 2, 24, 8, char, obj_type[11]);\ ++ MC_CMD_OP(cmd, 2, 32, 8, char, obj_type[12]);\ ++ MC_CMD_OP(cmd, 2, 40, 8, char, obj_type[13]);\ ++ MC_CMD_OP(cmd, 2, 48, 8, char, obj_type[14]);\ ++ MC_CMD_OP(cmd, 2, 56, 8, char, obj_type[15]);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_RSP_GET_OBJ_DESC(cmd, obj_desc) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 32, 32, int, obj_desc->id); \ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, obj_desc->vendor); \ ++ MC_RSP_OP(cmd, 1, 16, 8, uint8_t, obj_desc->irq_count); \ ++ MC_RSP_OP(cmd, 1, 24, 8, uint8_t, obj_desc->region_count); \ ++ MC_RSP_OP(cmd, 1, 32, 32, uint32_t, obj_desc->state);\ ++ MC_RSP_OP(cmd, 2, 0, 16, uint16_t, obj_desc->ver_major);\ ++ MC_RSP_OP(cmd, 2, 16, 16, uint16_t, obj_desc->ver_minor);\ ++ MC_RSP_OP(cmd, 2, 32, 16, uint16_t, obj_desc->flags); \ ++ MC_RSP_OP(cmd, 3, 0, 8, char, obj_desc->type[0]);\ ++ MC_RSP_OP(cmd, 3, 8, 8, char, obj_desc->type[1]);\ ++ MC_RSP_OP(cmd, 3, 16, 8, char, obj_desc->type[2]);\ ++ MC_RSP_OP(cmd, 3, 24, 8, char, obj_desc->type[3]);\ ++ MC_RSP_OP(cmd, 3, 32, 8, char, obj_desc->type[4]);\ ++ MC_RSP_OP(cmd, 3, 40, 8, char, obj_desc->type[5]);\ ++ MC_RSP_OP(cmd, 3, 48, 8, char, obj_desc->type[6]);\ ++ MC_RSP_OP(cmd, 3, 56, 8, char, obj_desc->type[7]);\ ++ MC_RSP_OP(cmd, 4, 0, 8, char, obj_desc->type[8]);\ ++ MC_RSP_OP(cmd, 4, 8, 8, char, obj_desc->type[9]);\ ++ MC_RSP_OP(cmd, 4, 16, 8, char, obj_desc->type[10]);\ ++ MC_RSP_OP(cmd, 4, 24, 8, char, obj_desc->type[11]);\ ++ MC_RSP_OP(cmd, 4, 32, 8, char, obj_desc->type[12]);\ ++ MC_RSP_OP(cmd, 4, 40, 8, char, obj_desc->type[13]);\ ++ MC_RSP_OP(cmd, 4, 48, 8, char, obj_desc->type[14]);\ ++ MC_RSP_OP(cmd, 4, 56, 8, char, obj_desc->type[15]);\ ++ MC_RSP_OP(cmd, 5, 0, 8, char, obj_desc->label[0]);\ ++ MC_RSP_OP(cmd, 5, 8, 8, char, obj_desc->label[1]);\ ++ MC_RSP_OP(cmd, 5, 16, 8, char, obj_desc->label[2]);\ ++ MC_RSP_OP(cmd, 5, 24, 8, char, obj_desc->label[3]);\ ++ MC_RSP_OP(cmd, 5, 32, 8, char, obj_desc->label[4]);\ ++ MC_RSP_OP(cmd, 5, 40, 8, char, obj_desc->label[5]);\ ++ MC_RSP_OP(cmd, 5, 48, 8, char, obj_desc->label[6]);\ ++ MC_RSP_OP(cmd, 5, 56, 8, char, obj_desc->label[7]);\ ++ MC_RSP_OP(cmd, 6, 0, 8, char, obj_desc->label[8]);\ ++ MC_RSP_OP(cmd, 6, 8, 8, char, obj_desc->label[9]);\ ++ MC_RSP_OP(cmd, 6, 16, 8, char, obj_desc->label[10]);\ ++ MC_RSP_OP(cmd, 6, 24, 8, char, obj_desc->label[11]);\ ++ MC_RSP_OP(cmd, 6, 32, 8, char, obj_desc->label[12]);\ ++ MC_RSP_OP(cmd, 6, 40, 8, char, obj_desc->label[13]);\ ++ MC_RSP_OP(cmd, 6, 48, 8, char, obj_desc->label[14]);\ ++ MC_RSP_OP(cmd, 6, 56, 8, char, obj_desc->label[15]);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_GET_RES_COUNT(cmd, type) \ ++do { \ ++ MC_CMD_OP(cmd, 1, 0, 8, char, type[0]);\ ++ MC_CMD_OP(cmd, 1, 8, 8, char, type[1]);\ ++ MC_CMD_OP(cmd, 1, 16, 8, char, type[2]);\ ++ MC_CMD_OP(cmd, 1, 24, 8, char, type[3]);\ ++ MC_CMD_OP(cmd, 1, 32, 8, char, type[4]);\ ++ MC_CMD_OP(cmd, 1, 40, 8, char, type[5]);\ ++ MC_CMD_OP(cmd, 1, 48, 8, char, type[6]);\ ++ MC_CMD_OP(cmd, 1, 56, 8, char, type[7]);\ ++ MC_CMD_OP(cmd, 2, 0, 8, char, type[8]);\ ++ MC_CMD_OP(cmd, 2, 8, 8, char, type[9]);\ ++ MC_CMD_OP(cmd, 2, 16, 8, char, type[10]);\ ++ MC_CMD_OP(cmd, 2, 24, 8, char, type[11]);\ ++ MC_CMD_OP(cmd, 2, 32, 8, char, type[12]);\ ++ MC_CMD_OP(cmd, 2, 40, 8, char, type[13]);\ ++ MC_CMD_OP(cmd, 2, 48, 8, char, type[14]);\ ++ MC_CMD_OP(cmd, 2, 56, 8, char, type[15]);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_RSP_GET_RES_COUNT(cmd, res_count) \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, res_count) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_GET_RES_IDS(cmd, range_desc, type) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 42, 7, enum dprc_iter_status, \ ++ range_desc->iter_status); \ ++ MC_CMD_OP(cmd, 1, 0, 32, int, range_desc->base_id); \ ++ MC_CMD_OP(cmd, 1, 32, 32, int, range_desc->last_id);\ ++ MC_CMD_OP(cmd, 2, 0, 8, char, type[0]);\ ++ MC_CMD_OP(cmd, 2, 8, 8, char, type[1]);\ ++ MC_CMD_OP(cmd, 2, 16, 8, char, type[2]);\ ++ MC_CMD_OP(cmd, 2, 24, 8, char, type[3]);\ ++ MC_CMD_OP(cmd, 2, 32, 8, char, type[4]);\ ++ MC_CMD_OP(cmd, 2, 40, 8, char, type[5]);\ ++ MC_CMD_OP(cmd, 2, 48, 8, char, type[6]);\ ++ MC_CMD_OP(cmd, 2, 56, 8, char, type[7]);\ ++ MC_CMD_OP(cmd, 3, 0, 8, char, type[8]);\ ++ MC_CMD_OP(cmd, 3, 8, 8, char, type[9]);\ ++ MC_CMD_OP(cmd, 3, 16, 8, char, type[10]);\ ++ MC_CMD_OP(cmd, 3, 24, 8, char, type[11]);\ ++ MC_CMD_OP(cmd, 3, 32, 8, char, type[12]);\ ++ MC_CMD_OP(cmd, 3, 40, 8, char, type[13]);\ ++ MC_CMD_OP(cmd, 3, 48, 8, char, type[14]);\ ++ MC_CMD_OP(cmd, 3, 56, 8, char, type[15]);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_RSP_GET_RES_IDS(cmd, range_desc) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 42, 7, enum dprc_iter_status, \ ++ range_desc->iter_status);\ ++ MC_RSP_OP(cmd, 1, 0, 32, int, range_desc->base_id); \ ++ MC_RSP_OP(cmd, 1, 32, 32, int, range_desc->last_id);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_GET_OBJ_REGION(cmd, obj_type, obj_id, region_index) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, obj_id); \ ++ MC_CMD_OP(cmd, 0, 48, 8, uint8_t, region_index);\ ++ MC_CMD_OP(cmd, 3, 0, 8, char, obj_type[0]);\ ++ MC_CMD_OP(cmd, 3, 8, 8, char, obj_type[1]);\ ++ MC_CMD_OP(cmd, 3, 16, 8, char, obj_type[2]);\ ++ MC_CMD_OP(cmd, 3, 24, 8, char, obj_type[3]);\ ++ MC_CMD_OP(cmd, 3, 32, 8, char, obj_type[4]);\ ++ MC_CMD_OP(cmd, 3, 40, 8, char, obj_type[5]);\ ++ MC_CMD_OP(cmd, 3, 48, 8, char, obj_type[6]);\ ++ MC_CMD_OP(cmd, 3, 56, 8, char, obj_type[7]);\ ++ MC_CMD_OP(cmd, 4, 0, 8, char, obj_type[8]);\ ++ MC_CMD_OP(cmd, 4, 8, 8, char, obj_type[9]);\ ++ MC_CMD_OP(cmd, 4, 16, 8, char, obj_type[10]);\ ++ MC_CMD_OP(cmd, 4, 24, 8, char, obj_type[11]);\ ++ MC_CMD_OP(cmd, 4, 32, 8, char, obj_type[12]);\ ++ MC_CMD_OP(cmd, 4, 40, 8, char, obj_type[13]);\ ++ MC_CMD_OP(cmd, 4, 48, 8, char, obj_type[14]);\ ++ MC_CMD_OP(cmd, 4, 56, 8, char, obj_type[15]);\ ++} while (0) ++ ++/* param, offset, width, type, arg_name */ ++#define DPRC_RSP_GET_OBJ_REGION(cmd, region_desc) \ ++do { \ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, region_desc->base_offset);\ ++ MC_RSP_OP(cmd, 2, 0, 32, uint32_t, region_desc->size); \ ++ MC_RSP_OP(cmd, 2, 32, 4, enum dprc_region_type, region_desc->type);\ ++ MC_RSP_OP(cmd, 3, 0, 32, uint32_t, region_desc->flags);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_SET_OBJ_LABEL(cmd, obj_type, obj_id, label) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, obj_id); \ ++ MC_CMD_OP(cmd, 1, 0, 8, char, label[0]);\ ++ MC_CMD_OP(cmd, 1, 8, 8, char, label[1]);\ ++ MC_CMD_OP(cmd, 1, 16, 8, char, label[2]);\ ++ MC_CMD_OP(cmd, 1, 24, 8, char, label[3]);\ ++ MC_CMD_OP(cmd, 1, 32, 8, char, label[4]);\ ++ MC_CMD_OP(cmd, 1, 40, 8, char, label[5]);\ ++ MC_CMD_OP(cmd, 1, 48, 8, char, label[6]);\ ++ MC_CMD_OP(cmd, 1, 56, 8, char, label[7]);\ ++ MC_CMD_OP(cmd, 2, 0, 8, char, label[8]);\ ++ MC_CMD_OP(cmd, 2, 8, 8, char, label[9]);\ ++ MC_CMD_OP(cmd, 2, 16, 8, char, label[10]);\ ++ MC_CMD_OP(cmd, 2, 24, 8, char, label[11]);\ ++ MC_CMD_OP(cmd, 2, 32, 8, char, label[12]);\ ++ MC_CMD_OP(cmd, 2, 40, 8, char, label[13]);\ ++ MC_CMD_OP(cmd, 2, 48, 8, char, label[14]);\ ++ MC_CMD_OP(cmd, 2, 56, 8, char, label[15]);\ ++ MC_CMD_OP(cmd, 3, 0, 8, char, obj_type[0]);\ ++ MC_CMD_OP(cmd, 3, 8, 8, char, obj_type[1]);\ ++ MC_CMD_OP(cmd, 3, 16, 8, char, obj_type[2]);\ ++ MC_CMD_OP(cmd, 3, 24, 8, char, obj_type[3]);\ ++ MC_CMD_OP(cmd, 3, 32, 8, char, obj_type[4]);\ ++ MC_CMD_OP(cmd, 3, 40, 8, char, obj_type[5]);\ ++ MC_CMD_OP(cmd, 3, 48, 8, char, obj_type[6]);\ ++ MC_CMD_OP(cmd, 3, 56, 8, char, obj_type[7]);\ ++ MC_CMD_OP(cmd, 4, 0, 8, char, obj_type[8]);\ ++ MC_CMD_OP(cmd, 4, 8, 8, char, obj_type[9]);\ ++ MC_CMD_OP(cmd, 4, 16, 8, char, obj_type[10]);\ ++ MC_CMD_OP(cmd, 4, 24, 8, char, obj_type[11]);\ ++ MC_CMD_OP(cmd, 4, 32, 8, char, obj_type[12]);\ ++ MC_CMD_OP(cmd, 4, 40, 8, char, obj_type[13]);\ ++ MC_CMD_OP(cmd, 4, 48, 8, char, obj_type[14]);\ ++ MC_CMD_OP(cmd, 4, 56, 8, char, obj_type[15]);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_SET_OBJ_IRQ(cmd, obj_type, obj_id, irq_index, irq_cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index); \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\ ++ MC_CMD_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++ MC_CMD_OP(cmd, 2, 32, 32, int, obj_id); \ ++ MC_CMD_OP(cmd, 3, 0, 8, char, obj_type[0]);\ ++ MC_CMD_OP(cmd, 3, 8, 8, char, obj_type[1]);\ ++ MC_CMD_OP(cmd, 3, 16, 8, char, obj_type[2]);\ ++ MC_CMD_OP(cmd, 3, 24, 8, char, obj_type[3]);\ ++ MC_CMD_OP(cmd, 3, 32, 8, char, obj_type[4]);\ ++ MC_CMD_OP(cmd, 3, 40, 8, char, obj_type[5]);\ ++ MC_CMD_OP(cmd, 3, 48, 8, char, obj_type[6]);\ ++ MC_CMD_OP(cmd, 3, 56, 8, char, obj_type[7]);\ ++ MC_CMD_OP(cmd, 4, 0, 8, char, obj_type[8]);\ ++ MC_CMD_OP(cmd, 4, 8, 8, char, obj_type[9]);\ ++ MC_CMD_OP(cmd, 4, 16, 8, char, obj_type[10]);\ ++ MC_CMD_OP(cmd, 4, 24, 8, char, obj_type[11]);\ ++ MC_CMD_OP(cmd, 4, 32, 8, char, obj_type[12]);\ ++ MC_CMD_OP(cmd, 4, 40, 8, char, obj_type[13]);\ ++ MC_CMD_OP(cmd, 4, 48, 8, char, obj_type[14]);\ ++ MC_CMD_OP(cmd, 4, 56, 8, char, obj_type[15]);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_GET_OBJ_IRQ(cmd, obj_type, obj_id, irq_index) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, obj_id); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index); \ ++ MC_CMD_OP(cmd, 1, 0, 8, char, obj_type[0]);\ ++ MC_CMD_OP(cmd, 1, 8, 8, char, obj_type[1]);\ ++ MC_CMD_OP(cmd, 1, 16, 8, char, obj_type[2]);\ ++ MC_CMD_OP(cmd, 1, 24, 8, char, obj_type[3]);\ ++ MC_CMD_OP(cmd, 1, 32, 8, char, obj_type[4]);\ ++ MC_CMD_OP(cmd, 1, 40, 8, char, obj_type[5]);\ ++ MC_CMD_OP(cmd, 1, 48, 8, char, obj_type[6]);\ ++ MC_CMD_OP(cmd, 1, 56, 8, char, obj_type[7]);\ ++ MC_CMD_OP(cmd, 2, 0, 8, char, obj_type[8]);\ ++ MC_CMD_OP(cmd, 2, 8, 8, char, obj_type[9]);\ ++ MC_CMD_OP(cmd, 2, 16, 8, char, obj_type[10]);\ ++ MC_CMD_OP(cmd, 2, 24, 8, char, obj_type[11]);\ ++ MC_CMD_OP(cmd, 2, 32, 8, char, obj_type[12]);\ ++ MC_CMD_OP(cmd, 2, 40, 8, char, obj_type[13]);\ ++ MC_CMD_OP(cmd, 2, 48, 8, char, obj_type[14]);\ ++ MC_CMD_OP(cmd, 2, 56, 8, char, obj_type[15]);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_RSP_GET_OBJ_IRQ(cmd, type, irq_cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\ ++ MC_RSP_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, type); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_CONNECT(cmd, endpoint1, endpoint2, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, endpoint1->id); \ ++ MC_CMD_OP(cmd, 0, 32, 16, uint16_t, endpoint1->if_id); \ ++ MC_CMD_OP(cmd, 1, 0, 32, int, endpoint2->id); \ ++ MC_CMD_OP(cmd, 1, 32, 16, uint16_t, endpoint2->if_id); \ ++ MC_CMD_OP(cmd, 2, 0, 8, char, endpoint1->type[0]); \ ++ MC_CMD_OP(cmd, 2, 8, 8, char, endpoint1->type[1]); \ ++ MC_CMD_OP(cmd, 2, 16, 8, char, endpoint1->type[2]); \ ++ MC_CMD_OP(cmd, 2, 24, 8, char, endpoint1->type[3]); \ ++ MC_CMD_OP(cmd, 2, 32, 8, char, endpoint1->type[4]); \ ++ MC_CMD_OP(cmd, 2, 40, 8, char, endpoint1->type[5]); \ ++ MC_CMD_OP(cmd, 2, 48, 8, char, endpoint1->type[6]); \ ++ MC_CMD_OP(cmd, 2, 56, 8, char, endpoint1->type[7]); \ ++ MC_CMD_OP(cmd, 3, 0, 8, char, endpoint1->type[8]); \ ++ MC_CMD_OP(cmd, 3, 8, 8, char, endpoint1->type[9]); \ ++ MC_CMD_OP(cmd, 3, 16, 8, char, endpoint1->type[10]); \ ++ MC_CMD_OP(cmd, 3, 24, 8, char, endpoint1->type[11]); \ ++ MC_CMD_OP(cmd, 3, 32, 8, char, endpoint1->type[12]); \ ++ MC_CMD_OP(cmd, 3, 40, 8, char, endpoint1->type[13]); \ ++ MC_CMD_OP(cmd, 3, 48, 8, char, endpoint1->type[14]); \ ++ MC_CMD_OP(cmd, 3, 56, 8, char, endpoint1->type[15]); \ ++ MC_CMD_OP(cmd, 4, 0, 32, uint32_t, cfg->max_rate); \ ++ MC_CMD_OP(cmd, 4, 32, 32, uint32_t, cfg->committed_rate); \ ++ MC_CMD_OP(cmd, 5, 0, 8, char, endpoint2->type[0]); \ ++ MC_CMD_OP(cmd, 5, 8, 8, char, endpoint2->type[1]); \ ++ MC_CMD_OP(cmd, 5, 16, 8, char, endpoint2->type[2]); \ ++ MC_CMD_OP(cmd, 5, 24, 8, char, endpoint2->type[3]); \ ++ MC_CMD_OP(cmd, 5, 32, 8, char, endpoint2->type[4]); \ ++ MC_CMD_OP(cmd, 5, 40, 8, char, endpoint2->type[5]); \ ++ MC_CMD_OP(cmd, 5, 48, 8, char, endpoint2->type[6]); \ ++ MC_CMD_OP(cmd, 5, 56, 8, char, endpoint2->type[7]); \ ++ MC_CMD_OP(cmd, 6, 0, 8, char, endpoint2->type[8]); \ ++ MC_CMD_OP(cmd, 6, 8, 8, char, endpoint2->type[9]); \ ++ MC_CMD_OP(cmd, 6, 16, 8, char, endpoint2->type[10]); \ ++ MC_CMD_OP(cmd, 6, 24, 8, char, endpoint2->type[11]); \ ++ MC_CMD_OP(cmd, 6, 32, 8, char, endpoint2->type[12]); \ ++ MC_CMD_OP(cmd, 6, 40, 8, char, endpoint2->type[13]); \ ++ MC_CMD_OP(cmd, 6, 48, 8, char, endpoint2->type[14]); \ ++ MC_CMD_OP(cmd, 6, 56, 8, char, endpoint2->type[15]); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_DISCONNECT(cmd, endpoint) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, endpoint->id); \ ++ MC_CMD_OP(cmd, 0, 32, 16, uint16_t, endpoint->if_id); \ ++ MC_CMD_OP(cmd, 1, 0, 8, char, endpoint->type[0]); \ ++ MC_CMD_OP(cmd, 1, 8, 8, char, endpoint->type[1]); \ ++ MC_CMD_OP(cmd, 1, 16, 8, char, endpoint->type[2]); \ ++ MC_CMD_OP(cmd, 1, 24, 8, char, endpoint->type[3]); \ ++ MC_CMD_OP(cmd, 1, 32, 8, char, endpoint->type[4]); \ ++ MC_CMD_OP(cmd, 1, 40, 8, char, endpoint->type[5]); \ ++ MC_CMD_OP(cmd, 1, 48, 8, char, endpoint->type[6]); \ ++ MC_CMD_OP(cmd, 1, 56, 8, char, endpoint->type[7]); \ ++ MC_CMD_OP(cmd, 2, 0, 8, char, endpoint->type[8]); \ ++ MC_CMD_OP(cmd, 2, 8, 8, char, endpoint->type[9]); \ ++ MC_CMD_OP(cmd, 2, 16, 8, char, endpoint->type[10]); \ ++ MC_CMD_OP(cmd, 2, 24, 8, char, endpoint->type[11]); \ ++ MC_CMD_OP(cmd, 2, 32, 8, char, endpoint->type[12]); \ ++ MC_CMD_OP(cmd, 2, 40, 8, char, endpoint->type[13]); \ ++ MC_CMD_OP(cmd, 2, 48, 8, char, endpoint->type[14]); \ ++ MC_CMD_OP(cmd, 2, 56, 8, char, endpoint->type[15]); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_CMD_GET_CONNECTION(cmd, endpoint1) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, endpoint1->id); \ ++ MC_CMD_OP(cmd, 0, 32, 16, uint16_t, endpoint1->if_id); \ ++ MC_CMD_OP(cmd, 1, 0, 8, char, endpoint1->type[0]); \ ++ MC_CMD_OP(cmd, 1, 8, 8, char, endpoint1->type[1]); \ ++ MC_CMD_OP(cmd, 1, 16, 8, char, endpoint1->type[2]); \ ++ MC_CMD_OP(cmd, 1, 24, 8, char, endpoint1->type[3]); \ ++ MC_CMD_OP(cmd, 1, 32, 8, char, endpoint1->type[4]); \ ++ MC_CMD_OP(cmd, 1, 40, 8, char, endpoint1->type[5]); \ ++ MC_CMD_OP(cmd, 1, 48, 8, char, endpoint1->type[6]); \ ++ MC_CMD_OP(cmd, 1, 56, 8, char, endpoint1->type[7]); \ ++ MC_CMD_OP(cmd, 2, 0, 8, char, endpoint1->type[8]); \ ++ MC_CMD_OP(cmd, 2, 8, 8, char, endpoint1->type[9]); \ ++ MC_CMD_OP(cmd, 2, 16, 8, char, endpoint1->type[10]); \ ++ MC_CMD_OP(cmd, 2, 24, 8, char, endpoint1->type[11]); \ ++ MC_CMD_OP(cmd, 2, 32, 8, char, endpoint1->type[12]); \ ++ MC_CMD_OP(cmd, 2, 40, 8, char, endpoint1->type[13]); \ ++ MC_CMD_OP(cmd, 2, 48, 8, char, endpoint1->type[14]); \ ++ MC_CMD_OP(cmd, 2, 56, 8, char, endpoint1->type[15]); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRC_RSP_GET_CONNECTION(cmd, endpoint2, state) \ ++do { \ ++ MC_RSP_OP(cmd, 3, 0, 32, int, endpoint2->id); \ ++ MC_RSP_OP(cmd, 3, 32, 16, uint16_t, endpoint2->if_id); \ ++ MC_RSP_OP(cmd, 4, 0, 8, char, endpoint2->type[0]); \ ++ MC_RSP_OP(cmd, 4, 8, 8, char, endpoint2->type[1]); \ ++ MC_RSP_OP(cmd, 4, 16, 8, char, endpoint2->type[2]); \ ++ MC_RSP_OP(cmd, 4, 24, 8, char, endpoint2->type[3]); \ ++ MC_RSP_OP(cmd, 4, 32, 8, char, endpoint2->type[4]); \ ++ MC_RSP_OP(cmd, 4, 40, 8, char, endpoint2->type[5]); \ ++ MC_RSP_OP(cmd, 4, 48, 8, char, endpoint2->type[6]); \ ++ MC_RSP_OP(cmd, 4, 56, 8, char, endpoint2->type[7]); \ ++ MC_RSP_OP(cmd, 5, 0, 8, char, endpoint2->type[8]); \ ++ MC_RSP_OP(cmd, 5, 8, 8, char, endpoint2->type[9]); \ ++ MC_RSP_OP(cmd, 5, 16, 8, char, endpoint2->type[10]); \ ++ MC_RSP_OP(cmd, 5, 24, 8, char, endpoint2->type[11]); \ ++ MC_RSP_OP(cmd, 5, 32, 8, char, endpoint2->type[12]); \ ++ MC_RSP_OP(cmd, 5, 40, 8, char, endpoint2->type[13]); \ ++ MC_RSP_OP(cmd, 5, 48, 8, char, endpoint2->type[14]); \ ++ MC_RSP_OP(cmd, 5, 56, 8, char, endpoint2->type[15]); \ ++ MC_RSP_OP(cmd, 6, 0, 32, int, state); \ ++} while (0) ++ ++#endif /* _FSL_DPRC_CMD_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dprtc.h b/drivers/net/dpaa2/mc/fsl_dprtc.h +new file mode 100644 +index 0000000..cad0693 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dprtc.h +@@ -0,0 +1,434 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPRTC_H ++#define __FSL_DPRTC_H ++ ++/* Data Path Real Time Counter API ++ * Contains initialization APIs and runtime control APIs for RTC ++ */ ++ ++struct fsl_mc_io; ++ ++/** ++ * Number of irq's ++ */ ++#define DPRTC_MAX_IRQ_NUM 1 ++#define DPRTC_IRQ_INDEX 0 ++ ++/** ++ * Interrupt event masks: ++ */ ++ ++/** ++ * Interrupt event mask indicating alarm event had occurred ++ */ ++#define DPRTC_EVENT_ALARM 0x40000000 ++/** ++ * Interrupt event mask indicating periodic pulse event had occurred ++ */ ++#define DPRTC_EVENT_PPS 0x08000000 ++ ++/** ++ * dprtc_open() - Open a control session for the specified object. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @dprtc_id: DPRTC unique ID ++ * @token: Returned token; use in subsequent API calls ++ * ++ * This function can be used to open a control session for an ++ * already created object; an object may have been declared in ++ * the DPL or by calling the dprtc_create function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent commands for ++ * this specific object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprtc_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dprtc_id, ++ uint16_t *token); ++ ++/** ++ * dprtc_close() - Close the control session of the object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRTC object ++ * ++ * After this function is called, no further operations are ++ * allowed on the object without opening a new control session. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprtc_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * struct dprtc_cfg - Structure representing DPRTC configuration ++ * @options: place holder ++ */ ++struct dprtc_cfg { ++ uint32_t options; ++}; ++ ++/** ++ * dprtc_create() - Create the DPRTC object. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @cfg: Configuration structure ++ * @token: Returned token; use in subsequent API calls ++ * ++ * Create the DPRTC object, allocate required resources and ++ * perform required initialization. ++ * ++ * The object can be created either by declaring it in the ++ * DPL file, or by calling this function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent calls to ++ * this specific object. For objects that are created using the ++ * DPL file, call dprtc_open function to get an authentication ++ * token first. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprtc_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dprtc_cfg *cfg, ++ uint16_t *token); ++ ++/** ++ * dprtc_destroy() - Destroy the DPRTC object and release all its resources. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRTC object ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dprtc_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dprtc_set_clock_offset() - Sets the clock's offset ++ * (usually relative to another clock). ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRTC object ++ * @offset: New clock offset (in nanoseconds). ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprtc_set_clock_offset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int64_t offset); ++ ++/** ++ * dprtc_set_freq_compensation() - Sets a new frequency compensation value. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRTC object ++ * @freq_compensation: ++ * The new frequency compensation value to set. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprtc_set_freq_compensation(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint32_t freq_compensation); ++ ++/** ++ * dprtc_get_freq_compensation() - Retrieves the frequency compensation value ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRTC object ++ * @freq_compensation: ++ * Frequency compensation value ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprtc_get_freq_compensation(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint32_t *freq_compensation); ++ ++/** ++ * dprtc_get_time() - Returns the current RTC time. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRTC object ++ * @time: Current RTC time. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprtc_get_time(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint64_t *time); ++ ++/** ++ * dprtc_set_time() - Updates current RTC time. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRTC object ++ * @time: New RTC time. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprtc_set_time(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint64_t time); ++ ++/** ++ * dprtc_set_alarm() - Defines and sets alarm. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRTC object ++ * @time: In nanoseconds, the time when the alarm ++ * should go off - must be a multiple of ++ * 1 microsecond ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprtc_set_alarm(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint64_t time); ++ ++/** ++ * struct dprtc_irq_cfg - IRQ configuration ++ * @addr: Address that must be written to signal a message-based interrupt ++ * @val: Value to write into irq_addr address ++ * @irq_num: A user defined number associated with this IRQ ++ */ ++struct dprtc_irq_cfg { ++ uint64_t addr; ++ uint32_t val; ++ int irq_num; ++}; ++ ++/** ++ * dprtc_set_irq() - Set IRQ information for the DPRTC to trigger an interrupt. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRTC object ++ * @irq_index: Identifies the interrupt index to configure ++ * @irq_cfg: IRQ configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprtc_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dprtc_irq_cfg *irq_cfg); ++ ++/** ++ * dprtc_get_irq() - Get IRQ information from the DPRTC. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRTC object ++ * @irq_index: The interrupt index to configure ++ * @type: Interrupt type: 0 represents message interrupt ++ * type (both irq_addr and irq_val are valid) ++ * @irq_cfg: IRQ attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprtc_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dprtc_irq_cfg *irq_cfg); ++ ++/** ++ * dprtc_set_irq_enable() - Set overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRTC object ++ * @irq_index: The interrupt index to configure ++ * @en: Interrupt state - enable = 1, disable = 0 ++ * ++ * Allows GPP software to control when interrupts are generated. ++ * Each interrupt can have up to 32 causes. The enable/disable control's the ++ * overall interrupt state. if the interrupt is disabled no causes will cause ++ * an interrupt. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprtc_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en); ++ ++/** ++ * dprtc_get_irq_enable() - Get overall interrupt state ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRTC object ++ * @irq_index: The interrupt index to configure ++ * @en: Returned interrupt state - enable = 1, disable = 0 ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprtc_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en); ++ ++/** ++ * dprtc_set_irq_mask() - Set interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRTC object ++ * @irq_index: The interrupt index to configure ++ * @mask: Event mask to trigger interrupt; ++ * each bit: ++ * 0 = ignore event ++ * 1 = consider event for asserting IRQ ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprtc_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask); ++ ++/** ++ * dprtc_get_irq_mask() - Get interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRTC object ++ * @irq_index: The interrupt index to configure ++ * @mask: Returned event mask to trigger interrupt ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprtc_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask); ++ ++/** ++ * dprtc_get_irq_status() - Get the current status of any pending interrupts. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRTC object ++ * @irq_index: The interrupt index to configure ++ * @status: Returned interrupts status - one bit per cause: ++ * 0 = no interrupt pending ++ * 1 = interrupt pending ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprtc_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status); ++ ++/** ++ * dprtc_clear_irq_status() - Clear a pending interrupt's status ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRTC object ++ * @irq_index: The interrupt index to configure ++ * @status: Bits to clear (W1C) - one bit per cause: ++ * 0 = don't change ++ * 1 = clear status bit ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprtc_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status); ++ ++/** ++ * struct dprtc_attr - Structure representing DPRTC attributes ++ * @id: DPRTC object ID ++ * @version: DPRTC version ++ */ ++struct dprtc_attr { ++ int id; ++ /** ++ * struct version - Structure representing DPRTC version ++ * @major: DPRTC major version ++ * @minor: DPRTC minor version ++ */ ++ struct { ++ uint16_t major; ++ uint16_t minor; ++ } version; ++}; ++ ++/** ++ * dprtc_get_attributes - Retrieve DPRTC attributes. ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPRTC object ++ * @attr: Returned object's attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dprtc_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dprtc_attr *attr); ++ ++#endif /* __FSL_DPRTC_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dprtc_cmd.h b/drivers/net/dpaa2/mc/fsl_dprtc_cmd.h +new file mode 100644 +index 0000000..aeccece +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dprtc_cmd.h +@@ -0,0 +1,181 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_DPRTC_CMD_H ++#define _FSL_DPRTC_CMD_H ++ ++/* DPRTC Version */ ++#define DPRTC_VER_MAJOR 1 ++#define DPRTC_VER_MINOR 0 ++ ++/* Command IDs */ ++#define DPRTC_CMDID_CLOSE 0x800 ++#define DPRTC_CMDID_OPEN 0x810 ++#define DPRTC_CMDID_CREATE 0x910 ++#define DPRTC_CMDID_DESTROY 0x900 ++ ++#define DPRTC_CMDID_ENABLE 0x002 ++#define DPRTC_CMDID_DISABLE 0x003 ++#define DPRTC_CMDID_GET_ATTR 0x004 ++#define DPRTC_CMDID_RESET 0x005 ++#define DPRTC_CMDID_IS_ENABLED 0x006 ++ ++#define DPRTC_CMDID_SET_IRQ 0x010 ++#define DPRTC_CMDID_GET_IRQ 0x011 ++#define DPRTC_CMDID_SET_IRQ_ENABLE 0x012 ++#define DPRTC_CMDID_GET_IRQ_ENABLE 0x013 ++#define DPRTC_CMDID_SET_IRQ_MASK 0x014 ++#define DPRTC_CMDID_GET_IRQ_MASK 0x015 ++#define DPRTC_CMDID_GET_IRQ_STATUS 0x016 ++#define DPRTC_CMDID_CLEAR_IRQ_STATUS 0x017 ++ ++#define DPRTC_CMDID_SET_CLOCK_OFFSET 0x1d0 ++#define DPRTC_CMDID_SET_FREQ_COMPENSATION 0x1d1 ++#define DPRTC_CMDID_GET_FREQ_COMPENSATION 0x1d2 ++#define DPRTC_CMDID_GET_TIME 0x1d3 ++#define DPRTC_CMDID_SET_TIME 0x1d4 ++#define DPRTC_CMDID_SET_ALARM 0x1d5 ++#define DPRTC_CMDID_SET_PERIODIC_PULSE 0x1d6 ++#define DPRTC_CMDID_CLEAR_PERIODIC_PULSE 0x1d7 ++#define DPRTC_CMDID_SET_EXT_TRIGGER 0x1d8 ++#define DPRTC_CMDID_CLEAR_EXT_TRIGGER 0x1d9 ++#define DPRTC_CMDID_GET_EXT_TRIGGER_TIMESTAMP 0x1dA ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_CMD_OPEN(cmd, dpbp_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpbp_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_RSP_IS_ENABLED(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, irq_index);\ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, irq_cfg->val);\ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr); \ ++ MC_CMD_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_CMD_GET_IRQ(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_RSP_GET_IRQ(cmd, type, irq_cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr); \ ++ MC_RSP_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, type); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_CMD_SET_IRQ_ENABLE(cmd, irq_index, en) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, en); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_CMD_GET_IRQ_ENABLE(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_RSP_GET_IRQ_ENABLE(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 8, uint8_t, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, mask);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_CMD_GET_IRQ_MASK(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_RSP_GET_IRQ_MASK(cmd, mask) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mask) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_RSP_GET_IRQ_STATUS(cmd, status) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, status) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_RSP_GET_ATTRIBUTES(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 32, 32, int, attr->id);\ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->version.major);\ ++ MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->version.minor);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_CMD_SET_CLOCK_OFFSET(cmd, offset) \ ++ MC_CMD_OP(cmd, 0, 0, 64, int64_t, offset) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_CMD_SET_FREQ_COMPENSATION(cmd, freq_compensation) \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, freq_compensation) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_RSP_GET_FREQ_COMPENSATION(cmd, freq_compensation) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, freq_compensation) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_RSP_GET_TIME(cmd, time) \ ++ MC_RSP_OP(cmd, 0, 0, 64, uint64_t, time) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_CMD_SET_TIME(cmd, time) \ ++ MC_CMD_OP(cmd, 0, 0, 64, uint64_t, time) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPRTC_CMD_SET_ALARM(cmd, time) \ ++ MC_CMD_OP(cmd, 0, 0, 64, uint64_t, time) ++ ++#endif /* _FSL_DPRTC_CMD_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpseci.h b/drivers/net/dpaa2/mc/fsl_dpseci.h +new file mode 100644 +index 0000000..1dd7215 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpseci.h +@@ -0,0 +1,647 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPSECI_H ++#define __FSL_DPSECI_H ++ ++/* Data Path SEC Interface API ++ * Contains initialization APIs and runtime control APIs for DPSECI ++ */ ++ ++struct fsl_mc_io; ++ ++/** ++ * General DPSECI macros ++ */ ++ ++/** ++ * Maximum number of Tx/Rx priorities per DPSECI object ++ */ ++#define DPSECI_PRIO_NUM 8 ++ ++/** ++ * All queues considered; see dpseci_set_rx_queue() ++ */ ++#define DPSECI_ALL_QUEUES (uint8_t)(-1) ++ ++/** ++ * dpseci_open() - Open a control session for the specified object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @dpseci_id: DPSECI unique ID ++ * @token: Returned token; use in subsequent API calls ++ * ++ * This function can be used to open a control session for an ++ * already created object; an object may have been declared in ++ * the DPL or by calling the dpseci_create() function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent commands for ++ * this specific object. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpseci_id, ++ uint16_t *token); ++ ++/** ++ * dpseci_close() - Close the control session of the object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * ++ * After this function is called, no further operations are ++ * allowed on the object without opening a new control session. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * struct dpseci_cfg - Structure representing DPSECI configuration ++ * @num_tx_queues: num of queues towards the SEC ++ * @num_rx_queues: num of queues back from the SEC ++ * @priorities: Priorities for the SEC hardware processing; ++ * each place in the array is the priority of the tx queue ++ * towards the SEC, ++ * valid priorities are configured with values 1-8; ++ */ ++struct dpseci_cfg { ++ uint8_t num_tx_queues; ++ uint8_t num_rx_queues; ++ uint8_t priorities[DPSECI_PRIO_NUM]; ++}; ++ ++/** ++ * dpseci_create() - Create the DPSECI object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @cfg: Configuration structure ++ * @token: Returned token; use in subsequent API calls ++ * ++ * Create the DPSECI object, allocate required resources and ++ * perform required initialization. ++ * ++ * The object can be created either by declaring it in the ++ * DPL file, or by calling this function. ++ * ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent calls to ++ * this specific object. For objects that are created using the ++ * DPL file, call dpseci_open() function to get an authentication ++ * token first. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpseci_cfg *cfg, ++ uint16_t *token); ++ ++/** ++ * dpseci_destroy() - Destroy the DPSECI object and release all its resources. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpseci_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpseci_enable() - Enable the DPSECI, allow sending and receiving frames. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpseci_disable() - Disable the DPSECI, stop sending and receiving frames. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpseci_is_enabled() - Check if the DPSECI is enabled. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * @en: Returns '1' if object is enabled; '0' otherwise ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en); ++ ++/** ++ * dpseci_reset() - Reset the DPSECI, returns the object to initial state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * struct dpseci_irq_cfg - IRQ configuration ++ * @addr: Address that must be written to signal a message-based interrupt ++ * @val: Value to write into irq_addr address ++ * @irq_num: A user defined number associated with this IRQ ++ */ ++struct dpseci_irq_cfg { ++ uint64_t addr; ++ uint32_t val; ++ int irq_num; ++}; ++ ++/** ++ * dpseci_set_irq() - Set IRQ information for the DPSECI to trigger an interrupt ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * @irq_index: Identifies the interrupt index to configure ++ * @irq_cfg: IRQ configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpseci_irq_cfg *irq_cfg); ++ ++/** ++ * dpseci_get_irq() - Get IRQ information from the DPSECI ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * @irq_index: The interrupt index to configure ++ * @type: Interrupt type: 0 represents message interrupt ++ * type (both irq_addr and irq_val are valid) ++ * @irq_cfg: IRQ attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpseci_irq_cfg *irq_cfg); ++ ++/** ++ * dpseci_set_irq_enable() - Set overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * @irq_index: The interrupt index to configure ++ * @en: Interrupt state - enable = 1, disable = 0 ++ * ++ * Allows GPP software to control when interrupts are generated. ++ * Each interrupt can have up to 32 causes. The enable/disable control's the ++ * overall interrupt state. if the interrupt is disabled no causes will cause ++ * an interrupt ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en); ++ ++/** ++ * dpseci_get_irq_enable() - Get overall interrupt state ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * @irq_index: The interrupt index to configure ++ * @en: Returned Interrupt state - enable = 1, disable = 0 ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en); ++ ++/** ++ * dpseci_set_irq_mask() - Set interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * @irq_index: The interrupt index to configure ++ * @mask: event mask to trigger interrupt; ++ * each bit: ++ * 0 = ignore event ++ * 1 = consider event for asserting IRQ ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask); ++ ++/** ++ * dpseci_get_irq_mask() - Get interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * @irq_index: The interrupt index to configure ++ * @mask: Returned event mask to trigger interrupt ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask); ++ ++/** ++ * dpseci_get_irq_status() - Get the current status of any pending interrupts ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * @irq_index: The interrupt index to configure ++ * @status: Returned interrupts status - one bit per cause: ++ * 0 = no interrupt pending ++ * 1 = interrupt pending ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status); ++ ++/** ++ * dpseci_clear_irq_status() - Clear a pending interrupt's status ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * @irq_index: The interrupt index to configure ++ * @status: bits to clear (W1C) - one bit per cause: ++ * 0 = don't change ++ * 1 = clear status bit ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status); ++ ++/** ++ * struct dpseci_attr - Structure representing DPSECI attributes ++ * @id: DPSECI object ID ++ * @version: DPSECI version ++ * @num_tx_queues: number of queues towards the SEC ++ * @num_rx_queues: number of queues back from the SEC ++ */ ++struct dpseci_attr { ++ int id; ++ /** ++ * struct version - DPSECI version ++ * @major: DPSECI major version ++ * @minor: DPSECI minor version ++ */ ++ struct { ++ uint16_t major; ++ uint16_t minor; ++ } version; ++ uint8_t num_tx_queues; ++ uint8_t num_rx_queues; ++}; ++ ++/** ++ * dpseci_get_attributes() - Retrieve DPSECI attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * @attr: Returned object's attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpseci_attr *attr); ++ ++/** ++ * enum dpseci_dest - DPSECI destination types ++ * @DPSECI_DEST_NONE: Unassigned destination; The queue is set in parked mode ++ * and does not generate FQDAN notifications; user is expected to ++ * dequeue from the queue based on polling or other user-defined ++ * method ++ * @DPSECI_DEST_DPIO: The queue is set in schedule mode and generates FQDAN ++ * notifications to the specified DPIO; user is expected to dequeue ++ * from the queue only after notification is received ++ * @DPSECI_DEST_DPCON: The queue is set in schedule mode and does not generate ++ * FQDAN notifications, but is connected to the specified DPCON ++ * object; user is expected to dequeue from the DPCON channel ++ */ ++enum dpseci_dest { ++ DPSECI_DEST_NONE = 0, ++ DPSECI_DEST_DPIO = 1, ++ DPSECI_DEST_DPCON = 2 ++}; ++ ++/** ++ * struct dpseci_dest_cfg - Structure representing DPSECI destination parameters ++ * @dest_type: Destination type ++ * @dest_id: Either DPIO ID or DPCON ID, depending on the destination type ++ * @priority: Priority selection within the DPIO or DPCON channel; valid values ++ * are 0-1 or 0-7, depending on the number of priorities in that ++ * channel; not relevant for 'DPSECI_DEST_NONE' option ++ */ ++struct dpseci_dest_cfg { ++ enum dpseci_dest dest_type; ++ int dest_id; ++ uint8_t priority; ++}; ++ ++/** ++ * DPSECI queue modification options ++ */ ++ ++/** ++ * Select to modify the user's context associated with the queue ++ */ ++#define DPSECI_QUEUE_OPT_USER_CTX 0x00000001 ++ ++/** ++ * Select to modify the queue's destination ++ */ ++#define DPSECI_QUEUE_OPT_DEST 0x00000002 ++ ++/** ++ * Select to modify the queue's order preservation ++ */ ++#define DPSECI_QUEUE_OPT_ORDER_PRESERVATION 0x00000004 ++ ++/** ++ * struct dpseci_rx_queue_cfg - DPSECI RX queue configuration ++ * @options: Flags representing the suggested modifications to the queue; ++ * Use any combination of 'DPSECI_QUEUE_OPT_' flags ++ * @order_preservation_en: order preservation configuration for the rx queue ++ * valid only if 'DPSECI_QUEUE_OPT_ORDER_PRESERVATION' is contained in 'options' ++ * @user_ctx: User context value provided in the frame descriptor of each ++ * dequeued frame; ++ * valid only if 'DPSECI_QUEUE_OPT_USER_CTX' is contained in 'options' ++ * @dest_cfg: Queue destination parameters; ++ * valid only if 'DPSECI_QUEUE_OPT_DEST' is contained in 'options' ++ */ ++struct dpseci_rx_queue_cfg { ++ uint32_t options; ++ int order_preservation_en; ++ uint64_t user_ctx; ++ struct dpseci_dest_cfg dest_cfg; ++}; ++ ++/** ++ * dpseci_set_rx_queue() - Set Rx queue configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * @queue: Select the queue relative to number of ++ * priorities configured at DPSECI creation; use ++ * DPSECI_ALL_QUEUES to configure all Rx queues identically. ++ * @cfg: Rx queue configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_set_rx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t queue, ++ const struct dpseci_rx_queue_cfg *cfg); ++ ++/** ++ * struct dpseci_rx_queue_attr - Structure representing attributes of Rx queues ++ * @user_ctx: User context value provided in the frame descriptor of each ++ * dequeued frame ++ * @order_preservation_en: Status of the order preservation configuration ++ * on the queue ++ * @dest_cfg: Queue destination configuration ++ * @fqid: Virtual FQID value to be used for dequeue operations ++ */ ++struct dpseci_rx_queue_attr { ++ uint64_t user_ctx; ++ int order_preservation_en; ++ struct dpseci_dest_cfg dest_cfg; ++ uint32_t fqid; ++}; ++ ++/** ++ * dpseci_get_rx_queue() - Retrieve Rx queue attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * @queue: Select the queue relative to number of ++ * priorities configured at DPSECI creation ++ * @attr: Returned Rx queue attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_get_rx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t queue, ++ struct dpseci_rx_queue_attr *attr); ++ ++/** ++ * struct dpseci_tx_queue_attr - Structure representing attributes of Tx queues ++ * @fqid: Virtual FQID to be used for sending frames to SEC hardware ++ * @priority: SEC hardware processing priority for the queue ++ */ ++struct dpseci_tx_queue_attr { ++ uint32_t fqid; ++ uint8_t priority; ++}; ++ ++/** ++ * dpseci_get_tx_queue() - Retrieve Tx queue attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * @queue: Select the queue relative to number of ++ * priorities configured at DPSECI creation ++ * @attr: Returned Tx queue attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_get_tx_queue(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t queue, ++ struct dpseci_tx_queue_attr *attr); ++ ++/** ++ * struct dpseci_sec_attr - Structure representing attributes of the SEC ++ * hardware accelerator ++ * @ip_id: ID for SEC. ++ * @major_rev: Major revision number for SEC. ++ * @minor_rev: Minor revision number for SEC. ++ * @era: SEC Era. ++ * @deco_num: The number of copies of the DECO that are implemented in ++ * this version of SEC. ++ * @zuc_auth_acc_num: The number of copies of ZUCA that are implemented ++ * in this version of SEC. ++ * @zuc_enc_acc_num: The number of copies of ZUCE that are implemented ++ * in this version of SEC. ++ * @snow_f8_acc_num: The number of copies of the SNOW-f8 module that are ++ * implemented in this version of SEC. ++ * @snow_f9_acc_num: The number of copies of the SNOW-f9 module that are ++ * implemented in this version of SEC. ++ * @crc_acc_num: The number of copies of the CRC module that are implemented ++ * in this version of SEC. ++ * @pk_acc_num: The number of copies of the Public Key module that are ++ * implemented in this version of SEC. ++ * @kasumi_acc_num: The number of copies of the Kasumi module that are ++ * implemented in this version of SEC. ++ * @rng_acc_num: The number of copies of the Random Number Generator that are ++ * implemented in this version of SEC. ++ * @md_acc_num: The number of copies of the MDHA (Hashing module) that are ++ * implemented in this version of SEC. ++ * @arc4_acc_num: The number of copies of the ARC4 module that are implemented ++ * in this version of SEC. ++ * @des_acc_num: The number of copies of the DES module that are implemented ++ * in this version of SEC. ++ * @aes_acc_num: The number of copies of the AES module that are implemented ++ * in this version of SEC. ++ **/ ++ ++struct dpseci_sec_attr { ++ uint16_t ip_id; ++ uint8_t major_rev; ++ uint8_t minor_rev; ++ uint8_t era; ++ uint8_t deco_num; ++ uint8_t zuc_auth_acc_num; ++ uint8_t zuc_enc_acc_num; ++ uint8_t snow_f8_acc_num; ++ uint8_t snow_f9_acc_num; ++ uint8_t crc_acc_num; ++ uint8_t pk_acc_num; ++ uint8_t kasumi_acc_num; ++ uint8_t rng_acc_num; ++ uint8_t md_acc_num; ++ uint8_t arc4_acc_num; ++ uint8_t des_acc_num; ++ uint8_t aes_acc_num; ++}; ++ ++/** ++ * dpseci_get_sec_attr() - Retrieve SEC accelerator attributes. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * @attr: Returned SEC attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_get_sec_attr(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpseci_sec_attr *attr); ++ ++/** ++ * struct dpseci_sec_counters - Structure representing global SEC counters and ++ * not per dpseci counters ++ * @dequeued_requests: Number of Requests Dequeued ++ * @ob_enc_requests: Number of Outbound Encrypt Requests ++ * @ib_dec_requests: Number of Inbound Decrypt Requests ++ * @ob_enc_bytes: Number of Outbound Bytes Encrypted ++ * @ob_prot_bytes: Number of Outbound Bytes Protected ++ * @ib_dec_bytes: Number of Inbound Bytes Decrypted ++ * @ib_valid_bytes: Number of Inbound Bytes Validated ++ */ ++struct dpseci_sec_counters { ++ uint64_t dequeued_requests; ++ uint64_t ob_enc_requests; ++ uint64_t ib_dec_requests; ++ uint64_t ob_enc_bytes; ++ uint64_t ob_prot_bytes; ++ uint64_t ib_dec_bytes; ++ uint64_t ib_valid_bytes; ++}; ++ ++/** ++ * dpseci_get_sec_counters() - Retrieve SEC accelerator counters. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSECI object ++ * @counters: Returned SEC counters ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpseci_get_sec_counters(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpseci_sec_counters *counters); ++ ++#endif /* __FSL_DPSECI_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpseci_cmd.h b/drivers/net/dpaa2/mc/fsl_dpseci_cmd.h +new file mode 100644 +index 0000000..6c0b96e +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpseci_cmd.h +@@ -0,0 +1,241 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_DPSECI_CMD_H ++#define _FSL_DPSECI_CMD_H ++ ++/* DPSECI Version */ ++#define DPSECI_VER_MAJOR 3 ++#define DPSECI_VER_MINOR 1 ++ ++/* Command IDs */ ++#define DPSECI_CMDID_CLOSE 0x800 ++#define DPSECI_CMDID_OPEN 0x809 ++#define DPSECI_CMDID_CREATE 0x909 ++#define DPSECI_CMDID_DESTROY 0x900 ++ ++#define DPSECI_CMDID_ENABLE 0x002 ++#define DPSECI_CMDID_DISABLE 0x003 ++#define DPSECI_CMDID_GET_ATTR 0x004 ++#define DPSECI_CMDID_RESET 0x005 ++#define DPSECI_CMDID_IS_ENABLED 0x006 ++ ++#define DPSECI_CMDID_SET_IRQ 0x010 ++#define DPSECI_CMDID_GET_IRQ 0x011 ++#define DPSECI_CMDID_SET_IRQ_ENABLE 0x012 ++#define DPSECI_CMDID_GET_IRQ_ENABLE 0x013 ++#define DPSECI_CMDID_SET_IRQ_MASK 0x014 ++#define DPSECI_CMDID_GET_IRQ_MASK 0x015 ++#define DPSECI_CMDID_GET_IRQ_STATUS 0x016 ++#define DPSECI_CMDID_CLEAR_IRQ_STATUS 0x017 ++ ++#define DPSECI_CMDID_SET_RX_QUEUE 0x194 ++#define DPSECI_CMDID_GET_RX_QUEUE 0x196 ++#define DPSECI_CMDID_GET_TX_QUEUE 0x197 ++#define DPSECI_CMDID_GET_SEC_ATTR 0x198 ++#define DPSECI_CMDID_GET_SEC_COUNTERS 0x199 ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_CMD_OPEN(cmd, dpseci_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpseci_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_CMD_CREATE(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, cfg->priorities[0]);\ ++ MC_CMD_OP(cmd, 0, 8, 8, uint8_t, cfg->priorities[1]);\ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, cfg->priorities[2]);\ ++ MC_CMD_OP(cmd, 0, 24, 8, uint8_t, cfg->priorities[3]);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->priorities[4]);\ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, cfg->priorities[5]);\ ++ MC_CMD_OP(cmd, 0, 48, 8, uint8_t, cfg->priorities[6]);\ ++ MC_CMD_OP(cmd, 0, 56, 8, uint8_t, cfg->priorities[7]);\ ++ MC_CMD_OP(cmd, 1, 0, 8, uint8_t, cfg->num_tx_queues);\ ++ MC_CMD_OP(cmd, 1, 8, 8, uint8_t, cfg->num_rx_queues);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_RSP_IS_ENABLED(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, irq_index);\ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, irq_cfg->val);\ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\ ++ MC_CMD_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_CMD_GET_IRQ(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_RSP_GET_IRQ(cmd, type, irq_cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\ ++ MC_RSP_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, type); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_CMD_SET_IRQ_ENABLE(cmd, irq_index, enable_state) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, enable_state); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_CMD_GET_IRQ_ENABLE(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_RSP_GET_IRQ_ENABLE(cmd, enable_state) \ ++ MC_RSP_OP(cmd, 0, 0, 8, uint8_t, enable_state) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, mask); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_CMD_GET_IRQ_MASK(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_RSP_GET_IRQ_MASK(cmd, mask) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mask) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_RSP_GET_IRQ_STATUS(cmd, status) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, status) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_RSP_GET_ATTR(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, attr->id); \ ++ MC_RSP_OP(cmd, 1, 0, 8, uint8_t, attr->num_tx_queues); \ ++ MC_RSP_OP(cmd, 1, 8, 8, uint8_t, attr->num_rx_queues); \ ++ MC_RSP_OP(cmd, 5, 0, 16, uint16_t, attr->version.major);\ ++ MC_RSP_OP(cmd, 5, 16, 16, uint16_t, attr->version.minor);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_CMD_SET_RX_QUEUE(cmd, queue, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, cfg->dest_cfg.dest_id); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->dest_cfg.priority); \ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, queue); \ ++ MC_CMD_OP(cmd, 0, 48, 4, enum dpseci_dest, cfg->dest_cfg.dest_type); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, cfg->user_ctx); \ ++ MC_CMD_OP(cmd, 2, 0, 32, uint32_t, cfg->options);\ ++ MC_CMD_OP(cmd, 2, 32, 1, int, cfg->order_preservation_en);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_CMD_GET_RX_QUEUE(cmd, queue) \ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, queue) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_RSP_GET_RX_QUEUE(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, int, attr->dest_cfg.dest_id);\ ++ MC_RSP_OP(cmd, 0, 32, 8, uint8_t, attr->dest_cfg.priority);\ ++ MC_RSP_OP(cmd, 0, 48, 4, enum dpseci_dest, attr->dest_cfg.dest_type);\ ++ MC_RSP_OP(cmd, 1, 0, 8, uint64_t, attr->user_ctx);\ ++ MC_RSP_OP(cmd, 2, 0, 32, uint32_t, attr->fqid);\ ++ MC_RSP_OP(cmd, 2, 32, 1, int, attr->order_preservation_en);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_CMD_GET_TX_QUEUE(cmd, queue) \ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, queue) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_RSP_GET_TX_QUEUE(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 32, 32, uint32_t, attr->fqid);\ ++ MC_RSP_OP(cmd, 1, 0, 8, uint8_t, attr->priority);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_RSP_GET_SEC_ATTR(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 16, uint16_t, attr->ip_id);\ ++ MC_RSP_OP(cmd, 0, 16, 8, uint8_t, attr->major_rev);\ ++ MC_RSP_OP(cmd, 0, 24, 8, uint8_t, attr->minor_rev);\ ++ MC_RSP_OP(cmd, 0, 32, 8, uint8_t, attr->era);\ ++ MC_RSP_OP(cmd, 1, 0, 8, uint8_t, attr->deco_num);\ ++ MC_RSP_OP(cmd, 1, 8, 8, uint8_t, attr->zuc_auth_acc_num);\ ++ MC_RSP_OP(cmd, 1, 16, 8, uint8_t, attr->zuc_enc_acc_num);\ ++ MC_RSP_OP(cmd, 1, 32, 8, uint8_t, attr->snow_f8_acc_num);\ ++ MC_RSP_OP(cmd, 1, 40, 8, uint8_t, attr->snow_f9_acc_num);\ ++ MC_RSP_OP(cmd, 1, 48, 8, uint8_t, attr->crc_acc_num);\ ++ MC_RSP_OP(cmd, 2, 0, 8, uint8_t, attr->pk_acc_num);\ ++ MC_RSP_OP(cmd, 2, 8, 8, uint8_t, attr->kasumi_acc_num);\ ++ MC_RSP_OP(cmd, 2, 16, 8, uint8_t, attr->rng_acc_num);\ ++ MC_RSP_OP(cmd, 2, 32, 8, uint8_t, attr->md_acc_num);\ ++ MC_RSP_OP(cmd, 2, 40, 8, uint8_t, attr->arc4_acc_num);\ ++ MC_RSP_OP(cmd, 2, 48, 8, uint8_t, attr->des_acc_num);\ ++ MC_RSP_OP(cmd, 2, 56, 8, uint8_t, attr->aes_acc_num);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSECI_RSP_GET_SEC_COUNTERS(cmd, counters) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 64, uint64_t, counters->dequeued_requests);\ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, counters->ob_enc_requests);\ ++ MC_RSP_OP(cmd, 2, 0, 64, uint64_t, counters->ib_dec_requests);\ ++ MC_RSP_OP(cmd, 3, 0, 64, uint64_t, counters->ob_enc_bytes);\ ++ MC_RSP_OP(cmd, 4, 0, 64, uint64_t, counters->ob_prot_bytes);\ ++ MC_RSP_OP(cmd, 5, 0, 64, uint64_t, counters->ib_dec_bytes);\ ++ MC_RSP_OP(cmd, 6, 0, 64, uint64_t, counters->ib_valid_bytes);\ ++} while (0) ++ ++#endif /* _FSL_DPSECI_CMD_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpsw.h b/drivers/net/dpaa2/mc/fsl_dpsw.h +new file mode 100644 +index 0000000..9c1bd9d +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpsw.h +@@ -0,0 +1,2164 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPSW_H ++#define __FSL_DPSW_H ++ ++#include ++ ++/* Data Path L2-Switch API ++ * Contains API for handling DPSW topology and functionality ++ */ ++ ++struct fsl_mc_io; ++ ++/** ++ * DPSW general definitions ++ */ ++ ++/** ++ * Maximum number of traffic class priorities ++ */ ++#define DPSW_MAX_PRIORITIES 8 ++/** ++ * Maximum number of interfaces ++ */ ++#define DPSW_MAX_IF 64 ++ ++/** ++ * dpsw_open() - Open a control session for the specified object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @dpsw_id: DPSW unique ID ++ * @token: Returned token; use in subsequent API calls ++ * ++ * This function can be used to open a control session for an ++ * already created object; an object may have been declared in ++ * the DPL or by calling the dpsw_create() function. ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent commands for ++ * this specific object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_open(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ int dpsw_id, ++ uint16_t *token); ++ ++/** ++ * dpsw_close() - Close the control session of the object ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * ++ * After this function is called, no further operations are ++ * allowed on the object without opening a new control session. ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_close(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * DPSW options ++ */ ++ ++/** ++ * Disable flooding ++ */ ++#define DPSW_OPT_FLOODING_DIS 0x0000000000000001ULL ++/** ++ * Disable Multicast ++ */ ++#define DPSW_OPT_MULTICAST_DIS 0x0000000000000004ULL ++/** ++ * Support control interface ++ */ ++#define DPSW_OPT_CTRL_IF_DIS 0x0000000000000010ULL ++/** ++ * Disable flooding metering ++ */ ++#define DPSW_OPT_FLOODING_METERING_DIS 0x0000000000000020ULL ++/** ++ * Enable metering ++ */ ++#define DPSW_OPT_METERING_EN 0x0000000000000040ULL ++ ++/** ++ * enum dpsw_component_type - component type of a bridge ++ * @DPSW_COMPONENT_TYPE_C_VLAN: A C-VLAN component of an ++ * enterprise VLAN bridge or of a Provider Bridge used ++ * to process C-tagged frames ++ * @DPSW_COMPONENT_TYPE_S_VLAN: An S-VLAN component of a ++ * Provider Bridge ++ * ++ */ ++enum dpsw_component_type { ++ DPSW_COMPONENT_TYPE_C_VLAN = 0, ++ DPSW_COMPONENT_TYPE_S_VLAN ++}; ++ ++/** ++ * struct dpsw_cfg - DPSW configuration ++ * @num_ifs: Number of external and internal interfaces ++ * @adv: Advanced parameters; default is all zeros; ++ * use this structure to change default settings ++ */ ++struct dpsw_cfg { ++ uint16_t num_ifs; ++ /** ++ * struct adv - Advanced parameters ++ * @options: Enable/Disable DPSW features (bitmap) ++ * @max_vlans: Maximum Number of VLAN's; 0 - indicates default 16 ++ * @max_meters_per_if: Number of meters per interface ++ * @max_fdbs: Maximum Number of FDB's; 0 - indicates default 16 ++ * @max_fdb_entries: Number of FDB entries for default FDB table; ++ * 0 - indicates default 1024 entries. ++ * @fdb_aging_time: Default FDB aging time for default FDB table; ++ * 0 - indicates default 300 seconds ++ * @max_fdb_mc_groups: Number of multicast groups in each FDB table; ++ * 0 - indicates default 32 ++ * @component_type: Indicates the component type of this bridge ++ */ ++ struct { ++ uint64_t options; ++ uint16_t max_vlans; ++ uint8_t max_meters_per_if; ++ uint8_t max_fdbs; ++ uint16_t max_fdb_entries; ++ uint16_t fdb_aging_time; ++ uint16_t max_fdb_mc_groups; ++ enum dpsw_component_type component_type; ++ } adv; ++}; ++ ++/** ++ * dpsw_create() - Create the DPSW object. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @cfg: Configuration structure ++ * @token: Returned token; use in subsequent API calls ++ * ++ * Create the DPSW object, allocate required resources and ++ * perform required initialization. ++ * ++ * The object can be created either by declaring it in the ++ * DPL file, or by calling this function. ++ * ++ * This function returns a unique authentication token, ++ * associated with the specific object ID and the specific MC ++ * portal; this token must be used in all subsequent calls to ++ * this specific object. For objects that are created using the ++ * DPL file, call dpsw_open() function to get an authentication ++ * token first ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_create(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ const struct dpsw_cfg *cfg, ++ uint16_t *token); ++ ++/** ++ * dpsw_destroy() - Destroy the DPSW object and release all its resources. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpsw_destroy(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpsw_enable() - Enable DPSW functionality ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpsw_disable() - Disable DPSW functionality ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * dpsw_is_enabled() - Check if the DPSW is enabled ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @en: Returns '1' if object is enabled; '0' otherwise ++ * ++ * Return: '0' on Success; Error code otherwise ++ */ ++int dpsw_is_enabled(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en); ++ ++/** ++ * dpsw_reset() - Reset the DPSW, returns the object to initial state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_reset(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++ * DPSW IRQ Index and Events ++ */ ++ ++#define DPSW_IRQ_INDEX_IF 0x0000 ++#define DPSW_IRQ_INDEX_L2SW 0x0001 ++ ++/** ++ * IRQ event - Indicates that the link state changed ++ */ ++#define DPSW_IRQ_EVENT_LINK_CHANGED 0x0001 ++ ++/** ++ * struct dpsw_irq_cfg - IRQ configuration ++ * @addr: Address that must be written to signal a message-based interrupt ++ * @val: Value to write into irq_addr address ++ * @irq_num: A user defined number associated with this IRQ ++ */ ++struct dpsw_irq_cfg { ++ uint64_t addr; ++ uint32_t val; ++ int irq_num; ++}; ++ ++/** ++ * dpsw_set_irq() - Set IRQ information for the DPSW to trigger an interrupt. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @irq_index: Identifies the interrupt index to configure ++ * @irq_cfg: IRQ configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_set_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ struct dpsw_irq_cfg *irq_cfg); ++ ++/** ++ * dpsw_get_irq() - Get IRQ information from the DPSW ++ * ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @irq_index: The interrupt index to configure ++ * @type: Interrupt type: 0 represents message interrupt ++ * type (both irq_addr and irq_val are valid) ++ * @irq_cfg: IRQ attributes ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_get_irq(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ int *type, ++ struct dpsw_irq_cfg *irq_cfg); ++ ++/** ++ * dpsw_set_irq_enable() - Set overall interrupt state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @irq_index: The interrupt index to configure ++ * @en: Interrupt state - enable = 1, disable = 0 ++ * ++ * Allows GPP software to control when interrupts are generated. ++ * Each interrupt can have up to 32 causes. The enable/disable control's the ++ * overall interrupt state. if the interrupt is disabled no causes will cause ++ * an interrupt ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_set_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t en); ++ ++/** ++ * dpsw_get_irq_enable() - Get overall interrupt state ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @irq_index: The interrupt index to configure ++ * @en: Returned Interrupt state - enable = 1, disable = 0 ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_get_irq_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint8_t *en); ++ ++/** ++ * dpsw_set_irq_mask() - Set interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @irq_index: The interrupt index to configure ++ * @mask: event mask to trigger interrupt; ++ * each bit: ++ * 0 = ignore event ++ * 1 = consider event for asserting IRQ ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_set_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t mask); ++ ++/** ++ * dpsw_get_irq_mask() - Get interrupt mask. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @irq_index: The interrupt index to configure ++ * @mask: Returned event mask to trigger interrupt ++ * ++ * Every interrupt can have up to 32 causes and the interrupt model supports ++ * masking/unmasking each cause independently ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_get_irq_mask(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *mask); ++ ++/** ++ * dpsw_get_irq_status() - Get the current status of any pending interrupts ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @irq_index: The interrupt index to configure ++ * @status: Returned interrupts status - one bit per cause: ++ * 0 = no interrupt pending ++ * 1 = interrupt pending ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_get_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t *status); ++ ++/** ++ * dpsw_clear_irq_status() - Clear a pending interrupt's status ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPCI object ++ * @irq_index: The interrupt index to configure ++ * @status: bits to clear (W1C) - one bit per cause: ++ * 0 = don't change ++ * 1 = clear status bit ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_clear_irq_status(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint8_t irq_index, ++ uint32_t status); ++/** ++ * struct dpsw_attr - Structure representing DPSW attributes ++ * @id: DPSW object ID ++ * @version: DPSW version ++ * @options: Enable/Disable DPSW features ++ * @max_vlans: Maximum Number of VLANs ++ * @max_meters_per_if: Number of meters per interface ++ * @max_fdbs: Maximum Number of FDBs ++ * @max_fdb_entries: Number of FDB entries for default FDB table; ++ * 0 - indicates default 1024 entries. ++ * @fdb_aging_time: Default FDB aging time for default FDB table; ++ * 0 - indicates default 300 seconds ++ * @max_fdb_mc_groups: Number of multicast groups in each FDB table; ++ * 0 - indicates default 32 ++ * @mem_size: DPSW frame storage memory size ++ * @num_ifs: Number of interfaces ++ * @num_vlans: Current number of VLANs ++ * @num_fdbs: Current number of FDBs ++ * @component_type: Component type of this bridge ++ */ ++struct dpsw_attr { ++ int id; ++ /** ++ * struct version - DPSW version ++ * @major: DPSW major version ++ * @minor: DPSW minor version ++ */ ++ struct { ++ uint16_t major; ++ uint16_t minor; ++ } version; ++ uint64_t options; ++ uint16_t max_vlans; ++ uint8_t max_meters_per_if; ++ uint8_t max_fdbs; ++ uint16_t max_fdb_entries; ++ uint16_t fdb_aging_time; ++ uint16_t max_fdb_mc_groups; ++ uint16_t num_ifs; ++ uint16_t mem_size; ++ uint16_t num_vlans; ++ uint8_t num_fdbs; ++ enum dpsw_component_type component_type; ++}; ++ ++/** ++ * dpsw_get_attributes() - Retrieve DPSW attributes ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @attr: Returned DPSW attributes ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpsw_attr *attr); ++ ++/** ++ * dpsw_set_reflection_if() - Set target interface for reflected interfaces. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Id ++ * ++ * Only one reflection receive interface is allowed per switch ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_set_reflection_if(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id); ++ ++/** ++ * enum dpsw_action - Action selection for special/control frames ++ * @DPSW_ACTION_DROP: Drop frame ++ * @DPSW_ACTION_REDIRECT: Redirect frame to control port ++ */ ++enum dpsw_action { ++ DPSW_ACTION_DROP = 0, ++ DPSW_ACTION_REDIRECT = 1 ++}; ++ ++/** ++ * Enable auto-negotiation ++ */ ++#define DPSW_LINK_OPT_AUTONEG 0x0000000000000001ULL ++/** ++ * Enable half-duplex mode ++ */ ++#define DPSW_LINK_OPT_HALF_DUPLEX 0x0000000000000002ULL ++/** ++ * Enable pause frames ++ */ ++#define DPSW_LINK_OPT_PAUSE 0x0000000000000004ULL ++/** ++ * Enable a-symmetric pause frames ++ */ ++#define DPSW_LINK_OPT_ASYM_PAUSE 0x0000000000000008ULL ++ ++/** ++ * struct dpsw_link_cfg - Structure representing DPSW link configuration ++ * @rate: Rate ++ * @options: Mask of available options; use 'DPSW_LINK_OPT_' values ++ */ ++struct dpsw_link_cfg { ++ uint32_t rate; ++ uint64_t options; ++}; ++ ++/** ++ * dpsw_if_set_link_cfg() - set the link configuration. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: interface id ++ * @cfg: Link configuration ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_set_link_cfg(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ struct dpsw_link_cfg *cfg); ++/** ++ * struct dpsw_link_state - Structure representing DPSW link state ++ * @rate: Rate ++ * @options: Mask of available options; use 'DPSW_LINK_OPT_' values ++ * @up: 0 - covers two cases: down and disconnected, 1 - up ++ */ ++struct dpsw_link_state { ++ uint32_t rate; ++ uint64_t options; ++ int up; ++}; ++ ++/** ++ * dpsw_if_get_link_state - Return the link state ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: interface id ++ * @state: link state 1 - linkup, 0 - link down or disconnected ++ * ++ * @returns '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_get_link_state(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ struct dpsw_link_state *state); ++ ++/** ++ * dpsw_if_set_flooding() - Enable Disable flooding for particular interface ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @en: 1 - enable, 0 - disable ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_set_flooding(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ int en); ++ ++/** ++ * dpsw_if_set_broadcast() - Enable/disable broadcast for particular interface ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @en: 1 - enable, 0 - disable ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_set_broadcast(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ int en); ++ ++/** ++ * dpsw_if_set_multicast() - Enable/disable multicast for particular interface ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @en: 1 - enable, 0 - disable ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_set_multicast(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ int en); ++ ++/** ++ * struct dpsw_tci_cfg - Tag Contorl Information (TCI) configuration ++ * @pcp: Priority Code Point (PCP): a 3-bit field which refers ++ * to the IEEE 802.1p priority ++ * @dei: Drop Eligible Indicator (DEI): a 1-bit field. May be used ++ * separately or in conjunction with PCP to indicate frames ++ * eligible to be dropped in the presence of congestion ++ * @vlan_id: VLAN Identifier (VID): a 12-bit field specifying the VLAN ++ * to which the frame belongs. The hexadecimal values ++ * of 0x000 and 0xFFF are reserved; ++ * all other values may be used as VLAN identifiers, ++ * allowing up to 4,094 VLANs ++ */ ++struct dpsw_tci_cfg { ++ uint8_t pcp; ++ uint8_t dei; ++ uint16_t vlan_id; ++}; ++ ++/** ++ * dpsw_if_set_tci() - Set default VLAN Tag Control Information (TCI) ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @cfg: Tag Control Information Configuration ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_set_tci(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpsw_tci_cfg *cfg); ++ ++/** ++ * dpsw_if_get_tci() - Get default VLAN Tag Control Information (TCI) ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @cfg: Tag Control Information Configuration ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_get_tci(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ struct dpsw_tci_cfg *cfg); ++ ++/** ++ * enum dpsw_stp_state - Spanning Tree Protocol (STP) states ++ * @DPSW_STP_STATE_BLOCKING: Blocking state ++ * @DPSW_STP_STATE_LISTENING: Listening state ++ * @DPSW_STP_STATE_LEARNING: Learning state ++ * @DPSW_STP_STATE_FORWARDING: Forwarding state ++ * ++ */ ++enum dpsw_stp_state { ++ DPSW_STP_STATE_BLOCKING = 0, ++ DPSW_STP_STATE_LISTENING = 1, ++ DPSW_STP_STATE_LEARNING = 2, ++ DPSW_STP_STATE_FORWARDING = 3 ++}; ++ ++/** ++ * struct dpsw_stp_cfg - Spanning Tree Protocol (STP) Configuration ++ * @vlan_id: VLAN ID STP state ++ * @state: STP state ++ */ ++struct dpsw_stp_cfg { ++ uint16_t vlan_id; ++ enum dpsw_stp_state state; ++}; ++ ++/** ++ * dpsw_if_set_stp() - Function sets Spanning Tree Protocol (STP) state. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @cfg: STP State configuration parameters ++ * ++ * The following STP states are supported - ++ * blocking, listening, learning, forwarding and disabled. ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_set_stp(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpsw_stp_cfg *cfg); ++ ++/** ++ * enum dpsw_accepted_frames - Types of frames to accept ++ * @DPSW_ADMIT_ALL: The device accepts VLAN tagged, untagged and ++ * priority tagged frames ++ * @DPSW_ADMIT_ONLY_VLAN_TAGGED: The device discards untagged frames or ++ * Priority-Tagged frames received on this interface. ++ * ++ */ ++enum dpsw_accepted_frames { ++ DPSW_ADMIT_ALL = 1, ++ DPSW_ADMIT_ONLY_VLAN_TAGGED = 3 ++}; ++ ++/** ++ * struct dpsw_accepted_frames_cfg - Types of frames to accept configuration ++ * @type: Defines ingress accepted frames ++ * @unaccept_act: When a frame is not accepted, it may be discarded or ++ * redirected to control interface depending on this mode ++ */ ++struct dpsw_accepted_frames_cfg { ++ enum dpsw_accepted_frames type; ++ enum dpsw_action unaccept_act; ++}; ++ ++/** ++ * dpsw_if_set_accepted_frames() ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @cfg: Frame types configuration ++ * ++ * When is admit_only_vlan_tagged- the device will discard untagged ++ * frames or Priority-Tagged frames received on this interface. ++ * When admit_only_untagged- untagged frames or Priority-Tagged ++ * frames received on this interface will be accepted and assigned ++ * to a VID based on the PVID and VID Set for this interface. ++ * When admit_all - the device will accept VLAN tagged, untagged ++ * and priority tagged frames. ++ * The default is admit_all ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_set_accepted_frames(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpsw_accepted_frames_cfg *cfg); ++ ++/** ++ * dpsw_if_set_accept_all_vlan() ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @accept_all: Accept or drop frames having different VLAN ++ * ++ * When this is accept (FALSE), the device will discard incoming ++ * frames for VLANs that do not include this interface in its ++ * Member set. When accept (TRUE), the interface will accept all incoming frames ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_set_accept_all_vlan(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ int accept_all); ++ ++/** ++ * enum dpsw_counter - Counters types ++ * @DPSW_CNT_ING_FRAME: Counts ingress frames ++ * @DPSW_CNT_ING_BYTE: Counts ingress bytes ++ * @DPSW_CNT_ING_FLTR_FRAME: Counts filtered ingress frames ++ * @DPSW_CNT_ING_FRAME_DISCARD: Counts discarded ingress frame ++ * @DPSW_CNT_ING_MCAST_FRAME: Counts ingress multicast frames ++ * @DPSW_CNT_ING_MCAST_BYTE: Counts ingress multicast bytes ++ * @DPSW_CNT_ING_BCAST_FRAME: Counts ingress broadcast frames ++ * @DPSW_CNT_ING_BCAST_BYTES: Counts ingress broadcast bytes ++ * @DPSW_CNT_EGR_FRAME: Counts egress frames ++ * @DPSW_CNT_EGR_BYTE: Counts eEgress bytes ++ * @DPSW_CNT_EGR_FRAME_DISCARD: Counts discarded egress frames ++ * @DPSW_CNT_EGR_STP_FRAME_DISCARD: Counts egress STP discarded frames ++ */ ++enum dpsw_counter { ++ DPSW_CNT_ING_FRAME = 0x0, ++ DPSW_CNT_ING_BYTE = 0x1, ++ DPSW_CNT_ING_FLTR_FRAME = 0x2, ++ DPSW_CNT_ING_FRAME_DISCARD = 0x3, ++ DPSW_CNT_ING_MCAST_FRAME = 0x4, ++ DPSW_CNT_ING_MCAST_BYTE = 0x5, ++ DPSW_CNT_ING_BCAST_FRAME = 0x6, ++ DPSW_CNT_ING_BCAST_BYTES = 0x7, ++ DPSW_CNT_EGR_FRAME = 0x8, ++ DPSW_CNT_EGR_BYTE = 0x9, ++ DPSW_CNT_EGR_FRAME_DISCARD = 0xa, ++ DPSW_CNT_EGR_STP_FRAME_DISCARD = 0xb ++}; ++ ++/** ++ * dpsw_if_get_counter() - Get specific counter of particular interface ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @type: Counter type ++ * @counter: return value ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_get_counter(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ enum dpsw_counter type, ++ uint64_t *counter); ++ ++/** ++ * dpsw_if_set_counter() - Set specific counter of particular interface ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @type: Counter type ++ * @counter: New counter value ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_set_counter(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ enum dpsw_counter type, ++ uint64_t counter); ++ ++/** ++ * Maximum number of TC ++ */ ++#define DPSW_MAX_TC 8 ++ ++/** ++ * enum dpsw_priority_selector - User priority ++ * @DPSW_UP_PCP: Priority Code Point (PCP): a 3-bit field which ++ * refers to the IEEE 802.1p priority. ++ * @DPSW_UP_DSCP: Differentiated services Code Point (DSCP): 6 bit ++ * field from IP header ++ * ++ */ ++enum dpsw_priority_selector { ++ DPSW_UP_PCP = 0, ++ DPSW_UP_DSCP = 1 ++}; ++ ++/** ++ * enum dpsw_schedule_mode - Traffic classes scheduling ++ * @DPSW_SCHED_STRICT_PRIORITY: schedule strict priority ++ * @DPSW_SCHED_WEIGHTED: schedule based on token bucket created algorithm ++ */ ++enum dpsw_schedule_mode { ++ DPSW_SCHED_STRICT_PRIORITY, ++ DPSW_SCHED_WEIGHTED ++}; ++ ++/** ++ * struct dpsw_tx_schedule_cfg - traffic class configuration ++ * @mode: Strict or weight-based scheduling ++ * @delta_bandwidth: weighted Bandwidth in range from 100 to 10000 ++ */ ++struct dpsw_tx_schedule_cfg { ++ enum dpsw_schedule_mode mode; ++ uint16_t delta_bandwidth; ++}; ++ ++/** ++ * struct dpsw_tx_selection_cfg - Mapping user priority into traffic ++ * class configuration ++ * @priority_selector: Source for user priority regeneration ++ * @tc_id: The Regenerated User priority that the incoming ++ * User Priority is mapped to for this interface ++ * @tc_sched: Traffic classes configuration ++ */ ++struct dpsw_tx_selection_cfg { ++ enum dpsw_priority_selector priority_selector; ++ uint8_t tc_id[DPSW_MAX_PRIORITIES]; ++ struct dpsw_tx_schedule_cfg tc_sched[DPSW_MAX_TC]; ++}; ++ ++/** ++ * dpsw_if_set_tx_selection() - Function is used for mapping variety ++ * of frame fields ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @cfg: Traffic class mapping configuration ++ * ++ * Function is used for mapping variety of frame fields (DSCP, PCP) ++ * to Traffic Class. Traffic class is a number ++ * in the range from 0 to 7 ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_set_tx_selection(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpsw_tx_selection_cfg *cfg); ++ ++/** ++ * enum dpsw_reflection_filter - Filter type for frames to reflect ++ * @DPSW_REFLECTION_FILTER_INGRESS_ALL: Reflect all frames ++ * @DPSW_REFLECTION_FILTER_INGRESS_VLAN: Reflect only frames belong to ++ * particular VLAN defined by vid parameter ++ * ++ */ ++enum dpsw_reflection_filter { ++ DPSW_REFLECTION_FILTER_INGRESS_ALL = 0, ++ DPSW_REFLECTION_FILTER_INGRESS_VLAN = 1 ++}; ++ ++/** ++ * struct dpsw_reflection_cfg - Structure representing reflection information ++ * @filter: Filter type for frames to reflect ++ * @vlan_id: Vlan Id to reflect; valid only when filter type is ++ * DPSW_INGRESS_VLAN ++ */ ++struct dpsw_reflection_cfg { ++ enum dpsw_reflection_filter filter; ++ uint16_t vlan_id; ++}; ++ ++/** ++ * dpsw_if_add_reflection() - Identify interface to be reflected or mirrored ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @cfg: Reflection configuration ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_add_reflection(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpsw_reflection_cfg *cfg); ++ ++/** ++ * dpsw_if_remove_reflection() - Remove interface to be reflected or mirrored ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @cfg: Reflection configuration ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_remove_reflection(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpsw_reflection_cfg *cfg); ++ ++/** ++ * enum dpsw_metering_mode - Metering modes ++ * @DPSW_METERING_MODE_NONE: metering disabled ++ * @DPSW_METERING_MODE_RFC2698: RFC 2698 ++ * @DPSW_METERING_MODE_RFC4115: RFC 4115 ++ */ ++enum dpsw_metering_mode { ++ DPSW_METERING_MODE_NONE = 0, ++ DPSW_METERING_MODE_RFC2698, ++ DPSW_METERING_MODE_RFC4115 ++}; ++ ++/** ++ * enum dpsw_metering_unit - Metering count ++ * @DPSW_METERING_UNIT_BYTES: count bytes ++ * @DPSW_METERING_UNIT_FRAMES: count frames ++ */ ++enum dpsw_metering_unit { ++ DPSW_METERING_UNIT_BYTES = 0, ++ DPSW_METERING_UNIT_FRAMES ++}; ++ ++/** ++ * struct dpsw_metering_cfg - Metering configuration ++ * @mode: metering modes ++ * @units: Bytes or frame units ++ * @cir: Committed information rate (CIR) in Kbits/s ++ * @eir: Peak information rate (PIR) Kbit/s rfc2698 ++ * Excess information rate (EIR) Kbit/s rfc4115 ++ * @cbs: Committed burst size (CBS) in bytes ++ * @ebs: Peak burst size (PBS) in bytes for rfc2698 ++ * Excess bust size (EBS) in bytes rfc4115 ++ * ++ */ ++struct dpsw_metering_cfg { ++ enum dpsw_metering_mode mode; ++ enum dpsw_metering_unit units; ++ uint32_t cir; ++ uint32_t eir; ++ uint32_t cbs; ++ uint32_t ebs; ++}; ++ ++/** ++ * dpsw_if_set_flooding_metering() - Set flooding metering ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @cfg: Metering parameters ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_set_flooding_metering(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ const struct dpsw_metering_cfg *cfg); ++ ++/** ++ * dpsw_if_set_metering() - Set interface metering for flooding ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @tc_id: Traffic class ID ++ * @cfg: Metering parameters ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_set_metering(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ uint8_t tc_id, ++ const struct dpsw_metering_cfg *cfg); ++ ++/** ++ * enum dpsw_early_drop_unit - DPSW early drop unit ++ * @DPSW_EARLY_DROP_UNIT_BYTE: count bytes ++ * @DPSW_EARLY_DROP_UNIT_FRAMES: count frames ++ */ ++enum dpsw_early_drop_unit { ++ DPSW_EARLY_DROP_UNIT_BYTE = 0, ++ DPSW_EARLY_DROP_UNIT_FRAMES ++}; ++ ++/** ++ * enum dpsw_early_drop_mode - DPSW early drop mode ++ * @DPSW_EARLY_DROP_MODE_NONE: early drop is disabled ++ * @DPSW_EARLY_DROP_MODE_TAIL: early drop in taildrop mode ++ * @DPSW_EARLY_DROP_MODE_WRED: early drop in WRED mode ++ */ ++enum dpsw_early_drop_mode { ++ DPSW_EARLY_DROP_MODE_NONE = 0, ++ DPSW_EARLY_DROP_MODE_TAIL, ++ DPSW_EARLY_DROP_MODE_WRED ++}; ++ ++/** ++ * struct dpsw_wred_cfg - WRED configuration ++ * @max_threshold: maximum threshold that packets may be discarded. Above this ++ * threshold all packets are discarded; must be less than 2^39; ++ * approximated to be expressed as (x+256)*2^(y-1) due to HW ++ * implementation. ++ * @min_threshold: minimum threshold that packets may be discarded at ++ * @drop_probability: probability that a packet will be discarded (1-100, ++ * associated with the maximum threshold) ++ */ ++struct dpsw_wred_cfg { ++ uint64_t min_threshold; ++ uint64_t max_threshold; ++ uint8_t drop_probability; ++}; ++ ++/** ++ * struct dpsw_early_drop_cfg - early-drop configuration ++ * @drop_mode: drop mode ++ * @units: count units ++ * @yellow: WRED - 'yellow' configuration ++ * @green: WRED - 'green' configuration ++ * @tail_drop_threshold: tail drop threshold ++ */ ++struct dpsw_early_drop_cfg { ++ enum dpsw_early_drop_mode drop_mode; ++ enum dpsw_early_drop_unit units; ++ struct dpsw_wred_cfg yellow; ++ struct dpsw_wred_cfg green; ++ uint32_t tail_drop_threshold; ++}; ++ ++/** ++ * dpsw_prepare_early_drop() - Prepare an early drop for setting in to interface ++ * @cfg: Early-drop configuration ++ * @early_drop_buf: Zeroed 256 bytes of memory before mapping it to DMA ++ * ++ * This function has to be called before dpsw_if_tc_set_early_drop ++ * ++ */ ++void dpsw_prepare_early_drop(const struct dpsw_early_drop_cfg *cfg, ++ uint8_t *early_drop_buf); ++ ++/** ++ * dpsw_if_set_early_drop() - Set interface traffic class early-drop ++ * configuration ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @tc_id: Traffic class selection (0-7) ++ * @early_drop_iova: I/O virtual address of 64 bytes; ++ * Must be cacheline-aligned and DMA-able memory ++ * ++ * warning: Before calling this function, call dpsw_prepare_if_tc_early_drop() ++ * to prepare the early_drop_iova parameter ++ * ++ * Return: '0' on Success; error code otherwise. ++ */ ++int dpsw_if_set_early_drop(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ uint8_t tc_id, ++ uint64_t early_drop_iova); ++ ++/** ++ * struct dpsw_custom_tpid_cfg - Structure representing tag Protocol identifier ++ * @tpid: An additional tag protocol identifier ++ */ ++struct dpsw_custom_tpid_cfg { ++ uint16_t tpid; ++}; ++ ++/** ++ * dpsw_add_custom_tpid() - API Configures a distinct Ethernet type value ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @cfg: Tag Protocol identifier ++ * ++ * API Configures a distinct Ethernet type value (or TPID value) ++ * to indicate a VLAN tag in addition to the common ++ * TPID values 0x8100 and 0x88A8. ++ * Two additional TPID's are supported ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_add_custom_tpid(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpsw_custom_tpid_cfg *cfg); ++ ++/** ++ * dpsw_remove_custom_tpid - API removes a distinct Ethernet type value ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @cfg: Tag Protocol identifier ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_remove_custom_tpid(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpsw_custom_tpid_cfg *cfg); ++ ++/** ++ * dpsw_if_enable() - Enable Interface ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id); ++ ++/** ++ * dpsw_if_disable() - Disable Interface ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id); ++ ++/** ++ * struct dpsw_if_attr - Structure representing DPSW interface attributes ++ * @num_tcs: Number of traffic classes ++ * @rate: Transmit rate in bits per second ++ * @options: Interface configuration options (bitmap) ++ * @enabled: Indicates if interface is enabled ++ * @accept_all_vlan: The device discards/accepts incoming frames ++ * for VLANs that do not include this interface ++ * @admit_untagged: When set to 'DPSW_ADMIT_ONLY_VLAN_TAGGED', the device ++ * discards untagged frames or priority-tagged frames received on ++ * this interface; ++ * When set to 'DPSW_ADMIT_ALL', untagged frames or priority- ++ * tagged frames received on this interface are accepted ++ * @qdid: control frames transmit qdid ++ */ ++struct dpsw_if_attr { ++ uint8_t num_tcs; ++ uint32_t rate; ++ uint32_t options; ++ int enabled; ++ int accept_all_vlan; ++ enum dpsw_accepted_frames admit_untagged; ++ uint16_t qdid; ++}; ++ ++/** ++ * dpsw_if_get_attributes() - Function obtains attributes of interface ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @attr: Returned interface attributes ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ struct dpsw_if_attr *attr); ++ ++/** ++ * dpsw_if_set_max_frame_length() - Set Maximum Receive frame length. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @frame_length: Maximum Frame Length ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_set_max_frame_length(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ uint16_t frame_length); ++ ++/** ++ * dpsw_if_get_max_frame_length() - Get Maximum Receive frame length. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @if_id: Interface Identifier ++ * @frame_length: Returned maximum Frame Length ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_if_get_max_frame_length(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t if_id, ++ uint16_t *frame_length); ++ ++/** ++ * struct dpsw_vlan_cfg - VLAN Configuration ++ * @fdb_id: Forwarding Data Base ++ */ ++struct dpsw_vlan_cfg { ++ uint16_t fdb_id; ++}; ++ ++/** ++ * dpsw_vlan_add() - Adding new VLAN to DPSW. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @vlan_id: VLAN Identifier ++ * @cfg: VLAN configuration ++ * ++ * Only VLAN ID and FDB ID are required parameters here. ++ * 12 bit VLAN ID is defined in IEEE802.1Q. ++ * Adding a duplicate VLAN ID is not allowed. ++ * FDB ID can be shared across multiple VLANs. Shared learning ++ * is obtained by calling dpsw_vlan_add for multiple VLAN IDs ++ * with same fdb_id ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_vlan_add(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ const struct dpsw_vlan_cfg *cfg); ++ ++/** ++ * struct dpsw_vlan_if_cfg - Set of VLAN Interfaces ++ * @num_ifs: The number of interfaces that are assigned to the egress ++ * list for this VLAN ++ * @if_id: The set of interfaces that are ++ * assigned to the egress list for this VLAN ++ */ ++struct dpsw_vlan_if_cfg { ++ uint16_t num_ifs; ++ uint16_t if_id[DPSW_MAX_IF]; ++}; ++ ++/** ++ * dpsw_vlan_add_if() - Adding a set of interfaces to an existing VLAN. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @vlan_id: VLAN Identifier ++ * @cfg: Set of interfaces to add ++ * ++ * It adds only interfaces not belonging to this VLAN yet, ++ * otherwise an error is generated and an entire command is ++ * ignored. This function can be called numerous times always ++ * providing required interfaces delta. ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_vlan_add_if(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ const struct dpsw_vlan_if_cfg *cfg); ++ ++/** ++ * dpsw_vlan_add_if_untagged() - Defining a set of interfaces that should be ++ * transmitted as untagged. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @vlan_id: VLAN Identifier ++ * @cfg: set of interfaces that should be transmitted as untagged ++ * ++ * These interfaces should already belong to this VLAN. ++ * By default all interfaces are transmitted as tagged. ++ * Providing un-existing interface or untagged interface that is ++ * configured untagged already generates an error and the entire ++ * command is ignored. ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_vlan_add_if_untagged(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ const struct dpsw_vlan_if_cfg *cfg); ++ ++/** ++ * dpsw_vlan_add_if_flooding() - Define a set of interfaces that should be ++ * included in flooding when frame with unknown destination ++ * unicast MAC arrived. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @vlan_id: VLAN Identifier ++ * @cfg: Set of interfaces that should be used for flooding ++ * ++ * These interfaces should belong to this VLAN. By default all ++ * interfaces are included into flooding list. Providing ++ * un-existing interface or an interface that already in the ++ * flooding list generates an error and the entire command is ++ * ignored. ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_vlan_add_if_flooding(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ const struct dpsw_vlan_if_cfg *cfg); ++ ++/** ++ * dpsw_vlan_remove_if() - Remove interfaces from an existing VLAN. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @vlan_id: VLAN Identifier ++ * @cfg: Set of interfaces that should be removed ++ * ++ * Interfaces must belong to this VLAN, otherwise an error ++ * is returned and an the command is ignored ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_vlan_remove_if(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ const struct dpsw_vlan_if_cfg *cfg); ++ ++/** ++ * dpsw_vlan_remove_if_untagged() - Define a set of interfaces that should be ++ * converted from transmitted as untagged to transmit as tagged. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @vlan_id: VLAN Identifier ++ * @cfg: set of interfaces that should be removed ++ * ++ * Interfaces provided by API have to belong to this VLAN and ++ * configured untagged, otherwise an error is returned and the ++ * command is ignored ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_vlan_remove_if_untagged(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ const struct dpsw_vlan_if_cfg *cfg); ++ ++/** ++ * dpsw_vlan_remove_if_flooding() - Define a set of interfaces that should be ++ * removed from the flooding list. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @vlan_id: VLAN Identifier ++ * @cfg: set of interfaces used for flooding ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_vlan_remove_if_flooding(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ const struct dpsw_vlan_if_cfg *cfg); ++ ++/** ++ * dpsw_vlan_remove() - Remove an entire VLAN ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @vlan_id: VLAN Identifier ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_vlan_remove(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id); ++ ++/** ++ * struct dpsw_vlan_attr - VLAN attributes ++ * @fdb_id: Associated FDB ID ++ * @num_ifs: Number of interfaces ++ * @num_untagged_ifs: Number of untagged interfaces ++ * @num_flooding_ifs: Number of flooding interfaces ++ */ ++struct dpsw_vlan_attr { ++ uint16_t fdb_id; ++ uint16_t num_ifs; ++ uint16_t num_untagged_ifs; ++ uint16_t num_flooding_ifs; ++}; ++ ++/** ++ * dpsw_vlan_get_attributes() - Get VLAN attributes ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @vlan_id: VLAN Identifier ++ * @attr: Returned DPSW attributes ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_vlan_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ struct dpsw_vlan_attr *attr); ++ ++/** ++ * dpsw_vlan_get_if() - Get interfaces belong to this VLAN ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @vlan_id: VLAN Identifier ++ * @cfg: Returned set of interfaces belong to this VLAN ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_vlan_get_if(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ struct dpsw_vlan_if_cfg *cfg); ++ ++/** ++ * dpsw_vlan_get_if_flooding() - Get interfaces used in flooding for this VLAN ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @vlan_id: VLAN Identifier ++ * @cfg: Returned set of flooding interfaces ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_vlan_get_if_flooding(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ struct dpsw_vlan_if_cfg *cfg); ++ ++/** ++ * dpsw_vlan_get_if_untagged() - Get interfaces that should be transmitted as ++ * untagged ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @vlan_id: VLAN Identifier ++ * @cfg: Returned set of untagged interfaces ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_vlan_get_if_untagged(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t vlan_id, ++ struct dpsw_vlan_if_cfg *cfg); ++ ++/** ++ * struct dpsw_fdb_cfg - FDB Configuration ++ * @num_fdb_entries: Number of FDB entries ++ * @fdb_aging_time: Aging time in seconds ++ */ ++struct dpsw_fdb_cfg { ++ uint16_t num_fdb_entries; ++ uint16_t fdb_aging_time; ++}; ++ ++/** ++ * dpsw_fdb_add() - Add FDB to switch and Returns handle to FDB table for ++ * the reference ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @fdb_id: Returned Forwarding Database Identifier ++ * @cfg: FDB Configuration ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_fdb_add(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t *fdb_id, ++ const struct dpsw_fdb_cfg *cfg); ++ ++/** ++ * dpsw_fdb_remove() - Remove FDB from switch ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @fdb_id: Forwarding Database Identifier ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_fdb_remove(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t fdb_id); ++ ++/** ++ * enum dpsw_fdb_entry_type - FDB Entry type - Static/Dynamic ++ * @DPSW_FDB_ENTRY_STATIC: Static entry ++ * @DPSW_FDB_ENTRY_DINAMIC: Dynamic entry ++ */ ++enum dpsw_fdb_entry_type { ++ DPSW_FDB_ENTRY_STATIC = 0, ++ DPSW_FDB_ENTRY_DINAMIC = 1 ++}; ++ ++/** ++ * struct dpsw_fdb_unicast_cfg - Unicast entry configuration ++ * @type: Select static or dynamic entry ++ * @mac_addr: MAC address ++ * @if_egress: Egress interface ID ++ */ ++struct dpsw_fdb_unicast_cfg { ++ enum dpsw_fdb_entry_type type; ++ uint8_t mac_addr[6]; ++ uint16_t if_egress; ++}; ++ ++/** ++ * dpsw_fdb_add_unicast() - Function adds an unicast entry into MAC lookup table ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @fdb_id: Forwarding Database Identifier ++ * @cfg: Unicast entry configuration ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_fdb_add_unicast(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t fdb_id, ++ const struct dpsw_fdb_unicast_cfg *cfg); ++ ++/** ++ * dpsw_fdb_get_unicast() - Get unicast entry from MAC lookup table by ++ * unicast Ethernet address ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @fdb_id: Forwarding Database Identifier ++ * @cfg: Returned unicast entry configuration ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_fdb_get_unicast(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t fdb_id, ++ struct dpsw_fdb_unicast_cfg *cfg); ++ ++/** ++ * dpsw_fdb_remove_unicast() - removes an entry from MAC lookup table ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @fdb_id: Forwarding Database Identifier ++ * @cfg: Unicast entry configuration ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_fdb_remove_unicast(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t fdb_id, ++ const struct dpsw_fdb_unicast_cfg *cfg); ++ ++/** ++ * struct dpsw_fdb_multicast_cfg - Multi-cast entry configuration ++ * @type: Select static or dynamic entry ++ * @mac_addr: MAC address ++ * @num_ifs: Number of external and internal interfaces ++ * @if_id: Egress interface IDs ++ */ ++struct dpsw_fdb_multicast_cfg { ++ enum dpsw_fdb_entry_type type; ++ uint8_t mac_addr[6]; ++ uint16_t num_ifs; ++ uint16_t if_id[DPSW_MAX_IF]; ++}; ++ ++/** ++ * dpsw_fdb_add_multicast() - Add a set of egress interfaces to multi-cast group ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @fdb_id: Forwarding Database Identifier ++ * @cfg: Multicast entry configuration ++ * ++ * If group doesn't exist, it will be created. ++ * It adds only interfaces not belonging to this multicast group ++ * yet, otherwise error will be generated and the command is ++ * ignored. ++ * This function may be called numerous times always providing ++ * required interfaces delta. ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_fdb_add_multicast(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t fdb_id, ++ const struct dpsw_fdb_multicast_cfg *cfg); ++ ++/** ++ * dpsw_fdb_get_multicast() - Reading multi-cast group by multi-cast Ethernet ++ * address. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @fdb_id: Forwarding Database Identifier ++ * @cfg: Returned multicast entry configuration ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_fdb_get_multicast(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t fdb_id, ++ struct dpsw_fdb_multicast_cfg *cfg); ++ ++/** ++ * dpsw_fdb_remove_multicast() - Removing interfaces from an existing multicast ++ * group. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @fdb_id: Forwarding Database Identifier ++ * @cfg: Multicast entry configuration ++ * ++ * Interfaces provided by this API have to exist in the group, ++ * otherwise an error will be returned and an entire command ++ * ignored. If there is no interface left in the group, ++ * an entire group is deleted ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_fdb_remove_multicast(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t fdb_id, ++ const struct dpsw_fdb_multicast_cfg *cfg); ++ ++/** ++ * enum dpsw_fdb_learning_mode - Auto-learning modes ++ * @DPSW_FDB_LEARNING_MODE_DIS: Disable Auto-learning ++ * @DPSW_FDB_LEARNING_MODE_HW: Enable HW auto-Learning ++ * @DPSW_FDB_LEARNING_MODE_NON_SECURE: Enable None secure learning by CPU ++ * @DPSW_FDB_LEARNING_MODE_SECURE: Enable secure learning by CPU ++ * ++ * NONE - SECURE LEARNING ++ * SMAC found DMAC found CTLU Action ++ * v v Forward frame to ++ * 1. DMAC destination ++ * - v Forward frame to ++ * 1. DMAC destination ++ * 2. Control interface ++ * v - Forward frame to ++ * 1. Flooding list of interfaces ++ * - - Forward frame to ++ * 1. Flooding list of interfaces ++ * 2. Control interface ++ * SECURE LEARING ++ * SMAC found DMAC found CTLU Action ++ * v v Forward frame to ++ * 1. DMAC destination ++ * - v Forward frame to ++ * 1. Control interface ++ * v - Forward frame to ++ * 1. Flooding list of interfaces ++ * - - Forward frame to ++ * 1. Control interface ++ */ ++enum dpsw_fdb_learning_mode { ++ DPSW_FDB_LEARNING_MODE_DIS = 0, ++ DPSW_FDB_LEARNING_MODE_HW = 1, ++ DPSW_FDB_LEARNING_MODE_NON_SECURE = 2, ++ DPSW_FDB_LEARNING_MODE_SECURE = 3 ++}; ++ ++/** ++ * dpsw_fdb_set_learning_mode() - Define FDB learning mode ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @fdb_id: Forwarding Database Identifier ++ * @mode: learning mode ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_fdb_set_learning_mode(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t fdb_id, ++ enum dpsw_fdb_learning_mode mode); ++ ++/** ++ * struct dpsw_fdb_attr - FDB Attributes ++ * @max_fdb_entries: Number of FDB entries ++ * @fdb_aging_time: Aging time in seconds ++ * @learning_mode: Learning mode ++ * @num_fdb_mc_groups: Current number of multicast groups ++ * @max_fdb_mc_groups: Maximum number of multicast groups ++ */ ++struct dpsw_fdb_attr { ++ uint16_t max_fdb_entries; ++ uint16_t fdb_aging_time; ++ enum dpsw_fdb_learning_mode learning_mode; ++ uint16_t num_fdb_mc_groups; ++ uint16_t max_fdb_mc_groups; ++}; ++ ++/** ++ * dpsw_fdb_get_attributes() - Get FDB attributes ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @fdb_id: Forwarding Database Identifier ++ * @attr: Returned FDB attributes ++ * ++ * Return: Completion status. '0' on Success; Error code otherwise. ++ */ ++int dpsw_fdb_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t fdb_id, ++ struct dpsw_fdb_attr *attr); ++ ++/** ++ * struct dpsw_acl_cfg - ACL Configuration ++ * @max_entries: Number of FDB entries ++ */ ++struct dpsw_acl_cfg { ++ uint16_t max_entries; ++}; ++ ++/** ++ * struct dpsw_acl_fields - ACL fields. ++ * @l2_dest_mac: Destination MAC address: BPDU, Multicast, Broadcast, Unicast, ++ * slow protocols, MVRP, STP ++ * @l2_source_mac: Source MAC address ++ * @l2_tpid: Layer 2 (Ethernet) protocol type, used to identify the following ++ * protocols: MPLS, PTP, PFC, ARP, Jumbo frames, LLDP, IEEE802.1ae, ++ * Q-in-Q, IPv4, IPv6, PPPoE ++ * @l2_pcp_dei: indicate which protocol is encapsulated in the payload ++ * @l2_vlan_id: layer 2 VLAN ID ++ * @l2_ether_type: layer 2 Ethernet type ++ * @l3_dscp: Layer 3 differentiated services code point ++ * @l3_protocol: Tells the Network layer at the destination host, to which ++ * Protocol this packet belongs to. The following protocol are ++ * supported: ICMP, IGMP, IPv4 (encapsulation), TCP, IPv6 ++ * (encapsulation), GRE, PTP ++ * @l3_source_ip: Source IPv4 IP ++ * @l3_dest_ip: Destination IPv4 IP ++ * @l4_source_port: Source TCP/UDP Port ++ * @l4_dest_port: Destination TCP/UDP Port ++ */ ++struct dpsw_acl_fields { ++ uint8_t l2_dest_mac[6]; ++ uint8_t l2_source_mac[6]; ++ uint16_t l2_tpid; ++ uint8_t l2_pcp_dei; ++ uint16_t l2_vlan_id; ++ uint16_t l2_ether_type; ++ uint8_t l3_dscp; ++ uint8_t l3_protocol; ++ uint32_t l3_source_ip; ++ uint32_t l3_dest_ip; ++ uint16_t l4_source_port; ++ uint16_t l4_dest_port; ++}; ++ ++/** ++ * struct dpsw_acl_key - ACL key ++ * @match: Match fields ++ * @mask: Mask: b'1 - valid, b'0 don't care ++ */ ++struct dpsw_acl_key { ++ struct dpsw_acl_fields match; ++ struct dpsw_acl_fields mask; ++}; ++ ++/** ++ * enum dpsw_acl_action ++ * @DPSW_ACL_ACTION_DROP: Drop frame ++ * @DPSW_ACL_ACTION_REDIRECT: Redirect to certain port ++ * @DPSW_ACL_ACTION_ACCEPT: Accept frame ++ * @DPSW_ACL_ACTION_REDIRECT_TO_CTRL_IF: Redirect to control interface ++ */ ++enum dpsw_acl_action { ++ DPSW_ACL_ACTION_DROP, ++ DPSW_ACL_ACTION_REDIRECT, ++ DPSW_ACL_ACTION_ACCEPT, ++ DPSW_ACL_ACTION_REDIRECT_TO_CTRL_IF ++}; ++ ++/** ++ * struct dpsw_acl_result - ACL action ++ * @action: Action should be taken when ACL entry hit ++ * @if_id: Interface IDs to redirect frame. Valid only if redirect selected for ++ * action ++ */ ++struct dpsw_acl_result { ++ enum dpsw_acl_action action; ++ uint16_t if_id; ++}; ++ ++/** ++ * struct dpsw_acl_entry_cfg - ACL entry ++ * @key_iova: I/O virtual address of DMA-able memory filled with key after call ++ * to dpsw_acl_prepare_entry_cfg() ++ * @result: Required action when entry hit occurs ++ * @precedence: Precedence inside ACL 0 is lowest; This priority can not change ++ * during the lifetime of a Policy. It is user responsibility to ++ * space the priorities according to consequent rule additions. ++ */ ++struct dpsw_acl_entry_cfg { ++ uint64_t key_iova; ++ struct dpsw_acl_result result; ++ int precedence; ++}; ++ ++/** ++ * dpsw_acl_add() - Adds ACL to L2 switch. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @acl_id: Returned ACL ID, for the future reference ++ * @cfg: ACL configuration ++ * ++ * Create Access Control List. Multiple ACLs can be created and ++ * co-exist in L2 switch ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_acl_add(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t *acl_id, ++ const struct dpsw_acl_cfg *cfg); ++ ++/** ++ * dpsw_acl_remove() - Removes ACL from L2 switch. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @acl_id: ACL ID ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_acl_remove(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t acl_id); ++ ++/** ++ * dpsw_acl_prepare_entry_cfg() - Set an entry to ACL. ++ * @key: key ++ * @entry_cfg_buf: Zeroed 256 bytes of memory before mapping it to DMA ++ * ++ * This function has to be called before adding or removing acl_entry ++ * ++ */ ++void dpsw_acl_prepare_entry_cfg(const struct dpsw_acl_key *key, ++ uint8_t *entry_cfg_buf); ++ ++/** ++ * dpsw_acl_add_entry() - Adds an entry to ACL. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @acl_id: ACL ID ++ * @cfg: entry configuration ++ * ++ * warning: This function has to be called after dpsw_acl_set_entry_cfg() ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_acl_add_entry(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t acl_id, ++ const struct dpsw_acl_entry_cfg *cfg); ++ ++/** ++ * dpsw_acl_remove_entry() - Removes an entry from ACL. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @acl_id: ACL ID ++ * @cfg: entry configuration ++ * ++ * warning: This function has to be called after dpsw_acl_set_entry_cfg() ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_acl_remove_entry(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t acl_id, ++ const struct dpsw_acl_entry_cfg *cfg); ++ ++/** ++ * struct dpsw_acl_if_cfg - List of interfaces to Associate with ACL ++ * @num_ifs: Number of interfaces ++ * @if_id: List of interfaces ++ */ ++struct dpsw_acl_if_cfg { ++ uint16_t num_ifs; ++ uint16_t if_id[DPSW_MAX_IF]; ++}; ++ ++/** ++ * dpsw_acl_add_if() - Associate interface/interfaces with ACL. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @acl_id: ACL ID ++ * @cfg: interfaces list ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_acl_add_if(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t acl_id, ++ const struct dpsw_acl_if_cfg *cfg); ++ ++/** ++ * dpsw_acl_remove_if() - De-associate interface/interfaces from ACL. ++ * @mc_io: Pointer to MC portal's I/O object ++ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++ * @token: Token of DPSW object ++ * @acl_id: ACL ID ++ * @cfg: interfaces list ++ * ++ * Return: '0' on Success; Error code otherwise. ++ */ ++int dpsw_acl_remove_if(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t acl_id, ++ const struct dpsw_acl_if_cfg *cfg); ++ ++/** ++ * struct dpsw_acl_attr - ACL Attributes ++ * @max_entries: Max number of ACL entries ++ * @num_entries: Number of used ACL entries ++ * @num_ifs: Number of interfaces associated with ACL ++ */ ++struct dpsw_acl_attr { ++ uint16_t max_entries; ++ uint16_t num_entries; ++ uint16_t num_ifs; ++}; ++ ++/** ++* dpsw_acl_get_attributes() - Get specific counter of particular interface ++* @mc_io: Pointer to MC portal's I/O object ++* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++* @token: Token of DPSW object ++* @acl_id: ACL Identifier ++* @attr: Returned ACL attributes ++* ++* Return: '0' on Success; Error code otherwise. ++*/ ++int dpsw_acl_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ uint16_t acl_id, ++ struct dpsw_acl_attr *attr); ++/** ++* struct dpsw_ctrl_if_attr - Control interface attributes ++* @rx_fqid: Receive FQID ++* @rx_err_fqid: Receive error FQID ++* @tx_err_conf_fqid: Transmit error and confirmation FQID ++*/ ++struct dpsw_ctrl_if_attr { ++ uint32_t rx_fqid; ++ uint32_t rx_err_fqid; ++ uint32_t tx_err_conf_fqid; ++}; ++ ++/** ++* dpsw_ctrl_if_get_attributes() - Obtain control interface attributes ++* @mc_io: Pointer to MC portal's I/O object ++* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++* @token: Token of DPSW object ++* @attr: Returned control interface attributes ++* ++* Return: '0' on Success; Error code otherwise. ++*/ ++int dpsw_ctrl_if_get_attributes(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ struct dpsw_ctrl_if_attr *attr); ++ ++/** ++ * Maximum number of DPBP ++ */ ++#define DPSW_MAX_DPBP 8 ++ ++/** ++ * struct dpsw_ctrl_if_pools_cfg - Control interface buffer pools configuration ++ * @num_dpbp: Number of DPBPs ++ * @pools: Array of buffer pools parameters; The number of valid entries ++ * must match 'num_dpbp' value ++ */ ++struct dpsw_ctrl_if_pools_cfg { ++ uint8_t num_dpbp; ++ /** ++ * struct pools - Buffer pools parameters ++ * @dpbp_id: DPBP object ID ++ * @buffer_size: Buffer size ++ * @backup_pool: Backup pool ++ */ ++ struct { ++ int dpbp_id; ++ uint16_t buffer_size; ++ int backup_pool; ++ } pools[DPSW_MAX_DPBP]; ++}; ++ ++/** ++* dpsw_ctrl_if_set_pools() - Set control interface buffer pools ++* @mc_io: Pointer to MC portal's I/O object ++* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++* @token: Token of DPSW object ++* @cfg: buffer pools configuration ++* ++* Return: '0' on Success; Error code otherwise. ++*/ ++int dpsw_ctrl_if_set_pools(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ const struct dpsw_ctrl_if_pools_cfg *cfg); ++ ++/** ++* dpsw_ctrl_if_enable() - Enable control interface ++* @mc_io: Pointer to MC portal's I/O object ++* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++* @token: Token of DPSW object ++* ++* Return: '0' on Success; Error code otherwise. ++*/ ++int dpsw_ctrl_if_enable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++/** ++* dpsw_ctrl_if_disable() - Function disables control interface ++* @mc_io: Pointer to MC portal's I/O object ++* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' ++* @token: Token of DPSW object ++* ++* Return: '0' on Success; Error code otherwise. ++*/ ++int dpsw_ctrl_if_disable(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token); ++ ++#endif /* __FSL_DPSW_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_dpsw_cmd.h b/drivers/net/dpaa2/mc/fsl_dpsw_cmd.h +new file mode 100644 +index 0000000..c65fe38 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_dpsw_cmd.h +@@ -0,0 +1,916 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_DPSW_CMD_H ++#define __FSL_DPSW_CMD_H ++ ++/* DPSW Version */ ++#define DPSW_VER_MAJOR 7 ++#define DPSW_VER_MINOR 0 ++ ++/* Command IDs */ ++#define DPSW_CMDID_CLOSE 0x800 ++#define DPSW_CMDID_OPEN 0x802 ++#define DPSW_CMDID_CREATE 0x902 ++#define DPSW_CMDID_DESTROY 0x900 ++ ++#define DPSW_CMDID_ENABLE 0x002 ++#define DPSW_CMDID_DISABLE 0x003 ++#define DPSW_CMDID_GET_ATTR 0x004 ++#define DPSW_CMDID_RESET 0x005 ++#define DPSW_CMDID_IS_ENABLED 0x006 ++ ++#define DPSW_CMDID_SET_IRQ 0x010 ++#define DPSW_CMDID_GET_IRQ 0x011 ++#define DPSW_CMDID_SET_IRQ_ENABLE 0x012 ++#define DPSW_CMDID_GET_IRQ_ENABLE 0x013 ++#define DPSW_CMDID_SET_IRQ_MASK 0x014 ++#define DPSW_CMDID_GET_IRQ_MASK 0x015 ++#define DPSW_CMDID_GET_IRQ_STATUS 0x016 ++#define DPSW_CMDID_CLEAR_IRQ_STATUS 0x017 ++ ++#define DPSW_CMDID_SET_REFLECTION_IF 0x022 ++ ++#define DPSW_CMDID_ADD_CUSTOM_TPID 0x024 ++ ++#define DPSW_CMDID_REMOVE_CUSTOM_TPID 0x026 ++ ++#define DPSW_CMDID_IF_SET_TCI 0x030 ++#define DPSW_CMDID_IF_SET_STP 0x031 ++#define DPSW_CMDID_IF_SET_ACCEPTED_FRAMES 0x032 ++#define DPSW_CMDID_SET_IF_ACCEPT_ALL_VLAN 0x033 ++#define DPSW_CMDID_IF_GET_COUNTER 0x034 ++#define DPSW_CMDID_IF_SET_COUNTER 0x035 ++#define DPSW_CMDID_IF_SET_TX_SELECTION 0x036 ++#define DPSW_CMDID_IF_ADD_REFLECTION 0x037 ++#define DPSW_CMDID_IF_REMOVE_REFLECTION 0x038 ++#define DPSW_CMDID_IF_SET_FLOODING_METERING 0x039 ++#define DPSW_CMDID_IF_SET_METERING 0x03A ++#define DPSW_CMDID_IF_SET_EARLY_DROP 0x03B ++ ++#define DPSW_CMDID_IF_ENABLE 0x03D ++#define DPSW_CMDID_IF_DISABLE 0x03E ++ ++#define DPSW_CMDID_IF_GET_ATTR 0x042 ++ ++#define DPSW_CMDID_IF_SET_MAX_FRAME_LENGTH 0x044 ++#define DPSW_CMDID_IF_GET_MAX_FRAME_LENGTH 0x045 ++#define DPSW_CMDID_IF_GET_LINK_STATE 0x046 ++#define DPSW_CMDID_IF_SET_FLOODING 0x047 ++#define DPSW_CMDID_IF_SET_BROADCAST 0x048 ++#define DPSW_CMDID_IF_SET_MULTICAST 0x049 ++#define DPSW_CMDID_IF_GET_TCI 0x04A ++ ++#define DPSW_CMDID_IF_SET_LINK_CFG 0x04C ++ ++#define DPSW_CMDID_VLAN_ADD 0x060 ++#define DPSW_CMDID_VLAN_ADD_IF 0x061 ++#define DPSW_CMDID_VLAN_ADD_IF_UNTAGGED 0x062 ++#define DPSW_CMDID_VLAN_ADD_IF_FLOODING 0x063 ++#define DPSW_CMDID_VLAN_REMOVE_IF 0x064 ++#define DPSW_CMDID_VLAN_REMOVE_IF_UNTAGGED 0x065 ++#define DPSW_CMDID_VLAN_REMOVE_IF_FLOODING 0x066 ++#define DPSW_CMDID_VLAN_REMOVE 0x067 ++#define DPSW_CMDID_VLAN_GET_IF 0x068 ++#define DPSW_CMDID_VLAN_GET_IF_FLOODING 0x069 ++#define DPSW_CMDID_VLAN_GET_IF_UNTAGGED 0x06A ++#define DPSW_CMDID_VLAN_GET_ATTRIBUTES 0x06B ++ ++#define DPSW_CMDID_FDB_GET_MULTICAST 0x080 ++#define DPSW_CMDID_FDB_GET_UNICAST 0x081 ++#define DPSW_CMDID_FDB_ADD 0x082 ++#define DPSW_CMDID_FDB_REMOVE 0x083 ++#define DPSW_CMDID_FDB_ADD_UNICAST 0x084 ++#define DPSW_CMDID_FDB_REMOVE_UNICAST 0x085 ++#define DPSW_CMDID_FDB_ADD_MULTICAST 0x086 ++#define DPSW_CMDID_FDB_REMOVE_MULTICAST 0x087 ++#define DPSW_CMDID_FDB_SET_LEARNING_MODE 0x088 ++#define DPSW_CMDID_FDB_GET_ATTR 0x089 ++ ++#define DPSW_CMDID_ACL_ADD 0x090 ++#define DPSW_CMDID_ACL_REMOVE 0x091 ++#define DPSW_CMDID_ACL_ADD_ENTRY 0x092 ++#define DPSW_CMDID_ACL_REMOVE_ENTRY 0x093 ++#define DPSW_CMDID_ACL_ADD_IF 0x094 ++#define DPSW_CMDID_ACL_REMOVE_IF 0x095 ++#define DPSW_CMDID_ACL_GET_ATTR 0x096 ++ ++#define DPSW_CMDID_CTRL_IF_GET_ATTR 0x0A0 ++#define DPSW_CMDID_CTRL_IF_SET_POOLS 0x0A1 ++#define DPSW_CMDID_CTRL_IF_ENABLE 0x0A2 ++#define DPSW_CMDID_CTRL_IF_DISABLE 0x0A3 ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_OPEN(cmd, dpsw_id) \ ++ MC_CMD_OP(cmd, 0, 0, 32, int, dpsw_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_CREATE(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, cfg->num_ifs);\ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, cfg->adv.max_fdbs);\ ++ MC_CMD_OP(cmd, 0, 24, 8, uint8_t, cfg->adv.max_meters_per_if);\ ++ MC_CMD_OP(cmd, 0, 32, 4, enum dpsw_component_type, \ ++ cfg->adv.component_type);\ ++ MC_CMD_OP(cmd, 1, 0, 16, uint16_t, cfg->adv.max_vlans);\ ++ MC_CMD_OP(cmd, 1, 16, 16, uint16_t, cfg->adv.max_fdb_entries);\ ++ MC_CMD_OP(cmd, 1, 32, 16, uint16_t, cfg->adv.fdb_aging_time);\ ++ MC_CMD_OP(cmd, 1, 48, 16, uint16_t, cfg->adv.max_fdb_mc_groups);\ ++ MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->adv.options);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_IS_ENABLED(cmd, en) \ ++ MC_RSP_OP(cmd, 0, 0, 1, int, en) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, irq_index);\ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, irq_cfg->val);\ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\ ++ MC_CMD_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_GET_IRQ(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_GET_IRQ(cmd, type, irq_cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_cfg->val); \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_cfg->addr);\ ++ MC_RSP_OP(cmd, 2, 0, 32, int, irq_cfg->irq_num); \ ++ MC_RSP_OP(cmd, 2, 32, 32, int, type); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_SET_IRQ_ENABLE(cmd, irq_index, enable_state) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, enable_state); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_GET_IRQ_ENABLE(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_GET_IRQ_ENABLE(cmd, enable_state) \ ++ MC_RSP_OP(cmd, 0, 0, 8, uint8_t, enable_state) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, mask); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_GET_IRQ_MASK(cmd, irq_index) \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_GET_IRQ_MASK(cmd, mask) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mask) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_GET_IRQ_STATUS(cmd, status) \ ++ MC_RSP_OP(cmd, 0, 0, 32, uint32_t, status) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status); \ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_GET_ATTR(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 16, uint16_t, attr->num_ifs);\ ++ MC_RSP_OP(cmd, 0, 16, 8, uint8_t, attr->max_fdbs);\ ++ MC_RSP_OP(cmd, 0, 24, 8, uint8_t, attr->num_fdbs);\ ++ MC_RSP_OP(cmd, 0, 32, 16, uint16_t, attr->max_vlans);\ ++ MC_RSP_OP(cmd, 0, 48, 16, uint16_t, attr->num_vlans);\ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->version.major);\ ++ MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->version.minor);\ ++ MC_RSP_OP(cmd, 1, 32, 16, uint16_t, attr->max_fdb_entries);\ ++ MC_RSP_OP(cmd, 1, 48, 16, uint16_t, attr->fdb_aging_time);\ ++ MC_RSP_OP(cmd, 2, 0, 32, int, attr->id);\ ++ MC_RSP_OP(cmd, 2, 32, 16, uint16_t, attr->mem_size);\ ++ MC_RSP_OP(cmd, 2, 48, 16, uint16_t, attr->max_fdb_mc_groups);\ ++ MC_RSP_OP(cmd, 3, 0, 64, uint64_t, attr->options);\ ++ MC_RSP_OP(cmd, 4, 0, 8, uint8_t, attr->max_meters_per_if);\ ++ MC_RSP_OP(cmd, 4, 8, 4, enum dpsw_component_type, \ ++ attr->component_type);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_SET_REFLECTION_IF(cmd, if_id) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_SET_FLOODING(cmd, if_id, en) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 16, 1, int, en);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_SET_BROADCAST(cmd, if_id, en) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 16, 1, int, en);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_SET_MULTICAST(cmd, if_id, en) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 16, 1, int, en);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_SET_TCI(cmd, if_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 16, 12, uint16_t, cfg->vlan_id);\ ++ MC_CMD_OP(cmd, 0, 28, 1, uint8_t, cfg->dei);\ ++ MC_CMD_OP(cmd, 0, 29, 3, uint8_t, cfg->pcp);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_GET_TCI(cmd, if_id) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_IF_GET_TCI(cmd, cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 16, 16, uint16_t, cfg->vlan_id);\ ++ MC_RSP_OP(cmd, 0, 32, 8, uint8_t, cfg->dei);\ ++ MC_RSP_OP(cmd, 0, 40, 8, uint8_t, cfg->pcp);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_SET_STP(cmd, if_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->vlan_id);\ ++ MC_CMD_OP(cmd, 0, 32, 4, enum dpsw_stp_state, cfg->state);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_SET_ACCEPTED_FRAMES(cmd, if_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 16, 4, enum dpsw_accepted_frames, cfg->type);\ ++ MC_CMD_OP(cmd, 0, 20, 4, enum dpsw_action, cfg->unaccept_act);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_SET_ACCEPT_ALL_VLAN(cmd, if_id, accept_all) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 16, 1, int, accept_all);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_GET_COUNTER(cmd, if_id, type) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 16, 5, enum dpsw_counter, type);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_IF_GET_COUNTER(cmd, counter) \ ++ MC_RSP_OP(cmd, 1, 0, 64, uint64_t, counter) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_SET_COUNTER(cmd, if_id, type, counter) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 16, 5, enum dpsw_counter, type);\ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, counter);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_SET_TX_SELECTION(cmd, if_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 16, 3, enum dpsw_priority_selector, \ ++ cfg->priority_selector);\ ++ MC_CMD_OP(cmd, 1, 0, 8, uint8_t, cfg->tc_id[0]);\ ++ MC_CMD_OP(cmd, 1, 8, 8, uint8_t, cfg->tc_id[1]);\ ++ MC_CMD_OP(cmd, 1, 16, 8, uint8_t, cfg->tc_id[2]);\ ++ MC_CMD_OP(cmd, 1, 24, 8, uint8_t, cfg->tc_id[3]);\ ++ MC_CMD_OP(cmd, 1, 32, 8, uint8_t, cfg->tc_id[4]);\ ++ MC_CMD_OP(cmd, 1, 40, 8, uint8_t, cfg->tc_id[5]);\ ++ MC_CMD_OP(cmd, 1, 48, 8, uint8_t, cfg->tc_id[6]);\ ++ MC_CMD_OP(cmd, 1, 56, 8, uint8_t, cfg->tc_id[7]);\ ++ MC_CMD_OP(cmd, 2, 0, 16, uint16_t, cfg->tc_sched[0].delta_bandwidth);\ ++ MC_CMD_OP(cmd, 2, 16, 4, enum dpsw_schedule_mode, \ ++ cfg->tc_sched[0].mode);\ ++ MC_CMD_OP(cmd, 2, 32, 16, uint16_t, cfg->tc_sched[1].delta_bandwidth);\ ++ MC_CMD_OP(cmd, 2, 48, 4, enum dpsw_schedule_mode, \ ++ cfg->tc_sched[1].mode);\ ++ MC_CMD_OP(cmd, 3, 0, 16, uint16_t, cfg->tc_sched[2].delta_bandwidth);\ ++ MC_CMD_OP(cmd, 3, 16, 4, enum dpsw_schedule_mode, \ ++ cfg->tc_sched[2].mode);\ ++ MC_CMD_OP(cmd, 3, 32, 16, uint16_t, cfg->tc_sched[3].delta_bandwidth);\ ++ MC_CMD_OP(cmd, 3, 48, 4, enum dpsw_schedule_mode, \ ++ cfg->tc_sched[3].mode);\ ++ MC_CMD_OP(cmd, 4, 0, 16, uint16_t, cfg->tc_sched[4].delta_bandwidth);\ ++ MC_CMD_OP(cmd, 4, 16, 4, enum dpsw_schedule_mode, \ ++ cfg->tc_sched[4].mode);\ ++ MC_CMD_OP(cmd, 4, 32, 16, uint16_t, cfg->tc_sched[5].delta_bandwidth);\ ++ MC_CMD_OP(cmd, 4, 48, 4, enum dpsw_schedule_mode, \ ++ cfg->tc_sched[5].mode);\ ++ MC_CMD_OP(cmd, 5, 0, 16, uint16_t, cfg->tc_sched[6].delta_bandwidth);\ ++ MC_CMD_OP(cmd, 5, 16, 4, enum dpsw_schedule_mode, \ ++ cfg->tc_sched[6].mode);\ ++ MC_CMD_OP(cmd, 5, 32, 16, uint16_t, cfg->tc_sched[7].delta_bandwidth);\ ++ MC_CMD_OP(cmd, 5, 48, 4, enum dpsw_schedule_mode, \ ++ cfg->tc_sched[7].mode);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_ADD_REFLECTION(cmd, if_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->vlan_id);\ ++ MC_CMD_OP(cmd, 0, 32, 2, enum dpsw_reflection_filter, cfg->filter);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_REMOVE_REFLECTION(cmd, if_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->vlan_id);\ ++ MC_CMD_OP(cmd, 0, 32, 2, enum dpsw_reflection_filter, cfg->filter);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_SET_FLOODING_METERING(cmd, if_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 24, 4, enum dpsw_metering_mode, cfg->mode);\ ++ MC_CMD_OP(cmd, 0, 28, 4, enum dpsw_metering_unit, cfg->units);\ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, cfg->cir);\ ++ MC_CMD_OP(cmd, 1, 0, 32, uint32_t, cfg->eir);\ ++ MC_CMD_OP(cmd, 1, 32, 32, uint32_t, cfg->cbs);\ ++ MC_CMD_OP(cmd, 2, 0, 32, uint32_t, cfg->ebs);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_SET_METERING(cmd, if_id, tc_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, tc_id);\ ++ MC_CMD_OP(cmd, 0, 24, 4, enum dpsw_metering_mode, cfg->mode);\ ++ MC_CMD_OP(cmd, 0, 28, 4, enum dpsw_metering_unit, cfg->units);\ ++ MC_CMD_OP(cmd, 0, 32, 32, uint32_t, cfg->cir);\ ++ MC_CMD_OP(cmd, 1, 0, 32, uint32_t, cfg->eir);\ ++ MC_CMD_OP(cmd, 1, 32, 32, uint32_t, cfg->cbs);\ ++ MC_CMD_OP(cmd, 2, 0, 32, uint32_t, cfg->ebs);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_PREP_EARLY_DROP(ext, cfg) \ ++do { \ ++ MC_PREP_OP(ext, 0, 0, 2, enum dpsw_early_drop_mode, cfg->drop_mode); \ ++ MC_PREP_OP(ext, 0, 2, 2, \ ++ enum dpsw_early_drop_unit, cfg->units); \ ++ MC_PREP_OP(ext, 0, 32, 32, uint32_t, cfg->tail_drop_threshold); \ ++ MC_PREP_OP(ext, 1, 0, 8, uint8_t, cfg->green.drop_probability); \ ++ MC_PREP_OP(ext, 2, 0, 64, uint64_t, cfg->green.max_threshold); \ ++ MC_PREP_OP(ext, 3, 0, 64, uint64_t, cfg->green.min_threshold); \ ++ MC_PREP_OP(ext, 5, 0, 8, uint8_t, cfg->yellow.drop_probability);\ ++ MC_PREP_OP(ext, 6, 0, 64, uint64_t, cfg->yellow.max_threshold); \ ++ MC_PREP_OP(ext, 7, 0, 64, uint64_t, cfg->yellow.min_threshold); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_EXT_EARLY_DROP(ext, cfg) \ ++do { \ ++ MC_EXT_OP(ext, 0, 0, 2, enum dpsw_early_drop_mode, cfg->drop_mode); \ ++ MC_EXT_OP(ext, 0, 2, 2, \ ++ enum dpsw_early_drop_unit, cfg->units); \ ++ MC_EXT_OP(ext, 0, 32, 32, uint32_t, cfg->tail_drop_threshold); \ ++ MC_EXT_OP(ext, 1, 0, 8, uint8_t, cfg->green.drop_probability); \ ++ MC_EXT_OP(ext, 2, 0, 64, uint64_t, cfg->green.max_threshold); \ ++ MC_EXT_OP(ext, 3, 0, 64, uint64_t, cfg->green.min_threshold); \ ++ MC_EXT_OP(ext, 5, 0, 8, uint8_t, cfg->yellow.drop_probability);\ ++ MC_EXT_OP(ext, 6, 0, 64, uint64_t, cfg->yellow.max_threshold); \ ++ MC_EXT_OP(ext, 7, 0, 64, uint64_t, cfg->yellow.min_threshold); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_SET_EARLY_DROP(cmd, if_id, tc_id, early_drop_iova) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 8, 8, uint8_t, tc_id); \ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, if_id); \ ++ MC_CMD_OP(cmd, 1, 0, 64, uint64_t, early_drop_iova); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_ADD_CUSTOM_TPID(cmd, cfg) \ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->tpid) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_REMOVE_CUSTOM_TPID(cmd, cfg) \ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->tpid) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_ENABLE(cmd, if_id) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_DISABLE(cmd, if_id) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_GET_ATTR(cmd, if_id) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_IF_GET_ATTR(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 0, 4, enum dpsw_accepted_frames, \ ++ attr->admit_untagged);\ ++ MC_RSP_OP(cmd, 0, 5, 1, int, attr->enabled);\ ++ MC_RSP_OP(cmd, 0, 6, 1, int, attr->accept_all_vlan);\ ++ MC_RSP_OP(cmd, 0, 16, 8, uint8_t, attr->num_tcs);\ ++ MC_RSP_OP(cmd, 0, 32, 16, uint16_t, attr->qdid);\ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, attr->options);\ ++ MC_RSP_OP(cmd, 2, 0, 32, uint32_t, attr->rate);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_SET_MAX_FRAME_LENGTH(cmd, if_id, frame_length) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, frame_length);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_GET_MAX_FRAME_LENGTH(cmd, if_id) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_IF_GET_MAX_FRAME_LENGTH(cmd, frame_length) \ ++ MC_RSP_OP(cmd, 0, 16, 16, uint16_t, frame_length) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_SET_LINK_CFG(cmd, if_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id);\ ++ MC_CMD_OP(cmd, 1, 0, 32, uint32_t, cfg->rate);\ ++ MC_CMD_OP(cmd, 2, 0, 64, uint64_t, cfg->options);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_IF_GET_LINK_STATE(cmd, if_id) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, if_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_IF_GET_LINK_STATE(cmd, state) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 32, 1, int, state->up);\ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, state->rate);\ ++ MC_RSP_OP(cmd, 2, 0, 64, uint64_t, state->options);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_VLAN_ADD(cmd, vlan_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, cfg->fdb_id);\ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, vlan_id);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_VLAN_ADD_IF(cmd, vlan_id) \ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, vlan_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_VLAN_ADD_IF_UNTAGGED(cmd, vlan_id) \ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, vlan_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_VLAN_ADD_IF_FLOODING(cmd, vlan_id) \ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, vlan_id) ++ ++#define DPSW_CMD_VLAN_REMOVE_IF(cmd, vlan_id) \ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, vlan_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_VLAN_REMOVE_IF_UNTAGGED(cmd, vlan_id) \ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, vlan_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_VLAN_REMOVE_IF_FLOODING(cmd, vlan_id) \ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, vlan_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_VLAN_REMOVE(cmd, vlan_id) \ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, vlan_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_VLAN_GET_ATTR(cmd, vlan_id) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, vlan_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_VLAN_GET_ATTR(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->fdb_id); \ ++ MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->num_ifs); \ ++ MC_RSP_OP(cmd, 1, 32, 16, uint16_t, attr->num_untagged_ifs); \ ++ MC_RSP_OP(cmd, 1, 48, 16, uint16_t, attr->num_flooding_ifs); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_VLAN_GET_IF(cmd, vlan_id) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, vlan_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_VLAN_GET_IF(cmd, cfg) \ ++ MC_RSP_OP(cmd, 0, 16, 16, uint16_t, cfg->num_ifs) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_VLAN_GET_IF_FLOODING(cmd, vlan_id) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, vlan_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_VLAN_GET_IF_FLOODING(cmd, cfg) \ ++ MC_RSP_OP(cmd, 0, 16, 16, uint16_t, cfg->num_ifs) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_VLAN_GET_IF_UNTAGGED(cmd, vlan_id) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, vlan_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_VLAN_GET_IF_UNTAGGED(cmd, cfg) \ ++ MC_RSP_OP(cmd, 0, 16, 16, uint16_t, cfg->num_ifs) ++ ++/* param, offset, width, type, arg_name */ ++#define DPSW_CMD_FDB_ADD(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 32, 16, uint16_t, cfg->fdb_aging_time);\ ++ MC_CMD_OP(cmd, 0, 48, 16, uint16_t, cfg->num_fdb_entries);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_FDB_ADD(cmd, fdb_id) \ ++ MC_RSP_OP(cmd, 0, 0, 16, uint16_t, fdb_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_FDB_REMOVE(cmd, fdb_id) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, fdb_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_FDB_ADD_UNICAST(cmd, fdb_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, fdb_id);\ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, cfg->mac_addr[5]);\ ++ MC_CMD_OP(cmd, 0, 24, 8, uint8_t, cfg->mac_addr[4]);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->mac_addr[3]);\ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, cfg->mac_addr[2]);\ ++ MC_CMD_OP(cmd, 0, 48, 8, uint8_t, cfg->mac_addr[1]);\ ++ MC_CMD_OP(cmd, 0, 56, 8, uint8_t, cfg->mac_addr[0]);\ ++ MC_CMD_OP(cmd, 1, 0, 8, uint16_t, cfg->if_egress);\ ++ MC_CMD_OP(cmd, 1, 16, 4, enum dpsw_fdb_entry_type, cfg->type);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_FDB_GET_UNICAST(cmd, fdb_id) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, fdb_id);\ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, cfg->mac_addr[5]);\ ++ MC_CMD_OP(cmd, 0, 24, 8, uint8_t, cfg->mac_addr[4]);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->mac_addr[3]);\ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, cfg->mac_addr[2]);\ ++ MC_CMD_OP(cmd, 0, 48, 8, uint8_t, cfg->mac_addr[1]);\ ++ MC_CMD_OP(cmd, 0, 56, 8, uint8_t, cfg->mac_addr[0]);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_FDB_GET_UNICAST(cmd, cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, cfg->if_egress);\ ++ MC_RSP_OP(cmd, 1, 16, 4, enum dpsw_fdb_entry_type, cfg->type);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_FDB_REMOVE_UNICAST(cmd, fdb_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, fdb_id);\ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, cfg->mac_addr[5]);\ ++ MC_CMD_OP(cmd, 0, 24, 8, uint8_t, cfg->mac_addr[4]);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->mac_addr[3]);\ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, cfg->mac_addr[2]);\ ++ MC_CMD_OP(cmd, 0, 48, 8, uint8_t, cfg->mac_addr[1]);\ ++ MC_CMD_OP(cmd, 0, 56, 8, uint8_t, cfg->mac_addr[0]);\ ++ MC_CMD_OP(cmd, 1, 0, 16, uint16_t, cfg->if_egress);\ ++ MC_CMD_OP(cmd, 1, 16, 4, enum dpsw_fdb_entry_type, cfg->type);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_FDB_ADD_MULTICAST(cmd, fdb_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, fdb_id);\ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->num_ifs);\ ++ MC_CMD_OP(cmd, 0, 32, 4, enum dpsw_fdb_entry_type, cfg->type);\ ++ MC_CMD_OP(cmd, 1, 0, 8, uint8_t, cfg->mac_addr[5]);\ ++ MC_CMD_OP(cmd, 1, 8, 8, uint8_t, cfg->mac_addr[4]);\ ++ MC_CMD_OP(cmd, 1, 16, 8, uint8_t, cfg->mac_addr[3]);\ ++ MC_CMD_OP(cmd, 1, 24, 8, uint8_t, cfg->mac_addr[2]);\ ++ MC_CMD_OP(cmd, 1, 32, 8, uint8_t, cfg->mac_addr[1]);\ ++ MC_CMD_OP(cmd, 1, 40, 8, uint8_t, cfg->mac_addr[0]);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_FDB_GET_MULTICAST(cmd, fdb_id) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, fdb_id);\ ++ MC_CMD_OP(cmd, 0, 16, 8, uint8_t, cfg->mac_addr[5]);\ ++ MC_CMD_OP(cmd, 0, 24, 8, uint8_t, cfg->mac_addr[4]);\ ++ MC_CMD_OP(cmd, 0, 32, 8, uint8_t, cfg->mac_addr[3]);\ ++ MC_CMD_OP(cmd, 0, 40, 8, uint8_t, cfg->mac_addr[2]);\ ++ MC_CMD_OP(cmd, 0, 48, 8, uint8_t, cfg->mac_addr[1]);\ ++ MC_CMD_OP(cmd, 0, 56, 8, uint8_t, cfg->mac_addr[0]);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_FDB_GET_MULTICAST(cmd, cfg) \ ++do { \ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, cfg->num_ifs);\ ++ MC_RSP_OP(cmd, 1, 16, 4, enum dpsw_fdb_entry_type, cfg->type);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_FDB_REMOVE_MULTICAST(cmd, fdb_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, fdb_id);\ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->num_ifs);\ ++ MC_CMD_OP(cmd, 0, 32, 4, enum dpsw_fdb_entry_type, cfg->type);\ ++ MC_CMD_OP(cmd, 1, 0, 8, uint8_t, cfg->mac_addr[5]);\ ++ MC_CMD_OP(cmd, 1, 8, 8, uint8_t, cfg->mac_addr[4]);\ ++ MC_CMD_OP(cmd, 1, 16, 8, uint8_t, cfg->mac_addr[3]);\ ++ MC_CMD_OP(cmd, 1, 24, 8, uint8_t, cfg->mac_addr[2]);\ ++ MC_CMD_OP(cmd, 1, 32, 8, uint8_t, cfg->mac_addr[1]);\ ++ MC_CMD_OP(cmd, 1, 40, 8, uint8_t, cfg->mac_addr[0]);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_FDB_SET_LEARNING_MODE(cmd, fdb_id, mode) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, fdb_id);\ ++ MC_CMD_OP(cmd, 0, 16, 4, enum dpsw_fdb_learning_mode, mode);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_FDB_GET_ATTR(cmd, fdb_id) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, fdb_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_FDB_GET_ATTR(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 0, 16, 16, uint16_t, attr->max_fdb_entries);\ ++ MC_RSP_OP(cmd, 0, 32, 16, uint16_t, attr->fdb_aging_time);\ ++ MC_RSP_OP(cmd, 0, 48, 16, uint16_t, attr->num_fdb_mc_groups);\ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->max_fdb_mc_groups);\ ++ MC_RSP_OP(cmd, 1, 16, 4, enum dpsw_fdb_learning_mode, \ ++ attr->learning_mode);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_ACL_ADD(cmd, cfg) \ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->max_entries) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_ACL_ADD(cmd, acl_id) \ ++ MC_RSP_OP(cmd, 0, 0, 16, uint16_t, acl_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_ACL_REMOVE(cmd, acl_id) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, acl_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_PREP_ACL_ENTRY(ext, key) \ ++do { \ ++ MC_PREP_OP(ext, 0, 0, 8, uint8_t, key->match.l2_dest_mac[5]);\ ++ MC_PREP_OP(ext, 0, 8, 8, uint8_t, key->match.l2_dest_mac[4]);\ ++ MC_PREP_OP(ext, 0, 16, 8, uint8_t, key->match.l2_dest_mac[3]);\ ++ MC_PREP_OP(ext, 0, 24, 8, uint8_t, key->match.l2_dest_mac[2]);\ ++ MC_PREP_OP(ext, 0, 32, 8, uint8_t, key->match.l2_dest_mac[1]);\ ++ MC_PREP_OP(ext, 0, 40, 8, uint8_t, key->match.l2_dest_mac[0]);\ ++ MC_PREP_OP(ext, 0, 48, 16, uint16_t, key->match.l2_tpid);\ ++ MC_PREP_OP(ext, 1, 0, 8, uint8_t, key->match.l2_source_mac[5]);\ ++ MC_PREP_OP(ext, 1, 8, 8, uint8_t, key->match.l2_source_mac[4]);\ ++ MC_PREP_OP(ext, 1, 16, 8, uint8_t, key->match.l2_source_mac[3]);\ ++ MC_PREP_OP(ext, 1, 24, 8, uint8_t, key->match.l2_source_mac[2]);\ ++ MC_PREP_OP(ext, 1, 32, 8, uint8_t, key->match.l2_source_mac[1]);\ ++ MC_PREP_OP(ext, 1, 40, 8, uint8_t, key->match.l2_source_mac[0]);\ ++ MC_PREP_OP(ext, 1, 48, 16, uint16_t, key->match.l2_vlan_id);\ ++ MC_PREP_OP(ext, 2, 0, 32, uint32_t, key->match.l3_dest_ip);\ ++ MC_PREP_OP(ext, 2, 32, 32, uint32_t, key->match.l3_source_ip);\ ++ MC_PREP_OP(ext, 3, 0, 16, uint16_t, key->match.l4_dest_port);\ ++ MC_PREP_OP(ext, 3, 16, 16, uint16_t, key->match.l4_source_port);\ ++ MC_PREP_OP(ext, 3, 32, 16, uint16_t, key->match.l2_ether_type);\ ++ MC_PREP_OP(ext, 3, 48, 8, uint8_t, key->match.l2_pcp_dei);\ ++ MC_PREP_OP(ext, 3, 56, 8, uint8_t, key->match.l3_dscp);\ ++ MC_PREP_OP(ext, 4, 0, 8, uint8_t, key->mask.l2_dest_mac[5]);\ ++ MC_PREP_OP(ext, 4, 8, 8, uint8_t, key->mask.l2_dest_mac[4]);\ ++ MC_PREP_OP(ext, 4, 16, 8, uint8_t, key->mask.l2_dest_mac[3]);\ ++ MC_PREP_OP(ext, 4, 24, 8, uint8_t, key->mask.l2_dest_mac[2]);\ ++ MC_PREP_OP(ext, 4, 32, 8, uint8_t, key->mask.l2_dest_mac[1]);\ ++ MC_PREP_OP(ext, 4, 40, 8, uint8_t, key->mask.l2_dest_mac[0]);\ ++ MC_PREP_OP(ext, 4, 48, 16, uint16_t, key->mask.l2_tpid);\ ++ MC_PREP_OP(ext, 5, 0, 8, uint8_t, key->mask.l2_source_mac[5]);\ ++ MC_PREP_OP(ext, 5, 8, 8, uint8_t, key->mask.l2_source_mac[4]);\ ++ MC_PREP_OP(ext, 5, 16, 8, uint8_t, key->mask.l2_source_mac[3]);\ ++ MC_PREP_OP(ext, 5, 24, 8, uint8_t, key->mask.l2_source_mac[2]);\ ++ MC_PREP_OP(ext, 5, 32, 8, uint8_t, key->mask.l2_source_mac[1]);\ ++ MC_PREP_OP(ext, 5, 40, 8, uint8_t, key->mask.l2_source_mac[0]);\ ++ MC_PREP_OP(ext, 5, 48, 16, uint16_t, key->mask.l2_vlan_id);\ ++ MC_PREP_OP(ext, 6, 0, 32, uint32_t, key->mask.l3_dest_ip);\ ++ MC_PREP_OP(ext, 6, 32, 32, uint32_t, key->mask.l3_source_ip);\ ++ MC_PREP_OP(ext, 7, 0, 16, uint16_t, key->mask.l4_dest_port);\ ++ MC_PREP_OP(ext, 7, 16, 16, uint16_t, key->mask.l4_source_port);\ ++ MC_PREP_OP(ext, 7, 32, 16, uint16_t, key->mask.l2_ether_type);\ ++ MC_PREP_OP(ext, 7, 48, 8, uint8_t, key->mask.l2_pcp_dei);\ ++ MC_PREP_OP(ext, 7, 56, 8, uint8_t, key->mask.l3_dscp);\ ++ MC_PREP_OP(ext, 8, 0, 8, uint8_t, key->match.l3_protocol);\ ++ MC_PREP_OP(ext, 8, 8, 8, uint8_t, key->mask.l3_protocol);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_EXT_ACL_ENTRY(ext, key) \ ++do { \ ++ MC_EXT_OP(ext, 0, 0, 8, uint8_t, key->match.l2_dest_mac[5]);\ ++ MC_EXT_OP(ext, 0, 8, 8, uint8_t, key->match.l2_dest_mac[4]);\ ++ MC_EXT_OP(ext, 0, 16, 8, uint8_t, key->match.l2_dest_mac[3]);\ ++ MC_EXT_OP(ext, 0, 24, 8, uint8_t, key->match.l2_dest_mac[2]);\ ++ MC_EXT_OP(ext, 0, 32, 8, uint8_t, key->match.l2_dest_mac[1]);\ ++ MC_EXT_OP(ext, 0, 40, 8, uint8_t, key->match.l2_dest_mac[0]);\ ++ MC_EXT_OP(ext, 0, 48, 16, uint16_t, key->match.l2_tpid);\ ++ MC_EXT_OP(ext, 1, 0, 8, uint8_t, key->match.l2_source_mac[5]);\ ++ MC_EXT_OP(ext, 1, 8, 8, uint8_t, key->match.l2_source_mac[4]);\ ++ MC_EXT_OP(ext, 1, 16, 8, uint8_t, key->match.l2_source_mac[3]);\ ++ MC_EXT_OP(ext, 1, 24, 8, uint8_t, key->match.l2_source_mac[2]);\ ++ MC_EXT_OP(ext, 1, 32, 8, uint8_t, key->match.l2_source_mac[1]);\ ++ MC_EXT_OP(ext, 1, 40, 8, uint8_t, key->match.l2_source_mac[0]);\ ++ MC_EXT_OP(ext, 1, 48, 16, uint16_t, key->match.l2_vlan_id);\ ++ MC_EXT_OP(ext, 2, 0, 32, uint32_t, key->match.l3_dest_ip);\ ++ MC_EXT_OP(ext, 2, 32, 32, uint32_t, key->match.l3_source_ip);\ ++ MC_EXT_OP(ext, 3, 0, 16, uint16_t, key->match.l4_dest_port);\ ++ MC_EXT_OP(ext, 3, 16, 16, uint16_t, key->match.l4_source_port);\ ++ MC_EXT_OP(ext, 3, 32, 16, uint16_t, key->match.l2_ether_type);\ ++ MC_EXT_OP(ext, 3, 48, 8, uint8_t, key->match.l2_pcp_dei);\ ++ MC_EXT_OP(ext, 3, 56, 8, uint8_t, key->match.l3_dscp);\ ++ MC_EXT_OP(ext, 4, 0, 8, uint8_t, key->mask.l2_dest_mac[5]);\ ++ MC_EXT_OP(ext, 4, 8, 8, uint8_t, key->mask.l2_dest_mac[4]);\ ++ MC_EXT_OP(ext, 4, 16, 8, uint8_t, key->mask.l2_dest_mac[3]);\ ++ MC_EXT_OP(ext, 4, 24, 8, uint8_t, key->mask.l2_dest_mac[2]);\ ++ MC_EXT_OP(ext, 4, 32, 8, uint8_t, key->mask.l2_dest_mac[1]);\ ++ MC_EXT_OP(ext, 4, 40, 8, uint8_t, key->mask.l2_dest_mac[0]);\ ++ MC_EXT_OP(ext, 4, 48, 16, uint16_t, key->mask.l2_tpid);\ ++ MC_EXT_OP(ext, 5, 0, 8, uint8_t, key->mask.l2_source_mac[5]);\ ++ MC_EXT_OP(ext, 5, 8, 8, uint8_t, key->mask.l2_source_mac[4]);\ ++ MC_EXT_OP(ext, 5, 16, 8, uint8_t, key->mask.l2_source_mac[3]);\ ++ MC_EXT_OP(ext, 5, 24, 8, uint8_t, key->mask.l2_source_mac[2]);\ ++ MC_EXT_OP(ext, 5, 32, 8, uint8_t, key->mask.l2_source_mac[1]);\ ++ MC_EXT_OP(ext, 5, 40, 8, uint8_t, key->mask.l2_source_mac[0]);\ ++ MC_EXT_OP(ext, 5, 48, 16, uint16_t, key->mask.l2_vlan_id);\ ++ MC_EXT_OP(ext, 6, 0, 32, uint32_t, key->mask.l3_dest_ip);\ ++ MC_EXT_OP(ext, 6, 32, 32, uint32_t, key->mask.l3_source_ip);\ ++ MC_EXT_OP(ext, 7, 0, 16, uint16_t, key->mask.l4_dest_port);\ ++ MC_EXT_OP(ext, 7, 16, 16, uint16_t, key->mask.l4_source_port);\ ++ MC_EXT_OP(ext, 7, 32, 16, uint16_t, key->mask.l2_ether_type);\ ++ MC_EXT_OP(ext, 7, 48, 8, uint8_t, key->mask.l2_pcp_dei);\ ++ MC_EXT_OP(ext, 7, 56, 8, uint8_t, key->mask.l3_dscp);\ ++ MC_EXT_OP(ext, 8, 0, 8, uint8_t, key->match.l3_protocol);\ ++ MC_EXT_OP(ext, 8, 8, 8, uint8_t, key->mask.l3_protocol);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_ACL_ADD_ENTRY(cmd, acl_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, acl_id);\ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->result.if_id);\ ++ MC_CMD_OP(cmd, 0, 32, 32, int, cfg->precedence);\ ++ MC_CMD_OP(cmd, 1, 0, 4, enum dpsw_acl_action, cfg->result.action);\ ++ MC_CMD_OP(cmd, 6, 0, 64, uint64_t, cfg->key_iova); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_ACL_REMOVE_ENTRY(cmd, acl_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, acl_id);\ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->result.if_id);\ ++ MC_CMD_OP(cmd, 0, 32, 32, int, cfg->precedence);\ ++ MC_CMD_OP(cmd, 1, 0, 4, enum dpsw_acl_action, cfg->result.action);\ ++ MC_CMD_OP(cmd, 6, 0, 64, uint64_t, cfg->key_iova); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_ACL_ADD_IF(cmd, acl_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, acl_id);\ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->num_ifs); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_ACL_REMOVE_IF(cmd, acl_id, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, acl_id);\ ++ MC_CMD_OP(cmd, 0, 16, 16, uint16_t, cfg->num_ifs); \ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_ACL_GET_ATTR(cmd, acl_id) \ ++ MC_CMD_OP(cmd, 0, 0, 16, uint16_t, acl_id) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_ACL_GET_ATTR(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->max_entries);\ ++ MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->num_entries);\ ++ MC_RSP_OP(cmd, 1, 32, 16, uint16_t, attr->num_ifs);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_RSP_CTRL_IF_GET_ATTR(cmd, attr) \ ++do { \ ++ MC_RSP_OP(cmd, 1, 0, 32, uint32_t, attr->rx_fqid);\ ++ MC_RSP_OP(cmd, 1, 32, 32, uint32_t, attr->rx_err_fqid);\ ++ MC_RSP_OP(cmd, 2, 0, 32, uint32_t, attr->tx_err_conf_fqid);\ ++} while (0) ++ ++/* cmd, param, offset, width, type, arg_name */ ++#define DPSW_CMD_CTRL_IF_SET_POOLS(cmd, cfg) \ ++do { \ ++ MC_CMD_OP(cmd, 0, 0, 8, uint8_t, cfg->num_dpbp); \ ++ MC_CMD_OP(cmd, 0, 8, 1, int, cfg->pools[0].backup_pool); \ ++ MC_CMD_OP(cmd, 0, 9, 1, int, cfg->pools[1].backup_pool); \ ++ MC_CMD_OP(cmd, 0, 10, 1, int, cfg->pools[2].backup_pool); \ ++ MC_CMD_OP(cmd, 0, 11, 1, int, cfg->pools[3].backup_pool); \ ++ MC_CMD_OP(cmd, 0, 12, 1, int, cfg->pools[4].backup_pool); \ ++ MC_CMD_OP(cmd, 0, 13, 1, int, cfg->pools[5].backup_pool); \ ++ MC_CMD_OP(cmd, 0, 14, 1, int, cfg->pools[6].backup_pool); \ ++ MC_CMD_OP(cmd, 0, 15, 1, int, cfg->pools[7].backup_pool); \ ++ MC_CMD_OP(cmd, 0, 32, 32, int, cfg->pools[0].dpbp_id); \ ++ MC_CMD_OP(cmd, 4, 32, 16, uint16_t, cfg->pools[0].buffer_size);\ ++ MC_CMD_OP(cmd, 1, 0, 32, int, cfg->pools[1].dpbp_id); \ ++ MC_CMD_OP(cmd, 4, 48, 16, uint16_t, cfg->pools[1].buffer_size);\ ++ MC_CMD_OP(cmd, 1, 32, 32, int, cfg->pools[2].dpbp_id); \ ++ MC_CMD_OP(cmd, 5, 0, 16, uint16_t, cfg->pools[2].buffer_size);\ ++ MC_CMD_OP(cmd, 2, 0, 32, int, cfg->pools[3].dpbp_id); \ ++ MC_CMD_OP(cmd, 5, 16, 16, uint16_t, cfg->pools[3].buffer_size);\ ++ MC_CMD_OP(cmd, 2, 32, 32, int, cfg->pools[4].dpbp_id); \ ++ MC_CMD_OP(cmd, 5, 32, 16, uint16_t, cfg->pools[4].buffer_size);\ ++ MC_CMD_OP(cmd, 3, 0, 32, int, cfg->pools[5].dpbp_id); \ ++ MC_CMD_OP(cmd, 5, 48, 16, uint16_t, cfg->pools[5].buffer_size);\ ++ MC_CMD_OP(cmd, 3, 32, 32, int, cfg->pools[6].dpbp_id); \ ++ MC_CMD_OP(cmd, 6, 0, 16, uint16_t, cfg->pools[6].buffer_size);\ ++ MC_CMD_OP(cmd, 4, 0, 32, int, cfg->pools[7].dpbp_id); \ ++ MC_CMD_OP(cmd, 6, 16, 16, uint16_t, cfg->pools[7].buffer_size);\ ++} while (0) ++ ++#endif /* __FSL_DPSW_CMD_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_mc_cmd.h b/drivers/net/dpaa2/mc/fsl_mc_cmd.h +new file mode 100644 +index 0000000..ca4fb64 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_mc_cmd.h +@@ -0,0 +1,221 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_MC_CMD_H ++#define __FSL_MC_CMD_H ++ ++#define MC_CMD_NUM_OF_PARAMS 7 ++ ++#define MAKE_UMASK64(_width) \ ++ ((uint64_t)((_width) < 64 ? ((uint64_t)1 << (_width)) - 1 :\ ++ (uint64_t)-1)) ++static inline uint64_t mc_enc(int lsoffset, int width, uint64_t val) ++{ ++ return (uint64_t)(((uint64_t)val & MAKE_UMASK64(width)) << lsoffset); ++} ++ ++static inline uint64_t mc_dec(uint64_t val, int lsoffset, int width) ++{ ++ return (uint64_t)((val >> lsoffset) & MAKE_UMASK64(width)); ++} ++ ++struct mc_command { ++ uint64_t header; ++ uint64_t params[MC_CMD_NUM_OF_PARAMS]; ++}; ++ ++/** ++ * enum mc_cmd_status - indicates MC status at command response ++ * @MC_CMD_STATUS_OK: Completed successfully ++ * @MC_CMD_STATUS_READY: Ready to be processed ++ * @MC_CMD_STATUS_AUTH_ERR: Authentication error ++ * @MC_CMD_STATUS_NO_PRIVILEGE: No privilege ++ * @MC_CMD_STATUS_DMA_ERR: DMA or I/O error ++ * @MC_CMD_STATUS_CONFIG_ERR: Configuration error ++ * @MC_CMD_STATUS_TIMEOUT: Operation timed out ++ * @MC_CMD_STATUS_NO_RESOURCE: No resources ++ * @MC_CMD_STATUS_NO_MEMORY: No memory available ++ * @MC_CMD_STATUS_BUSY: Device is busy ++ * @MC_CMD_STATUS_UNSUPPORTED_OP: Unsupported operation ++ * @MC_CMD_STATUS_INVALID_STATE: Invalid state ++ */ ++enum mc_cmd_status { ++ MC_CMD_STATUS_OK = 0x0, ++ MC_CMD_STATUS_READY = 0x1, ++ MC_CMD_STATUS_AUTH_ERR = 0x3, ++ MC_CMD_STATUS_NO_PRIVILEGE = 0x4, ++ MC_CMD_STATUS_DMA_ERR = 0x5, ++ MC_CMD_STATUS_CONFIG_ERR = 0x6, ++ MC_CMD_STATUS_TIMEOUT = 0x7, ++ MC_CMD_STATUS_NO_RESOURCE = 0x8, ++ MC_CMD_STATUS_NO_MEMORY = 0x9, ++ MC_CMD_STATUS_BUSY = 0xA, ++ MC_CMD_STATUS_UNSUPPORTED_OP = 0xB, ++ MC_CMD_STATUS_INVALID_STATE = 0xC ++}; ++ ++/* MC command flags */ ++ ++/** ++ * High priority flag ++ */ ++#define MC_CMD_FLAG_PRI 0x00008000 ++/** ++ * Command completion flag ++ */ ++#define MC_CMD_FLAG_INTR_DIS 0x01000000 ++ ++/** ++ * Command ID field offset ++ */ ++#define MC_CMD_HDR_CMDID_O 52 ++/** ++ * Command ID field size ++ */ ++#define MC_CMD_HDR_CMDID_S 12 ++/** ++ * Token field offset ++ */ ++#define MC_CMD_HDR_TOKEN_O 38 ++/** ++ * Token field size ++ */ ++#define MC_CMD_HDR_TOKEN_S 10 ++/** ++ * Status field offset ++ */ ++#define MC_CMD_HDR_STATUS_O 16 ++/** ++ * Status field size ++ */ ++#define MC_CMD_HDR_STATUS_S 8 ++/** ++ * Flags field offset ++ */ ++#define MC_CMD_HDR_FLAGS_O 0 ++/** ++ * Flags field size ++ */ ++#define MC_CMD_HDR_FLAGS_S 32 ++/** ++ * Command flags mask ++ */ ++#define MC_CMD_HDR_FLAGS_MASK 0xFF00FF00 ++ ++#define MC_CMD_HDR_READ_STATUS(_hdr) \ ++ ((enum mc_cmd_status)mc_dec((_hdr), \ ++ MC_CMD_HDR_STATUS_O, MC_CMD_HDR_STATUS_S)) ++ ++#define MC_CMD_HDR_READ_TOKEN(_hdr) \ ++ ((uint16_t)mc_dec((_hdr), MC_CMD_HDR_TOKEN_O, MC_CMD_HDR_TOKEN_S)) ++ ++#define MC_PREP_OP(_ext, _param, _offset, _width, _type, _arg) \ ++ ((_ext)[_param] |= cpu_to_le64(mc_enc((_offset), (_width), _arg))) ++ ++#define MC_EXT_OP(_ext, _param, _offset, _width, _type, _arg) \ ++ (_arg = (_type)mc_dec(cpu_to_le64(_ext[_param]), (_offset), (_width))) ++ ++#define MC_CMD_OP(_cmd, _param, _offset, _width, _type, _arg) \ ++ ((_cmd).params[_param] |= mc_enc((_offset), (_width), _arg)) ++ ++#define MC_RSP_OP(_cmd, _param, _offset, _width, _type, _arg) \ ++ (_arg = (_type)mc_dec(_cmd.params[_param], (_offset), (_width))) ++ ++static inline uint64_t mc_encode_cmd_header(uint16_t cmd_id, ++ uint32_t cmd_flags, ++ uint16_t token) ++{ ++ uint64_t hdr; ++ ++ hdr = mc_enc(MC_CMD_HDR_CMDID_O, MC_CMD_HDR_CMDID_S, cmd_id); ++ hdr |= mc_enc(MC_CMD_HDR_FLAGS_O, MC_CMD_HDR_FLAGS_S, ++ (cmd_flags & MC_CMD_HDR_FLAGS_MASK)); ++ hdr |= mc_enc(MC_CMD_HDR_TOKEN_O, MC_CMD_HDR_TOKEN_S, token); ++ hdr |= mc_enc(MC_CMD_HDR_STATUS_O, MC_CMD_HDR_STATUS_S, ++ MC_CMD_STATUS_READY); ++ ++ return hdr; ++} ++ ++/** ++ * mc_write_command - writes a command to a Management Complex (MC) portal ++ * ++ * @portal: pointer to an MC portal ++ * @cmd: pointer to a filled command ++ */ ++static inline void mc_write_command(struct mc_command __iomem *portal, ++ struct mc_command *cmd) ++{ ++ int i; ++ uint32_t word; ++ ++ /* copy command parameters into the portal */ ++ for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++) ++ iowrite64(cmd->params[i], &portal->params[i]); ++ ++ /* submit the command by writing the header */ ++ word = (uint32_t)mc_dec(cmd->header, 32, 32); ++ iowrite32(word, (((uint32_t *)&portal->header) + 1)); ++ ++ word = (uint32_t)mc_dec(cmd->header, 0, 32); ++ iowrite32(word, (uint32_t *)&portal->header); ++} ++ ++/** ++ * mc_read_response - reads the response for the last MC command from a ++ * Management Complex (MC) portal ++ * ++ * @portal: pointer to an MC portal ++ * @resp: pointer to command response buffer ++ * ++ * Returns MC_CMD_STATUS_OK on Success; Error code otherwise. ++ */ ++static inline enum mc_cmd_status mc_read_response( ++ struct mc_command __iomem *portal, ++ struct mc_command *resp) ++{ ++ int i; ++ enum mc_cmd_status status; ++ ++ /* Copy command response header from MC portal: */ ++ resp->header = ioread64(&portal->header); ++ status = MC_CMD_HDR_READ_STATUS(resp->header); ++ if (status != MC_CMD_STATUS_OK) ++ return status; ++ ++ /* Copy command response data from MC portal: */ ++ for (i = 0; i < MC_CMD_NUM_OF_PARAMS; i++) ++ resp->params[i] = ioread64(&portal->params[i]); ++ ++ return status; ++} ++ ++#endif /* __FSL_MC_CMD_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_mc_sys.h b/drivers/net/dpaa2/mc/fsl_mc_sys.h +new file mode 100644 +index 0000000..b9f4244 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_mc_sys.h +@@ -0,0 +1,98 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_MC_SYS_H ++#define _FSL_MC_SYS_H ++ ++#ifdef __linux_driver__ ++ ++#include ++#include ++#include ++ ++struct fsl_mc_io { ++ void *regs; ++}; ++ ++#ifndef ENOTSUP ++#define ENOTSUP 95 ++#endif ++ ++#define ioread64(_p) readq(_p) ++#define iowrite64(_v, _p) writeq(_v, _p) ++ ++#else /* __linux_driver__ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define cpu_to_le64(x) __cpu_to_le64(x) ++#ifndef dmb ++#define dmb() do {\ ++ __asm__ __volatile__ ("" : : : "memory");\ ++} while (0) ++ ++#endif ++#define __iormb() dmb() ++#define __iowmb() dmb() ++#define __arch_getq(a) (*(volatile unsigned long *)(a)) ++#define __arch_putq(v, a) (*(volatile unsigned long *)(a) = (v)) ++#define __arch_putq32(v, a) (*(volatile unsigned int *)(a) = (v)) ++#define readq(c) ({ uint64_t __v = __arch_getq(c); __iormb(); __v; }) ++#define writeq(v, c) ({ uint64_t __v = v; __iowmb(); __arch_putq(__v, c); __v; }) ++#define writeq32(v, c) ({ uint32_t __v = v; __iowmb(); __arch_putq32(__v, c); __v; }) ++#define ioread64(_p) readq(_p) ++#define iowrite64(_v, _p) writeq(_v, _p) ++#define iowrite32(_v, _p) writeq32(_v, _p) ++#define __iomem ++ ++struct fsl_mc_io { ++ void *regs; ++}; ++ ++#ifndef ENOTSUP ++#define ENOTSUP 95 ++#endif ++ ++/*GPP is supposed to use MC commands with low priority*/ ++#define CMD_PRI_LOW 0 /*!< Low Priority command indication */ ++ ++struct mc_command; ++ ++int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd); ++ ++#endif /* __linux_driver__ */ ++ ++#endif /* _FSL_MC_SYS_H */ +diff --git a/drivers/net/dpaa2/mc/fsl_net.h b/drivers/net/dpaa2/mc/fsl_net.h +new file mode 100644 +index 0000000..43825b8 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/fsl_net.h +@@ -0,0 +1,480 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef __FSL_NET_H ++#define __FSL_NET_H ++ ++#define LAST_HDR_INDEX 0xFFFFFFFF ++ ++/*****************************************************************************/ ++/* Protocol fields */ ++/*****************************************************************************/ ++ ++/************************* Ethernet fields *********************************/ ++#define NH_FLD_ETH_DA (1) ++#define NH_FLD_ETH_SA (NH_FLD_ETH_DA << 1) ++#define NH_FLD_ETH_LENGTH (NH_FLD_ETH_DA << 2) ++#define NH_FLD_ETH_TYPE (NH_FLD_ETH_DA << 3) ++#define NH_FLD_ETH_FINAL_CKSUM (NH_FLD_ETH_DA << 4) ++#define NH_FLD_ETH_PADDING (NH_FLD_ETH_DA << 5) ++#define NH_FLD_ETH_ALL_FIELDS ((NH_FLD_ETH_DA << 6) - 1) ++ ++#define NH_FLD_ETH_ADDR_SIZE 6 ++ ++/*************************** VLAN fields ***********************************/ ++#define NH_FLD_VLAN_VPRI (1) ++#define NH_FLD_VLAN_CFI (NH_FLD_VLAN_VPRI << 1) ++#define NH_FLD_VLAN_VID (NH_FLD_VLAN_VPRI << 2) ++#define NH_FLD_VLAN_LENGTH (NH_FLD_VLAN_VPRI << 3) ++#define NH_FLD_VLAN_TYPE (NH_FLD_VLAN_VPRI << 4) ++#define NH_FLD_VLAN_ALL_FIELDS ((NH_FLD_VLAN_VPRI << 5) - 1) ++ ++#define NH_FLD_VLAN_TCI (NH_FLD_VLAN_VPRI | \ ++ NH_FLD_VLAN_CFI | \ ++ NH_FLD_VLAN_VID) ++ ++/************************ IP (generic) fields ******************************/ ++#define NH_FLD_IP_VER (1) ++#define NH_FLD_IP_DSCP (NH_FLD_IP_VER << 2) ++#define NH_FLD_IP_ECN (NH_FLD_IP_VER << 3) ++#define NH_FLD_IP_PROTO (NH_FLD_IP_VER << 4) ++#define NH_FLD_IP_SRC (NH_FLD_IP_VER << 5) ++#define NH_FLD_IP_DST (NH_FLD_IP_VER << 6) ++#define NH_FLD_IP_TOS_TC (NH_FLD_IP_VER << 7) ++#define NH_FLD_IP_ID (NH_FLD_IP_VER << 8) ++#define NH_FLD_IP_ALL_FIELDS ((NH_FLD_IP_VER << 9) - 1) ++ ++#define NH_FLD_IP_PROTO_SIZE 1 ++ ++/***************************** IPV4 fields *********************************/ ++#define NH_FLD_IPV4_VER (1) ++#define NH_FLD_IPV4_HDR_LEN (NH_FLD_IPV4_VER << 1) ++#define NH_FLD_IPV4_TOS (NH_FLD_IPV4_VER << 2) ++#define NH_FLD_IPV4_TOTAL_LEN (NH_FLD_IPV4_VER << 3) ++#define NH_FLD_IPV4_ID (NH_FLD_IPV4_VER << 4) ++#define NH_FLD_IPV4_FLAG_D (NH_FLD_IPV4_VER << 5) ++#define NH_FLD_IPV4_FLAG_M (NH_FLD_IPV4_VER << 6) ++#define NH_FLD_IPV4_OFFSET (NH_FLD_IPV4_VER << 7) ++#define NH_FLD_IPV4_TTL (NH_FLD_IPV4_VER << 8) ++#define NH_FLD_IPV4_PROTO (NH_FLD_IPV4_VER << 9) ++#define NH_FLD_IPV4_CKSUM (NH_FLD_IPV4_VER << 10) ++#define NH_FLD_IPV4_SRC_IP (NH_FLD_IPV4_VER << 11) ++#define NH_FLD_IPV4_DST_IP (NH_FLD_IPV4_VER << 12) ++#define NH_FLD_IPV4_OPTS (NH_FLD_IPV4_VER << 13) ++#define NH_FLD_IPV4_OPTS_COUNT (NH_FLD_IPV4_VER << 14) ++#define NH_FLD_IPV4_ALL_FIELDS ((NH_FLD_IPV4_VER << 15) - 1) ++ ++#define NH_FLD_IPV4_ADDR_SIZE 4 ++#define NH_FLD_IPV4_PROTO_SIZE 1 ++ ++/***************************** IPV6 fields *********************************/ ++#define NH_FLD_IPV6_VER (1) ++#define NH_FLD_IPV6_TC (NH_FLD_IPV6_VER << 1) ++#define NH_FLD_IPV6_SRC_IP (NH_FLD_IPV6_VER << 2) ++#define NH_FLD_IPV6_DST_IP (NH_FLD_IPV6_VER << 3) ++#define NH_FLD_IPV6_NEXT_HDR (NH_FLD_IPV6_VER << 4) ++#define NH_FLD_IPV6_FL (NH_FLD_IPV6_VER << 5) ++#define NH_FLD_IPV6_HOP_LIMIT (NH_FLD_IPV6_VER << 6) ++#define NH_FLD_IPV6_ID (NH_FLD_IPV6_VER << 7) ++#define NH_FLD_IPV6_ALL_FIELDS ((NH_FLD_IPV6_VER << 8) - 1) ++ ++#define NH_FLD_IPV6_ADDR_SIZE 16 ++#define NH_FLD_IPV6_NEXT_HDR_SIZE 1 ++ ++/***************************** ICMP fields *********************************/ ++#define NH_FLD_ICMP_TYPE (1) ++#define NH_FLD_ICMP_CODE (NH_FLD_ICMP_TYPE << 1) ++#define NH_FLD_ICMP_CKSUM (NH_FLD_ICMP_TYPE << 2) ++#define NH_FLD_ICMP_ID (NH_FLD_ICMP_TYPE << 3) ++#define NH_FLD_ICMP_SQ_NUM (NH_FLD_ICMP_TYPE << 4) ++#define NH_FLD_ICMP_ALL_FIELDS ((NH_FLD_ICMP_TYPE << 5) - 1) ++ ++#define NH_FLD_ICMP_CODE_SIZE 1 ++#define NH_FLD_ICMP_TYPE_SIZE 1 ++ ++/***************************** IGMP fields *********************************/ ++#define NH_FLD_IGMP_VERSION (1) ++#define NH_FLD_IGMP_TYPE (NH_FLD_IGMP_VERSION << 1) ++#define NH_FLD_IGMP_CKSUM (NH_FLD_IGMP_VERSION << 2) ++#define NH_FLD_IGMP_DATA (NH_FLD_IGMP_VERSION << 3) ++#define NH_FLD_IGMP_ALL_FIELDS ((NH_FLD_IGMP_VERSION << 4) - 1) ++ ++/***************************** TCP fields **********************************/ ++#define NH_FLD_TCP_PORT_SRC (1) ++#define NH_FLD_TCP_PORT_DST (NH_FLD_TCP_PORT_SRC << 1) ++#define NH_FLD_TCP_SEQ (NH_FLD_TCP_PORT_SRC << 2) ++#define NH_FLD_TCP_ACK (NH_FLD_TCP_PORT_SRC << 3) ++#define NH_FLD_TCP_OFFSET (NH_FLD_TCP_PORT_SRC << 4) ++#define NH_FLD_TCP_FLAGS (NH_FLD_TCP_PORT_SRC << 5) ++#define NH_FLD_TCP_WINDOW (NH_FLD_TCP_PORT_SRC << 6) ++#define NH_FLD_TCP_CKSUM (NH_FLD_TCP_PORT_SRC << 7) ++#define NH_FLD_TCP_URGPTR (NH_FLD_TCP_PORT_SRC << 8) ++#define NH_FLD_TCP_OPTS (NH_FLD_TCP_PORT_SRC << 9) ++#define NH_FLD_TCP_OPTS_COUNT (NH_FLD_TCP_PORT_SRC << 10) ++#define NH_FLD_TCP_ALL_FIELDS ((NH_FLD_TCP_PORT_SRC << 11) - 1) ++ ++#define NH_FLD_TCP_PORT_SIZE 2 ++ ++/***************************** UDP fields **********************************/ ++#define NH_FLD_UDP_PORT_SRC (1) ++#define NH_FLD_UDP_PORT_DST (NH_FLD_UDP_PORT_SRC << 1) ++#define NH_FLD_UDP_LEN (NH_FLD_UDP_PORT_SRC << 2) ++#define NH_FLD_UDP_CKSUM (NH_FLD_UDP_PORT_SRC << 3) ++#define NH_FLD_UDP_ALL_FIELDS ((NH_FLD_UDP_PORT_SRC << 4) - 1) ++ ++#define NH_FLD_UDP_PORT_SIZE 2 ++ ++/*************************** UDP-lite fields *******************************/ ++#define NH_FLD_UDP_LITE_PORT_SRC (1) ++#define NH_FLD_UDP_LITE_PORT_DST (NH_FLD_UDP_LITE_PORT_SRC << 1) ++#define NH_FLD_UDP_LITE_ALL_FIELDS \ ++ ((NH_FLD_UDP_LITE_PORT_SRC << 2) - 1) ++ ++#define NH_FLD_UDP_LITE_PORT_SIZE 2 ++ ++/*************************** UDP-encap-ESP fields **************************/ ++#define NH_FLD_UDP_ENC_ESP_PORT_SRC (1) ++#define NH_FLD_UDP_ENC_ESP_PORT_DST (NH_FLD_UDP_ENC_ESP_PORT_SRC << 1) ++#define NH_FLD_UDP_ENC_ESP_LEN (NH_FLD_UDP_ENC_ESP_PORT_SRC << 2) ++#define NH_FLD_UDP_ENC_ESP_CKSUM (NH_FLD_UDP_ENC_ESP_PORT_SRC << 3) ++#define NH_FLD_UDP_ENC_ESP_SPI (NH_FLD_UDP_ENC_ESP_PORT_SRC << 4) ++#define NH_FLD_UDP_ENC_ESP_SEQUENCE_NUM (NH_FLD_UDP_ENC_ESP_PORT_SRC << 5) ++#define NH_FLD_UDP_ENC_ESP_ALL_FIELDS \ ++ ((NH_FLD_UDP_ENC_ESP_PORT_SRC << 6) - 1) ++ ++#define NH_FLD_UDP_ENC_ESP_PORT_SIZE 2 ++#define NH_FLD_UDP_ENC_ESP_SPI_SIZE 4 ++ ++/***************************** SCTP fields *********************************/ ++#define NH_FLD_SCTP_PORT_SRC (1) ++#define NH_FLD_SCTP_PORT_DST (NH_FLD_SCTP_PORT_SRC << 1) ++#define NH_FLD_SCTP_VER_TAG (NH_FLD_SCTP_PORT_SRC << 2) ++#define NH_FLD_SCTP_CKSUM (NH_FLD_SCTP_PORT_SRC << 3) ++#define NH_FLD_SCTP_ALL_FIELDS ((NH_FLD_SCTP_PORT_SRC << 4) - 1) ++ ++#define NH_FLD_SCTP_PORT_SIZE 2 ++ ++/***************************** DCCP fields *********************************/ ++#define NH_FLD_DCCP_PORT_SRC (1) ++#define NH_FLD_DCCP_PORT_DST (NH_FLD_DCCP_PORT_SRC << 1) ++#define NH_FLD_DCCP_ALL_FIELDS ((NH_FLD_DCCP_PORT_SRC << 2) - 1) ++ ++#define NH_FLD_DCCP_PORT_SIZE 2 ++ ++/***************************** IPHC fields *********************************/ ++#define NH_FLD_IPHC_CID (1) ++#define NH_FLD_IPHC_CID_TYPE (NH_FLD_IPHC_CID << 1) ++#define NH_FLD_IPHC_HCINDEX (NH_FLD_IPHC_CID << 2) ++#define NH_FLD_IPHC_GEN (NH_FLD_IPHC_CID << 3) ++#define NH_FLD_IPHC_D_BIT (NH_FLD_IPHC_CID << 4) ++#define NH_FLD_IPHC_ALL_FIELDS ((NH_FLD_IPHC_CID << 5) - 1) ++ ++/***************************** SCTP fields *********************************/ ++#define NH_FLD_SCTP_CHUNK_DATA_TYPE (1) ++#define NH_FLD_SCTP_CHUNK_DATA_FLAGS (NH_FLD_SCTP_CHUNK_DATA_TYPE << 1) ++#define NH_FLD_SCTP_CHUNK_DATA_LENGTH (NH_FLD_SCTP_CHUNK_DATA_TYPE << 2) ++#define NH_FLD_SCTP_CHUNK_DATA_TSN (NH_FLD_SCTP_CHUNK_DATA_TYPE << 3) ++#define NH_FLD_SCTP_CHUNK_DATA_STREAM_ID (NH_FLD_SCTP_CHUNK_DATA_TYPE << 4) ++#define NH_FLD_SCTP_CHUNK_DATA_STREAM_SQN (NH_FLD_SCTP_CHUNK_DATA_TYPE << 5) ++#define NH_FLD_SCTP_CHUNK_DATA_PAYLOAD_PID (NH_FLD_SCTP_CHUNK_DATA_TYPE << 6) ++#define NH_FLD_SCTP_CHUNK_DATA_UNORDERED (NH_FLD_SCTP_CHUNK_DATA_TYPE << 7) ++#define NH_FLD_SCTP_CHUNK_DATA_BEGGINING (NH_FLD_SCTP_CHUNK_DATA_TYPE << 8) ++#define NH_FLD_SCTP_CHUNK_DATA_END (NH_FLD_SCTP_CHUNK_DATA_TYPE << 9) ++#define NH_FLD_SCTP_CHUNK_DATA_ALL_FIELDS \ ++ ((NH_FLD_SCTP_CHUNK_DATA_TYPE << 10) - 1) ++ ++/*************************** L2TPV2 fields *********************************/ ++#define NH_FLD_L2TPV2_TYPE_BIT (1) ++#define NH_FLD_L2TPV2_LENGTH_BIT (NH_FLD_L2TPV2_TYPE_BIT << 1) ++#define NH_FLD_L2TPV2_SEQUENCE_BIT (NH_FLD_L2TPV2_TYPE_BIT << 2) ++#define NH_FLD_L2TPV2_OFFSET_BIT (NH_FLD_L2TPV2_TYPE_BIT << 3) ++#define NH_FLD_L2TPV2_PRIORITY_BIT (NH_FLD_L2TPV2_TYPE_BIT << 4) ++#define NH_FLD_L2TPV2_VERSION (NH_FLD_L2TPV2_TYPE_BIT << 5) ++#define NH_FLD_L2TPV2_LEN (NH_FLD_L2TPV2_TYPE_BIT << 6) ++#define NH_FLD_L2TPV2_TUNNEL_ID (NH_FLD_L2TPV2_TYPE_BIT << 7) ++#define NH_FLD_L2TPV2_SESSION_ID (NH_FLD_L2TPV2_TYPE_BIT << 8) ++#define NH_FLD_L2TPV2_NS (NH_FLD_L2TPV2_TYPE_BIT << 9) ++#define NH_FLD_L2TPV2_NR (NH_FLD_L2TPV2_TYPE_BIT << 10) ++#define NH_FLD_L2TPV2_OFFSET_SIZE (NH_FLD_L2TPV2_TYPE_BIT << 11) ++#define NH_FLD_L2TPV2_FIRST_BYTE (NH_FLD_L2TPV2_TYPE_BIT << 12) ++#define NH_FLD_L2TPV2_ALL_FIELDS \ ++ ((NH_FLD_L2TPV2_TYPE_BIT << 13) - 1) ++ ++/*************************** L2TPV3 fields *********************************/ ++#define NH_FLD_L2TPV3_CTRL_TYPE_BIT (1) ++#define NH_FLD_L2TPV3_CTRL_LENGTH_BIT (NH_FLD_L2TPV3_CTRL_TYPE_BIT << 1) ++#define NH_FLD_L2TPV3_CTRL_SEQUENCE_BIT (NH_FLD_L2TPV3_CTRL_TYPE_BIT << 2) ++#define NH_FLD_L2TPV3_CTRL_VERSION (NH_FLD_L2TPV3_CTRL_TYPE_BIT << 3) ++#define NH_FLD_L2TPV3_CTRL_LENGTH (NH_FLD_L2TPV3_CTRL_TYPE_BIT << 4) ++#define NH_FLD_L2TPV3_CTRL_CONTROL (NH_FLD_L2TPV3_CTRL_TYPE_BIT << 5) ++#define NH_FLD_L2TPV3_CTRL_SENT (NH_FLD_L2TPV3_CTRL_TYPE_BIT << 6) ++#define NH_FLD_L2TPV3_CTRL_RECV (NH_FLD_L2TPV3_CTRL_TYPE_BIT << 7) ++#define NH_FLD_L2TPV3_CTRL_FIRST_BYTE (NH_FLD_L2TPV3_CTRL_TYPE_BIT << 8) ++#define NH_FLD_L2TPV3_CTRL_ALL_FIELDS \ ++ ((NH_FLD_L2TPV3_CTRL_TYPE_BIT << 9) - 1) ++ ++#define NH_FLD_L2TPV3_SESS_TYPE_BIT (1) ++#define NH_FLD_L2TPV3_SESS_VERSION (NH_FLD_L2TPV3_SESS_TYPE_BIT << 1) ++#define NH_FLD_L2TPV3_SESS_ID (NH_FLD_L2TPV3_SESS_TYPE_BIT << 2) ++#define NH_FLD_L2TPV3_SESS_COOKIE (NH_FLD_L2TPV3_SESS_TYPE_BIT << 3) ++#define NH_FLD_L2TPV3_SESS_ALL_FIELDS \ ++ ((NH_FLD_L2TPV3_SESS_TYPE_BIT << 4) - 1) ++ ++/**************************** PPP fields ***********************************/ ++#define NH_FLD_PPP_PID (1) ++#define NH_FLD_PPP_COMPRESSED (NH_FLD_PPP_PID << 1) ++#define NH_FLD_PPP_ALL_FIELDS ((NH_FLD_PPP_PID << 2) - 1) ++ ++/************************** PPPoE fields ***********************************/ ++#define NH_FLD_PPPOE_VER (1) ++#define NH_FLD_PPPOE_TYPE (NH_FLD_PPPOE_VER << 1) ++#define NH_FLD_PPPOE_CODE (NH_FLD_PPPOE_VER << 2) ++#define NH_FLD_PPPOE_SID (NH_FLD_PPPOE_VER << 3) ++#define NH_FLD_PPPOE_LEN (NH_FLD_PPPOE_VER << 4) ++#define NH_FLD_PPPOE_SESSION (NH_FLD_PPPOE_VER << 5) ++#define NH_FLD_PPPOE_PID (NH_FLD_PPPOE_VER << 6) ++#define NH_FLD_PPPOE_ALL_FIELDS ((NH_FLD_PPPOE_VER << 7) - 1) ++ ++/************************* PPP-Mux fields **********************************/ ++#define NH_FLD_PPPMUX_PID (1) ++#define NH_FLD_PPPMUX_CKSUM (NH_FLD_PPPMUX_PID << 1) ++#define NH_FLD_PPPMUX_COMPRESSED (NH_FLD_PPPMUX_PID << 2) ++#define NH_FLD_PPPMUX_ALL_FIELDS ((NH_FLD_PPPMUX_PID << 3) - 1) ++ ++/*********************** PPP-Mux sub-frame fields **************************/ ++#define NH_FLD_PPPMUX_SUBFRM_PFF (1) ++#define NH_FLD_PPPMUX_SUBFRM_LXT (NH_FLD_PPPMUX_SUBFRM_PFF << 1) ++#define NH_FLD_PPPMUX_SUBFRM_LEN (NH_FLD_PPPMUX_SUBFRM_PFF << 2) ++#define NH_FLD_PPPMUX_SUBFRM_PID (NH_FLD_PPPMUX_SUBFRM_PFF << 3) ++#define NH_FLD_PPPMUX_SUBFRM_USE_PID (NH_FLD_PPPMUX_SUBFRM_PFF << 4) ++#define NH_FLD_PPPMUX_SUBFRM_ALL_FIELDS \ ++ ((NH_FLD_PPPMUX_SUBFRM_PFF << 5) - 1) ++ ++/*************************** LLC fields ************************************/ ++#define NH_FLD_LLC_DSAP (1) ++#define NH_FLD_LLC_SSAP (NH_FLD_LLC_DSAP << 1) ++#define NH_FLD_LLC_CTRL (NH_FLD_LLC_DSAP << 2) ++#define NH_FLD_LLC_ALL_FIELDS ((NH_FLD_LLC_DSAP << 3) - 1) ++ ++/*************************** NLPID fields **********************************/ ++#define NH_FLD_NLPID_NLPID (1) ++#define NH_FLD_NLPID_ALL_FIELDS ((NH_FLD_NLPID_NLPID << 1) - 1) ++ ++/*************************** SNAP fields ***********************************/ ++#define NH_FLD_SNAP_OUI (1) ++#define NH_FLD_SNAP_PID (NH_FLD_SNAP_OUI << 1) ++#define NH_FLD_SNAP_ALL_FIELDS ((NH_FLD_SNAP_OUI << 2) - 1) ++ ++/*************************** LLC SNAP fields *******************************/ ++#define NH_FLD_LLC_SNAP_TYPE (1) ++#define NH_FLD_LLC_SNAP_ALL_FIELDS ((NH_FLD_LLC_SNAP_TYPE << 1) - 1) ++ ++#define NH_FLD_ARP_HTYPE (1) ++#define NH_FLD_ARP_PTYPE (NH_FLD_ARP_HTYPE << 1) ++#define NH_FLD_ARP_HLEN (NH_FLD_ARP_HTYPE << 2) ++#define NH_FLD_ARP_PLEN (NH_FLD_ARP_HTYPE << 3) ++#define NH_FLD_ARP_OPER (NH_FLD_ARP_HTYPE << 4) ++#define NH_FLD_ARP_SHA (NH_FLD_ARP_HTYPE << 5) ++#define NH_FLD_ARP_SPA (NH_FLD_ARP_HTYPE << 6) ++#define NH_FLD_ARP_THA (NH_FLD_ARP_HTYPE << 7) ++#define NH_FLD_ARP_TPA (NH_FLD_ARP_HTYPE << 8) ++#define NH_FLD_ARP_ALL_FIELDS ((NH_FLD_ARP_HTYPE << 9) - 1) ++ ++/*************************** RFC2684 fields ********************************/ ++#define NH_FLD_RFC2684_LLC (1) ++#define NH_FLD_RFC2684_NLPID (NH_FLD_RFC2684_LLC << 1) ++#define NH_FLD_RFC2684_OUI (NH_FLD_RFC2684_LLC << 2) ++#define NH_FLD_RFC2684_PID (NH_FLD_RFC2684_LLC << 3) ++#define NH_FLD_RFC2684_VPN_OUI (NH_FLD_RFC2684_LLC << 4) ++#define NH_FLD_RFC2684_VPN_IDX (NH_FLD_RFC2684_LLC << 5) ++#define NH_FLD_RFC2684_ALL_FIELDS ((NH_FLD_RFC2684_LLC << 6) - 1) ++ ++/*************************** User defined fields ***************************/ ++#define NH_FLD_USER_DEFINED_SRCPORT (1) ++#define NH_FLD_USER_DEFINED_PCDID (NH_FLD_USER_DEFINED_SRCPORT << 1) ++#define NH_FLD_USER_DEFINED_ALL_FIELDS \ ++ ((NH_FLD_USER_DEFINED_SRCPORT << 2) - 1) ++ ++/*************************** Payload fields ********************************/ ++#define NH_FLD_PAYLOAD_BUFFER (1) ++#define NH_FLD_PAYLOAD_SIZE (NH_FLD_PAYLOAD_BUFFER << 1) ++#define NH_FLD_MAX_FRM_SIZE (NH_FLD_PAYLOAD_BUFFER << 2) ++#define NH_FLD_MIN_FRM_SIZE (NH_FLD_PAYLOAD_BUFFER << 3) ++#define NH_FLD_PAYLOAD_TYPE (NH_FLD_PAYLOAD_BUFFER << 4) ++#define NH_FLD_FRAME_SIZE (NH_FLD_PAYLOAD_BUFFER << 5) ++#define NH_FLD_PAYLOAD_ALL_FIELDS ((NH_FLD_PAYLOAD_BUFFER << 6) - 1) ++ ++/*************************** GRE fields ************************************/ ++#define NH_FLD_GRE_TYPE (1) ++#define NH_FLD_GRE_ALL_FIELDS ((NH_FLD_GRE_TYPE << 1) - 1) ++ ++/*************************** MINENCAP fields *******************************/ ++#define NH_FLD_MINENCAP_SRC_IP (1) ++#define NH_FLD_MINENCAP_DST_IP (NH_FLD_MINENCAP_SRC_IP << 1) ++#define NH_FLD_MINENCAP_TYPE (NH_FLD_MINENCAP_SRC_IP << 2) ++#define NH_FLD_MINENCAP_ALL_FIELDS \ ++ ((NH_FLD_MINENCAP_SRC_IP << 3) - 1) ++ ++/*************************** IPSEC AH fields *******************************/ ++#define NH_FLD_IPSEC_AH_SPI (1) ++#define NH_FLD_IPSEC_AH_NH (NH_FLD_IPSEC_AH_SPI << 1) ++#define NH_FLD_IPSEC_AH_ALL_FIELDS ((NH_FLD_IPSEC_AH_SPI << 2) - 1) ++ ++/*************************** IPSEC ESP fields ******************************/ ++#define NH_FLD_IPSEC_ESP_SPI (1) ++#define NH_FLD_IPSEC_ESP_SEQUENCE_NUM (NH_FLD_IPSEC_ESP_SPI << 1) ++#define NH_FLD_IPSEC_ESP_ALL_FIELDS ((NH_FLD_IPSEC_ESP_SPI << 2) - 1) ++ ++#define NH_FLD_IPSEC_ESP_SPI_SIZE 4 ++ ++/*************************** MPLS fields ***********************************/ ++#define NH_FLD_MPLS_LABEL_STACK (1) ++#define NH_FLD_MPLS_LABEL_STACK_ALL_FIELDS \ ++ ((NH_FLD_MPLS_LABEL_STACK << 1) - 1) ++ ++/*************************** MACSEC fields *********************************/ ++#define NH_FLD_MACSEC_SECTAG (1) ++#define NH_FLD_MACSEC_ALL_FIELDS ((NH_FLD_MACSEC_SECTAG << 1) - 1) ++ ++/*************************** GTP fields ************************************/ ++#define NH_FLD_GTP_TEID (1) ++ ++/* Protocol options */ ++ ++/* Ethernet options */ ++#define NH_OPT_ETH_BROADCAST 1 ++#define NH_OPT_ETH_MULTICAST 2 ++#define NH_OPT_ETH_UNICAST 3 ++#define NH_OPT_ETH_BPDU 4 ++ ++#define NH_ETH_IS_MULTICAST_ADDR(addr) (addr[0] & 0x01) ++/* also applicable for broadcast */ ++ ++/* VLAN options */ ++#define NH_OPT_VLAN_CFI 1 ++ ++/* IPV4 options */ ++#define NH_OPT_IPV4_UNICAST 1 ++#define NH_OPT_IPV4_MULTICAST 2 ++#define NH_OPT_IPV4_BROADCAST 3 ++#define NH_OPT_IPV4_OPTION 4 ++#define NH_OPT_IPV4_FRAG 5 ++#define NH_OPT_IPV4_INITIAL_FRAG 6 ++ ++/* IPV6 options */ ++#define NH_OPT_IPV6_UNICAST 1 ++#define NH_OPT_IPV6_MULTICAST 2 ++#define NH_OPT_IPV6_OPTION 3 ++#define NH_OPT_IPV6_FRAG 4 ++#define NH_OPT_IPV6_INITIAL_FRAG 5 ++ ++/* General IP options (may be used for any version) */ ++#define NH_OPT_IP_FRAG 1 ++#define NH_OPT_IP_INITIAL_FRAG 2 ++#define NH_OPT_IP_OPTION 3 ++ ++/* Minenc. options */ ++#define NH_OPT_MINENCAP_SRC_ADDR_PRESENT 1 ++ ++/* GRE. options */ ++#define NH_OPT_GRE_ROUTING_PRESENT 1 ++ ++/* TCP options */ ++#define NH_OPT_TCP_OPTIONS 1 ++#define NH_OPT_TCP_CONTROL_HIGH_BITS 2 ++#define NH_OPT_TCP_CONTROL_LOW_BITS 3 ++ ++/* CAPWAP options */ ++#define NH_OPT_CAPWAP_DTLS 1 ++ ++enum net_prot { ++ NET_PROT_NONE = 0, ++ NET_PROT_PAYLOAD, ++ NET_PROT_ETH, ++ NET_PROT_VLAN, ++ NET_PROT_IPV4, ++ NET_PROT_IPV6, ++ NET_PROT_IP, ++ NET_PROT_TCP, ++ NET_PROT_UDP, ++ NET_PROT_UDP_LITE, ++ NET_PROT_IPHC, ++ NET_PROT_SCTP, ++ NET_PROT_SCTP_CHUNK_DATA, ++ NET_PROT_PPPOE, ++ NET_PROT_PPP, ++ NET_PROT_PPPMUX, ++ NET_PROT_PPPMUX_SUBFRM, ++ NET_PROT_L2TPV2, ++ NET_PROT_L2TPV3_CTRL, ++ NET_PROT_L2TPV3_SESS, ++ NET_PROT_LLC, ++ NET_PROT_LLC_SNAP, ++ NET_PROT_NLPID, ++ NET_PROT_SNAP, ++ NET_PROT_MPLS, ++ NET_PROT_IPSEC_AH, ++ NET_PROT_IPSEC_ESP, ++ NET_PROT_UDP_ENC_ESP, /* RFC 3948 */ ++ NET_PROT_MACSEC, ++ NET_PROT_GRE, ++ NET_PROT_MINENCAP, ++ NET_PROT_DCCP, ++ NET_PROT_ICMP, ++ NET_PROT_IGMP, ++ NET_PROT_ARP, ++ NET_PROT_CAPWAP_DATA, ++ NET_PROT_CAPWAP_CTRL, ++ NET_PROT_RFC2684, ++ NET_PROT_ICMPV6, ++ NET_PROT_FCOE, ++ NET_PROT_FIP, ++ NET_PROT_ISCSI, ++ NET_PROT_GTP, ++ NET_PROT_USER_DEFINED_L2, ++ NET_PROT_USER_DEFINED_L3, ++ NET_PROT_USER_DEFINED_L4, ++ NET_PROT_USER_DEFINED_L5, ++ NET_PROT_USER_DEFINED_SHIM1, ++ NET_PROT_USER_DEFINED_SHIM2, ++ ++ NET_PROT_DUMMY_LAST ++}; ++ ++/*! IEEE8021.Q */ ++#define NH_IEEE8021Q_ETYPE 0x8100 ++#define NH_IEEE8021Q_HDR(etype, pcp, dei, vlan_id) \ ++ ((((uint32_t)(etype & 0xFFFF)) << 16) | \ ++ (((uint32_t)(pcp & 0x07)) << 13) | \ ++ (((uint32_t)(dei & 0x01)) << 12) | \ ++ (((uint32_t)(vlan_id & 0xFFF)))) ++ ++#endif /* __FSL_NET_H */ +diff --git a/drivers/net/dpaa2/mc/mc_sys.c b/drivers/net/dpaa2/mc/mc_sys.c +new file mode 100644 +index 0000000..fcbed28 +--- /dev/null ++++ b/drivers/net/dpaa2/mc/mc_sys.c +@@ -0,0 +1,127 @@ ++/* Copyright 2013-2015 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of the above-listed copyright holders nor the ++ * names of any contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE ++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++ * POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++ ++/* ODP framework using MC poratl in shared mode. Following ++ changes to introduce Locks must be maintained while ++ merging the FLIB. ++*/ ++ ++/** ++* The mc_spinlock_t type. ++*/ ++typedef struct { ++ volatile int locked; /**< lock status 0 = unlocked, 1 = locked */ ++} mc_spinlock_t; ++ ++/** ++* A static spinlock initializer. ++*/ ++static mc_spinlock_t mc_portal_lock = { 0 }; ++ ++static inline void mc_pause(void) {} ++ ++static inline void mc_spinlock_lock(mc_spinlock_t *sl) ++{ ++ while (__sync_lock_test_and_set(&sl->locked, 1)) ++ while (sl->locked) ++ mc_pause(); ++} ++ ++static inline void mc_spinlock_unlock(mc_spinlock_t *sl) ++{ ++ __sync_lock_release(&sl->locked); ++} ++ ++static int mc_status_to_error(enum mc_cmd_status status) ++{ ++ switch (status) { ++ case MC_CMD_STATUS_OK: ++ return 0; ++ case MC_CMD_STATUS_AUTH_ERR: ++ return -EACCES; /* Token error */ ++ case MC_CMD_STATUS_NO_PRIVILEGE: ++ return -EPERM; /* Permission denied */ ++ case MC_CMD_STATUS_DMA_ERR: ++ return -EIO; /* Input/Output error */ ++ case MC_CMD_STATUS_CONFIG_ERR: ++ return -EINVAL; /* Device not configured */ ++ case MC_CMD_STATUS_TIMEOUT: ++ return -ETIMEDOUT; /* Operation timed out */ ++ case MC_CMD_STATUS_NO_RESOURCE: ++ return -ENAVAIL; /* Resource temporarily unavailable */ ++ case MC_CMD_STATUS_NO_MEMORY: ++ return -ENOMEM; /* Cannot allocate memory */ ++ case MC_CMD_STATUS_BUSY: ++ return -EBUSY; /* Device busy */ ++ case MC_CMD_STATUS_UNSUPPORTED_OP: ++ return -ENOTSUP; /* Operation not supported by device */ ++ case MC_CMD_STATUS_INVALID_STATE: ++ return -ENODEV; /* Invalid device state */ ++ default: ++ break; ++ } ++ ++ /* Not expected to reach here */ ++ return -EINVAL; ++} ++ ++int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd) ++{ ++ enum mc_cmd_status status; ++ ++ if (!mc_io || !mc_io->regs) ++ return -EACCES; ++ ++ /* --- Call lock function here in case portal is shared --- */ ++ mc_spinlock_lock(&mc_portal_lock); ++ ++ mc_write_command(mc_io->regs, cmd); ++ ++ /* Spin until status changes */ ++ do { ++ status = MC_CMD_HDR_READ_STATUS(ioread64(mc_io->regs)); ++ ++ /* --- Call wait function here to prevent blocking --- ++ * Change the loop condition accordingly to exit on timeout. ++ */ ++ } while (status == MC_CMD_STATUS_READY); ++ ++ /* Read the response back into the command buffer */ ++ mc_read_response(mc_io->regs, cmd); ++ ++ /* --- Call unlock function here in case portal is shared --- */ ++ mc_spinlock_unlock(&mc_portal_lock); ++ ++ return mc_status_to_error(status); ++} +diff --git a/drivers/net/dpaa2/qbman/driver/qbman_debug.c b/drivers/net/dpaa2/qbman/driver/qbman_debug.c +new file mode 100644 +index 0000000..ef6c257 +--- /dev/null ++++ b/drivers/net/dpaa2/qbman/driver/qbman_debug.c +@@ -0,0 +1,929 @@ ++/* Copyright (C) 2015 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY ++ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include "qbman_portal.h" ++#include "qbman_debug.h" ++#include ++ ++/* QBMan portal management command code */ ++#define QBMAN_BP_QUERY 0x32 ++#define QBMAN_FQ_QUERY 0x44 ++#define QBMAN_FQ_QUERY_NP 0x45 ++#define QBMAN_WQ_QUERY 0x47 ++#define QBMAN_CGR_QUERY 0x51 ++#define QBMAN_WRED_QUERY 0x54 ++#define QBMAN_CGR_STAT_QUERY 0x55 ++#define QBMAN_CGR_STAT_QUERY_CLR 0x56 ++ ++enum qbman_attr_usage_e { ++ qbman_attr_usage_fq, ++ qbman_attr_usage_bpool, ++ qbman_attr_usage_cgr, ++ qbman_attr_usage_wqchan ++}; ++ ++struct int_qbman_attr { ++ uint32_t words[32]; ++ enum qbman_attr_usage_e usage; ++}; ++ ++#define attr_type_set(a, e) \ ++{ \ ++ struct qbman_attr *__attr = a; \ ++ enum qbman_attr_usage_e __usage = e; \ ++ ((struct int_qbman_attr *)__attr)->usage = __usage; \ ++} ++ ++#define ATTR32(d) (&(d)->dont_manipulate_directly[0]) ++#define ATTR32_1(d) (&(d)->dont_manipulate_directly[16]) ++ ++static struct qb_attr_code code_bp_bpid = QB_CODE(0, 16, 16); ++static struct qb_attr_code code_bp_bdi = QB_CODE(1, 16, 1); ++static struct qb_attr_code code_bp_va = QB_CODE(1, 17, 1); ++static struct qb_attr_code code_bp_wae = QB_CODE(1, 18, 1); ++static struct qb_attr_code code_bp_swdet = QB_CODE(4, 0, 16); ++static struct qb_attr_code code_bp_swdxt = QB_CODE(4, 16, 16); ++static struct qb_attr_code code_bp_hwdet = QB_CODE(5, 0, 16); ++static struct qb_attr_code code_bp_hwdxt = QB_CODE(5, 16, 16); ++static struct qb_attr_code code_bp_swset = QB_CODE(6, 0, 16); ++static struct qb_attr_code code_bp_swsxt = QB_CODE(6, 16, 16); ++static struct qb_attr_code code_bp_vbpid = QB_CODE(7, 0, 14); ++static struct qb_attr_code code_bp_icid = QB_CODE(7, 16, 15); ++static struct qb_attr_code code_bp_pl = QB_CODE(7, 31, 1); ++static struct qb_attr_code code_bp_bpscn_addr_lo = QB_CODE(8, 0, 32); ++static struct qb_attr_code code_bp_bpscn_addr_hi = QB_CODE(9, 0, 32); ++static struct qb_attr_code code_bp_bpscn_ctx_lo = QB_CODE(10, 0, 32); ++static struct qb_attr_code code_bp_bpscn_ctx_hi = QB_CODE(11, 0, 32); ++static struct qb_attr_code code_bp_hw_targ = QB_CODE(12, 0, 16); ++static struct qb_attr_code code_bp_state = QB_CODE(1, 24, 3); ++static struct qb_attr_code code_bp_fill = QB_CODE(2, 0, 32); ++static struct qb_attr_code code_bp_hdptr = QB_CODE(3, 0, 32); ++static struct qb_attr_code code_bp_sdcnt = QB_CODE(13, 0, 8); ++static struct qb_attr_code code_bp_hdcnt = QB_CODE(13, 8, 8); ++static struct qb_attr_code code_bp_sscnt = QB_CODE(13, 16, 8); ++ ++static void qbman_bp_attr_clear(struct qbman_attr *a) ++{ ++ memset(a, 0, sizeof(*a)); ++ attr_type_set(a, qbman_attr_usage_bpool); ++} ++ ++int qbman_bp_query(struct qbman_swp *s, uint32_t bpid, ++ struct qbman_attr *a) ++{ ++ uint32_t *p; ++ uint32_t rslt; ++ uint32_t *attr = ATTR32(a); ++ ++ qbman_bp_attr_clear(a); ++ ++ /* Start the management command */ ++ p = qbman_swp_mc_start(s); ++ if (!p) ++ return -EBUSY; ++ ++ /* Encode the caller-provided attributes */ ++ qb_attr_code_encode(&code_bp_bpid, p, bpid); ++ ++ /* Complete the management command */ ++ p = qbman_swp_mc_complete(s, p, p[0] | QBMAN_BP_QUERY); ++ ++ /* Decode the outcome */ ++ rslt = qb_attr_code_decode(&code_generic_rslt, p); ++ BUG_ON(qb_attr_code_decode(&code_generic_verb, p) != QBMAN_BP_QUERY); ++ ++ /* Determine success or failure */ ++ if (unlikely(rslt != QBMAN_MC_RSLT_OK)) { ++ pr_err("Query of BPID 0x%x failed, code=0x%02x\n", bpid, rslt); ++ return -EIO; ++ } ++ ++ /* For the query, word[0] of the result contains only the ++ * verb/rslt fields, so skip word[0]. ++ */ ++ word_copy(&attr[1], &p[1], 15); ++ return 0; ++} ++ ++void qbman_bp_attr_get_bdi(struct qbman_attr *a, int *bdi, int *va, int *wae) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ *bdi = !!qb_attr_code_decode(&code_bp_bdi, p); ++ *va = !!qb_attr_code_decode(&code_bp_va, p); ++ *wae = !!qb_attr_code_decode(&code_bp_wae, p); ++} ++ ++static uint32_t qbman_bp_thresh_to_value(uint32_t val) ++{ ++ return (val & 0xff) << ((val & 0xf00) >> 8); ++} ++ ++void qbman_bp_attr_get_swdet(struct qbman_attr *a, uint32_t *swdet) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ *swdet = qbman_bp_thresh_to_value(qb_attr_code_decode(&code_bp_swdet, ++ p)); ++} ++ ++void qbman_bp_attr_get_swdxt(struct qbman_attr *a, uint32_t *swdxt) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ *swdxt = qbman_bp_thresh_to_value(qb_attr_code_decode(&code_bp_swdxt, ++ p)); ++} ++ ++void qbman_bp_attr_get_hwdet(struct qbman_attr *a, uint32_t *hwdet) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ *hwdet = qbman_bp_thresh_to_value(qb_attr_code_decode(&code_bp_hwdet, ++ p)); ++} ++ ++void qbman_bp_attr_get_hwdxt(struct qbman_attr *a, uint32_t *hwdxt) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ *hwdxt = qbman_bp_thresh_to_value(qb_attr_code_decode(&code_bp_hwdxt, ++ p)); ++} ++ ++void qbman_bp_attr_get_swset(struct qbman_attr *a, uint32_t *swset) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ *swset = qbman_bp_thresh_to_value(qb_attr_code_decode(&code_bp_swset, ++ p)); ++} ++ ++void qbman_bp_attr_get_swsxt(struct qbman_attr *a, uint32_t *swsxt) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ *swsxt = qbman_bp_thresh_to_value(qb_attr_code_decode(&code_bp_swsxt, ++ p)); ++} ++ ++void qbman_bp_attr_get_vbpid(struct qbman_attr *a, uint32_t *vbpid) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ *vbpid = qb_attr_code_decode(&code_bp_vbpid, p); ++} ++ ++void qbman_bp_attr_get_icid(struct qbman_attr *a, uint32_t *icid, int *pl) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ *icid = qb_attr_code_decode(&code_bp_icid, p); ++ *pl = !!qb_attr_code_decode(&code_bp_pl, p); ++} ++ ++void qbman_bp_attr_get_bpscn_addr(struct qbman_attr *a, uint64_t *bpscn_addr) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ *bpscn_addr = ((uint64_t)qb_attr_code_decode(&code_bp_bpscn_addr_hi, ++ p) << 32) | ++ (uint64_t)qb_attr_code_decode(&code_bp_bpscn_addr_lo, ++ p); ++} ++ ++void qbman_bp_attr_get_bpscn_ctx(struct qbman_attr *a, uint64_t *bpscn_ctx) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ *bpscn_ctx = ((uint64_t)qb_attr_code_decode(&code_bp_bpscn_ctx_hi, p) ++ << 32) | ++ (uint64_t)qb_attr_code_decode(&code_bp_bpscn_ctx_lo, ++ p); ++} ++ ++void qbman_bp_attr_get_hw_targ(struct qbman_attr *a, uint32_t *hw_targ) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ *hw_targ = qb_attr_code_decode(&code_bp_hw_targ, p); ++} ++ ++int qbman_bp_info_has_free_bufs(struct qbman_attr *a) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ return !(int)(qb_attr_code_decode(&code_bp_state, p) & 0x1); ++} ++ ++int qbman_bp_info_is_depleted(struct qbman_attr *a) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ return (int)(qb_attr_code_decode(&code_bp_state, p) & 0x2); ++} ++ ++int qbman_bp_info_is_surplus(struct qbman_attr *a) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ return (int)(qb_attr_code_decode(&code_bp_state, p) & 0x4); ++} ++ ++uint32_t qbman_bp_info_num_free_bufs(struct qbman_attr *a) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ return qb_attr_code_decode(&code_bp_fill, p); ++} ++ ++uint32_t qbman_bp_info_hdptr(struct qbman_attr *a) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ return qb_attr_code_decode(&code_bp_hdptr, p); ++} ++ ++uint32_t qbman_bp_info_sdcnt(struct qbman_attr *a) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ return qb_attr_code_decode(&code_bp_sdcnt, p); ++} ++ ++uint32_t qbman_bp_info_hdcnt(struct qbman_attr *a) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ return qb_attr_code_decode(&code_bp_hdcnt, p); ++} ++ ++uint32_t qbman_bp_info_sscnt(struct qbman_attr *a) ++{ ++ uint32_t *p = ATTR32(a); ++ ++ return qb_attr_code_decode(&code_bp_sscnt, p); ++} ++ ++static struct qb_attr_code code_fq_fqid = QB_CODE(1, 0, 24); ++static struct qb_attr_code code_fq_cgrid = QB_CODE(2, 16, 16); ++static struct qb_attr_code code_fq_destwq = QB_CODE(3, 0, 15); ++static struct qb_attr_code code_fq_fqctrl = QB_CODE(3, 24, 8); ++static struct qb_attr_code code_fq_icscred = QB_CODE(4, 0, 15); ++static struct qb_attr_code code_fq_tdthresh = QB_CODE(4, 16, 13); ++static struct qb_attr_code code_fq_oa_len = QB_CODE(5, 0, 12); ++static struct qb_attr_code code_fq_oa_ics = QB_CODE(5, 14, 1); ++static struct qb_attr_code code_fq_oa_cgr = QB_CODE(5, 15, 1); ++static struct qb_attr_code code_fq_mctl_bdi = QB_CODE(5, 24, 1); ++static struct qb_attr_code code_fq_mctl_ff = QB_CODE(5, 25, 1); ++static struct qb_attr_code code_fq_mctl_va = QB_CODE(5, 26, 1); ++static struct qb_attr_code code_fq_mctl_ps = QB_CODE(5, 27, 1); ++static struct qb_attr_code code_fq_ctx_lower32 = QB_CODE(6, 0, 32); ++static struct qb_attr_code code_fq_ctx_upper32 = QB_CODE(7, 0, 32); ++static struct qb_attr_code code_fq_icid = QB_CODE(8, 0, 15); ++static struct qb_attr_code code_fq_pl = QB_CODE(8, 15, 1); ++static struct qb_attr_code code_fq_vfqid = QB_CODE(9, 0, 24); ++static struct qb_attr_code code_fq_erfqid = QB_CODE(10, 0, 24); ++ ++static void qbman_fq_attr_clear(struct qbman_attr *a) ++{ ++ memset(a, 0, sizeof(*a)); ++ attr_type_set(a, qbman_attr_usage_fq); ++} ++ ++/* FQ query function for programmable fields */ ++int qbman_fq_query(struct qbman_swp *s, uint32_t fqid, struct qbman_attr *desc) ++{ ++ uint32_t *p; ++ uint32_t rslt; ++ uint32_t *d = ATTR32(desc); ++ ++ qbman_fq_attr_clear(desc); ++ ++ p = qbman_swp_mc_start(s); ++ if (!p) ++ return -EBUSY; ++ qb_attr_code_encode(&code_fq_fqid, p, fqid); ++ p = qbman_swp_mc_complete(s, p, QBMAN_FQ_QUERY); ++ ++ /* Decode the outcome */ ++ rslt = qb_attr_code_decode(&code_generic_rslt, p); ++ BUG_ON(qb_attr_code_decode(&code_generic_verb, p) != QBMAN_FQ_QUERY); ++ ++ /* Determine success or failure */ ++ if (unlikely(rslt != QBMAN_MC_RSLT_OK)) { ++ pr_err("Query of FQID 0x%x failed, code=0x%02x\n", ++ fqid, rslt); ++ return -EIO; ++ } ++ /* For the configure, word[0] of the command contains only the WE-mask. ++ * For the query, word[0] of the result contains only the verb/rslt ++ * fields. Skip word[0] in the latter case. */ ++ word_copy(&d[1], &p[1], 15); ++ return 0; ++} ++ ++void qbman_fq_attr_get_fqctrl(struct qbman_attr *d, uint32_t *fqctrl) ++{ ++ uint32_t *p = ATTR32(d); ++ ++ *fqctrl = qb_attr_code_decode(&code_fq_fqctrl, p); ++} ++ ++void qbman_fq_attr_get_cgrid(struct qbman_attr *d, uint32_t *cgrid) ++{ ++ uint32_t *p = ATTR32(d); ++ ++ *cgrid = qb_attr_code_decode(&code_fq_cgrid, p); ++} ++ ++void qbman_fq_attr_get_destwq(struct qbman_attr *d, uint32_t *destwq) ++{ ++ uint32_t *p = ATTR32(d); ++ ++ *destwq = qb_attr_code_decode(&code_fq_destwq, p); ++} ++ ++void qbman_fq_attr_get_icscred(struct qbman_attr *d, uint32_t *icscred) ++{ ++ uint32_t *p = ATTR32(d); ++ ++ *icscred = qb_attr_code_decode(&code_fq_icscred, p); ++} ++ ++static struct qb_attr_code code_tdthresh_exp = QB_CODE(0, 0, 5); ++static struct qb_attr_code code_tdthresh_mant = QB_CODE(0, 5, 8); ++static uint32_t qbman_thresh_to_value(uint32_t val) ++{ ++ uint32_t m, e; ++ ++ m = qb_attr_code_decode(&code_tdthresh_mant, &val); ++ e = qb_attr_code_decode(&code_tdthresh_exp, &val); ++ return m << e; ++} ++ ++void qbman_fq_attr_get_tdthresh(struct qbman_attr *d, uint32_t *tdthresh) ++{ ++ uint32_t *p = ATTR32(d); ++ ++ *tdthresh = qbman_thresh_to_value(qb_attr_code_decode(&code_fq_tdthresh, ++ p)); ++} ++ ++void qbman_fq_attr_get_oa(struct qbman_attr *d, ++ int *oa_ics, int *oa_cgr, int32_t *oa_len) ++{ ++ uint32_t *p = ATTR32(d); ++ ++ *oa_ics = !!qb_attr_code_decode(&code_fq_oa_ics, p); ++ *oa_cgr = !!qb_attr_code_decode(&code_fq_oa_cgr, p); ++ *oa_len = qb_attr_code_makesigned(&code_fq_oa_len, ++ qb_attr_code_decode(&code_fq_oa_len, p)); ++} ++ ++void qbman_fq_attr_get_mctl(struct qbman_attr *d, ++ int *bdi, int *ff, int *va, int *ps) ++{ ++ uint32_t *p = ATTR32(d); ++ ++ *bdi = !!qb_attr_code_decode(&code_fq_mctl_bdi, p); ++ *ff = !!qb_attr_code_decode(&code_fq_mctl_ff, p); ++ *va = !!qb_attr_code_decode(&code_fq_mctl_va, p); ++ *ps = !!qb_attr_code_decode(&code_fq_mctl_ps, p); ++} ++ ++void qbman_fq_attr_get_ctx(struct qbman_attr *d, uint32_t *hi, uint32_t *lo) ++{ ++ uint32_t *p = ATTR32(d); ++ ++ *hi = qb_attr_code_decode(&code_fq_ctx_upper32, p); ++ *lo = qb_attr_code_decode(&code_fq_ctx_lower32, p); ++} ++ ++void qbman_fq_attr_get_icid(struct qbman_attr *d, uint32_t *icid, int *pl) ++{ ++ uint32_t *p = ATTR32(d); ++ ++ *icid = qb_attr_code_decode(&code_fq_icid, p); ++ *pl = !!qb_attr_code_decode(&code_fq_pl, p); ++} ++ ++void qbman_fq_attr_get_vfqid(struct qbman_attr *d, uint32_t *vfqid) ++{ ++ uint32_t *p = ATTR32(d); ++ ++ *vfqid = qb_attr_code_decode(&code_fq_vfqid, p); ++} ++ ++void qbman_fq_attr_get_erfqid(struct qbman_attr *d, uint32_t *erfqid) ++{ ++ uint32_t *p = ATTR32(d); ++ ++ *erfqid = qb_attr_code_decode(&code_fq_erfqid, p); ++} ++ ++/* Query FQ Non-Programmalbe Fields */ ++static struct qb_attr_code code_fq_np_state = QB_CODE(0, 16, 3); ++static struct qb_attr_code code_fq_np_fe = QB_CODE(0, 19, 1); ++static struct qb_attr_code code_fq_np_x = QB_CODE(0, 20, 1); ++static struct qb_attr_code code_fq_np_r = QB_CODE(0, 21, 1); ++static struct qb_attr_code code_fq_np_oe = QB_CODE(0, 22, 1); ++static struct qb_attr_code code_fq_np_frm_cnt = QB_CODE(6, 0, 24); ++static struct qb_attr_code code_fq_np_byte_cnt = QB_CODE(7, 0, 32); ++ ++int qbman_fq_query_state(struct qbman_swp *s, uint32_t fqid, ++ struct qbman_attr *state) ++{ ++ uint32_t *p; ++ uint32_t rslt; ++ uint32_t *d = ATTR32(state); ++ ++ qbman_fq_attr_clear(state); ++ ++ p = qbman_swp_mc_start(s); ++ if (!p) ++ return -EBUSY; ++ qb_attr_code_encode(&code_fq_fqid, p, fqid); ++ p = qbman_swp_mc_complete(s, p, QBMAN_FQ_QUERY_NP); ++ ++ /* Decode the outcome */ ++ rslt = qb_attr_code_decode(&code_generic_rslt, p); ++ BUG_ON(qb_attr_code_decode(&code_generic_verb, p) != QBMAN_FQ_QUERY_NP); ++ ++ /* Determine success or failure */ ++ if (unlikely(rslt != QBMAN_MC_RSLT_OK)) { ++ pr_err("Query NP fields of FQID 0x%x failed, code=0x%02x\n", ++ fqid, rslt); ++ return -EIO; ++ } ++ word_copy(&d[0], &p[0], 16); ++ return 0; ++} ++ ++uint32_t qbman_fq_state_schedstate(const struct qbman_attr *state) ++{ ++ const uint32_t *p = ATTR32(state); ++ ++ return qb_attr_code_decode(&code_fq_np_state, p); ++} ++ ++int qbman_fq_state_force_eligible(const struct qbman_attr *state) ++{ ++ const uint32_t *p = ATTR32(state); ++ ++ return !!qb_attr_code_decode(&code_fq_np_fe, p); ++} ++ ++int qbman_fq_state_xoff(const struct qbman_attr *state) ++{ ++ const uint32_t *p = ATTR32(state); ++ ++ return !!qb_attr_code_decode(&code_fq_np_x, p); ++} ++ ++int qbman_fq_state_retirement_pending(const struct qbman_attr *state) ++{ ++ const uint32_t *p = ATTR32(state); ++ ++ return !!qb_attr_code_decode(&code_fq_np_r, p); ++} ++ ++int qbman_fq_state_overflow_error(const struct qbman_attr *state) ++{ ++ const uint32_t *p = ATTR32(state); ++ ++ return !!qb_attr_code_decode(&code_fq_np_oe, p); ++} ++ ++uint32_t qbman_fq_state_frame_count(const struct qbman_attr *state) ++{ ++ const uint32_t *p = ATTR32(state); ++ ++ return qb_attr_code_decode(&code_fq_np_frm_cnt, p); ++} ++ ++uint32_t qbman_fq_state_byte_count(const struct qbman_attr *state) ++{ ++ const uint32_t *p = ATTR32(state); ++ ++ return qb_attr_code_decode(&code_fq_np_byte_cnt, p); ++} ++ ++/* Query CGR */ ++static struct qb_attr_code code_cgr_cgid = QB_CODE(0, 16, 16); ++static struct qb_attr_code code_cgr_cscn_wq_en_enter = QB_CODE(2, 0, 1); ++static struct qb_attr_code code_cgr_cscn_wq_en_exit = QB_CODE(2, 1, 1); ++static struct qb_attr_code code_cgr_cscn_wq_icd = QB_CODE(2, 2, 1); ++static struct qb_attr_code code_cgr_mode = QB_CODE(3, 16, 2); ++static struct qb_attr_code code_cgr_rej_cnt_mode = QB_CODE(3, 18, 1); ++static struct qb_attr_code code_cgr_cscn_bdi = QB_CODE(3, 19, 1); ++static struct qb_attr_code code_cgr_cscn_wr_en_enter = QB_CODE(3, 24, 1); ++static struct qb_attr_code code_cgr_cscn_wr_en_exit = QB_CODE(3, 25, 1); ++static struct qb_attr_code code_cgr_cg_wr_ae = QB_CODE(3, 26, 1); ++static struct qb_attr_code code_cgr_cscn_dcp_en = QB_CODE(3, 27, 1); ++static struct qb_attr_code code_cgr_cg_wr_va = QB_CODE(3, 28, 1); ++static struct qb_attr_code code_cgr_i_cnt_wr_en = QB_CODE(4, 0, 1); ++static struct qb_attr_code code_cgr_i_cnt_wr_bnd = QB_CODE(4, 1, 5); ++static struct qb_attr_code code_cgr_td_en = QB_CODE(4, 8, 1); ++static struct qb_attr_code code_cgr_cs_thres = QB_CODE(4, 16, 13); ++static struct qb_attr_code code_cgr_cs_thres_x = QB_CODE(5, 0, 13); ++static struct qb_attr_code code_cgr_td_thres = QB_CODE(5, 16, 13); ++static struct qb_attr_code code_cgr_cscn_tdcp = QB_CODE(6, 0, 16); ++static struct qb_attr_code code_cgr_cscn_wqid = QB_CODE(6, 16, 16); ++static struct qb_attr_code code_cgr_cscn_vcgid = QB_CODE(7, 0, 16); ++static struct qb_attr_code code_cgr_cg_icid = QB_CODE(7, 16, 15); ++static struct qb_attr_code code_cgr_cg_pl = QB_CODE(7, 31, 1); ++static struct qb_attr_code code_cgr_cg_wr_addr_lo = QB_CODE(8, 0, 32); ++static struct qb_attr_code code_cgr_cg_wr_addr_hi = QB_CODE(9, 0, 32); ++static struct qb_attr_code code_cgr_cscn_ctx_lo = QB_CODE(10, 0, 32); ++static struct qb_attr_code code_cgr_cscn_ctx_hi = QB_CODE(11, 0, 32); ++ ++static void qbman_cgr_attr_clear(struct qbman_attr *a) ++{ ++ memset(a, 0, sizeof(*a)); ++ attr_type_set(a, qbman_attr_usage_cgr); ++} ++ ++int qbman_cgr_query(struct qbman_swp *s, uint32_t cgid, struct qbman_attr *attr) ++{ ++ uint32_t *p; ++ uint32_t verb, rslt; ++ uint32_t *d[2]; ++ int i; ++ uint32_t query_verb; ++ ++ d[0] = ATTR32(attr); ++ d[1] = ATTR32_1(attr); ++ ++ qbman_cgr_attr_clear(attr); ++ ++ for (i = 0; i < 2; i++) { ++ p = qbman_swp_mc_start(s); ++ if (!p) ++ return -EBUSY; ++ query_verb = i ? QBMAN_WRED_QUERY : QBMAN_CGR_QUERY; ++ ++ qb_attr_code_encode(&code_cgr_cgid, p, cgid); ++ p = qbman_swp_mc_complete(s, p, p[0] | query_verb); ++ ++ /* Decode the outcome */ ++ verb = qb_attr_code_decode(&code_generic_verb, p); ++ rslt = qb_attr_code_decode(&code_generic_rslt, p); ++ BUG_ON(verb != query_verb); ++ ++ /* Determine success or failure */ ++ if (unlikely(rslt != QBMAN_MC_RSLT_OK)) { ++ pr_err("Query CGID 0x%x failed,", cgid); ++ pr_err(" verb=0x%02x, code=0x%02x\n", verb, rslt); ++ return -EIO; ++ } ++ /* For the configure, word[0] of the command contains only the ++ * verb/cgid. For the query, word[0] of the result contains ++ * only the verb/rslt fields. Skip word[0] in the latter case. ++ */ ++ word_copy(&d[i][1], &p[1], 15); ++ } ++ return 0; ++} ++ ++void qbman_cgr_attr_get_ctl1(struct qbman_attr *d, int *cscn_wq_en_enter, ++ int *cscn_wq_en_exit, int *cscn_wq_icd) ++ { ++ uint32_t *p = ATTR32(d); ++ *cscn_wq_en_enter = !!qb_attr_code_decode(&code_cgr_cscn_wq_en_enter, ++ p); ++ *cscn_wq_en_exit = !!qb_attr_code_decode(&code_cgr_cscn_wq_en_exit, p); ++ *cscn_wq_icd = !!qb_attr_code_decode(&code_cgr_cscn_wq_icd, p); ++} ++ ++void qbman_cgr_attr_get_mode(struct qbman_attr *d, uint32_t *mode, ++ int *rej_cnt_mode, int *cscn_bdi) ++{ ++ uint32_t *p = ATTR32(d); ++ *mode = qb_attr_code_decode(&code_cgr_mode, p); ++ *rej_cnt_mode = !!qb_attr_code_decode(&code_cgr_rej_cnt_mode, p); ++ *cscn_bdi = !!qb_attr_code_decode(&code_cgr_cscn_bdi, p); ++} ++ ++void qbman_cgr_attr_get_ctl2(struct qbman_attr *d, int *cscn_wr_en_enter, ++ int *cscn_wr_en_exit, int *cg_wr_ae, ++ int *cscn_dcp_en, int *cg_wr_va) ++{ ++ uint32_t *p = ATTR32(d); ++ *cscn_wr_en_enter = !!qb_attr_code_decode(&code_cgr_cscn_wr_en_enter, ++ p); ++ *cscn_wr_en_exit = !!qb_attr_code_decode(&code_cgr_cscn_wr_en_exit, p); ++ *cg_wr_ae = !!qb_attr_code_decode(&code_cgr_cg_wr_ae, p); ++ *cscn_dcp_en = !!qb_attr_code_decode(&code_cgr_cscn_dcp_en, p); ++ *cg_wr_va = !!qb_attr_code_decode(&code_cgr_cg_wr_va, p); ++} ++ ++void qbman_cgr_attr_get_iwc(struct qbman_attr *d, int *i_cnt_wr_en, ++ uint32_t *i_cnt_wr_bnd) ++{ ++ uint32_t *p = ATTR32(d); ++ *i_cnt_wr_en = !!qb_attr_code_decode(&code_cgr_i_cnt_wr_en, p); ++ *i_cnt_wr_bnd = qb_attr_code_decode(&code_cgr_i_cnt_wr_bnd, p); ++} ++ ++void qbman_cgr_attr_get_tdc(struct qbman_attr *d, int *td_en) ++{ ++ uint32_t *p = ATTR32(d); ++ *td_en = !!qb_attr_code_decode(&code_cgr_td_en, p); ++} ++ ++void qbman_cgr_attr_get_cs_thres(struct qbman_attr *d, uint32_t *cs_thres) ++{ ++ uint32_t *p = ATTR32(d); ++ *cs_thres = qbman_thresh_to_value(qb_attr_code_decode( ++ &code_cgr_cs_thres, p)); ++} ++ ++void qbman_cgr_attr_get_cs_thres_x(struct qbman_attr *d, ++ uint32_t *cs_thres_x) ++{ ++ uint32_t *p = ATTR32(d); ++ *cs_thres_x = qbman_thresh_to_value(qb_attr_code_decode( ++ &code_cgr_cs_thres_x, p)); ++} ++ ++void qbman_cgr_attr_get_td_thres(struct qbman_attr *d, uint32_t *td_thres) ++{ ++ uint32_t *p = ATTR32(d); ++ *td_thres = qbman_thresh_to_value(qb_attr_code_decode( ++ &code_cgr_td_thres, p)); ++} ++ ++void qbman_cgr_attr_get_cscn_tdcp(struct qbman_attr *d, uint32_t *cscn_tdcp) ++{ ++ uint32_t *p = ATTR32(d); ++ *cscn_tdcp = qb_attr_code_decode(&code_cgr_cscn_tdcp, p); ++} ++ ++void qbman_cgr_attr_get_cscn_wqid(struct qbman_attr *d, uint32_t *cscn_wqid) ++{ ++ uint32_t *p = ATTR32(d); ++ *cscn_wqid = qb_attr_code_decode(&code_cgr_cscn_wqid, p); ++} ++ ++void qbman_cgr_attr_get_cscn_vcgid(struct qbman_attr *d, ++ uint32_t *cscn_vcgid) ++{ ++ uint32_t *p = ATTR32(d); ++ *cscn_vcgid = qb_attr_code_decode(&code_cgr_cscn_vcgid, p); ++} ++ ++void qbman_cgr_attr_get_cg_icid(struct qbman_attr *d, uint32_t *icid, ++ int *pl) ++{ ++ uint32_t *p = ATTR32(d); ++ *icid = qb_attr_code_decode(&code_cgr_cg_icid, p); ++ *pl = !!qb_attr_code_decode(&code_cgr_cg_pl, p); ++} ++ ++void qbman_cgr_attr_get_cg_wr_addr(struct qbman_attr *d, ++ uint64_t *cg_wr_addr) ++{ ++ uint32_t *p = ATTR32(d); ++ *cg_wr_addr = ((uint64_t)qb_attr_code_decode(&code_cgr_cg_wr_addr_hi, ++ p) << 32) | ++ (uint64_t)qb_attr_code_decode(&code_cgr_cg_wr_addr_lo, ++ p); ++} ++ ++void qbman_cgr_attr_get_cscn_ctx(struct qbman_attr *d, uint64_t *cscn_ctx) ++{ ++ uint32_t *p = ATTR32(d); ++ *cscn_ctx = ((uint64_t)qb_attr_code_decode(&code_cgr_cscn_ctx_hi, p) ++ << 32) | ++ (uint64_t)qb_attr_code_decode(&code_cgr_cscn_ctx_lo, p); ++} ++ ++#define WRED_EDP_WORD(n) (18 + n / 4) ++#define WRED_EDP_OFFSET(n) (8 * (n % 4)) ++#define WRED_PARM_DP_WORD(n) (n + 20) ++#define WRED_WE_EDP(n) (16 + n * 2) ++#define WRED_WE_PARM_DP(n) (17 + n * 2) ++void qbman_cgr_attr_wred_get_edp(struct qbman_attr *d, uint32_t idx, ++ int *edp) ++{ ++ uint32_t *p = ATTR32(d); ++ struct qb_attr_code code_wred_edp = QB_CODE(WRED_EDP_WORD(idx), ++ WRED_EDP_OFFSET(idx), 8); ++ *edp = (int)qb_attr_code_decode(&code_wred_edp, p); ++} ++ ++void qbman_cgr_attr_wred_dp_decompose(uint32_t dp, uint64_t *minth, ++ uint64_t *maxth, uint8_t *maxp) ++{ ++ uint8_t ma, mn, step_i, step_s, pn; ++ ++ ma = (uint8_t)(dp >> 24); ++ mn = (uint8_t)(dp >> 19) & 0x1f; ++ step_i = (uint8_t)(dp >> 11); ++ step_s = (uint8_t)(dp >> 6) & 0x1f; ++ pn = (uint8_t)dp & 0x3f; ++ ++ *maxp = (uint8_t)(((pn << 2) * 100) / 256); ++ ++ if (mn == 0) ++ *maxth = ma; ++ else ++ *maxth = ((ma + 256) * (1 << (mn - 1))); ++ ++ if (step_s == 0) ++ *minth = *maxth - step_i; ++ else ++ *minth = *maxth - (256 + step_i) * (1 << (step_s - 1)); ++} ++ ++void qbman_cgr_attr_wred_get_parm_dp(struct qbman_attr *d, uint32_t idx, ++ uint32_t *dp) ++{ ++ uint32_t *p = ATTR32(d); ++ struct qb_attr_code code_wred_parm_dp = QB_CODE(WRED_PARM_DP_WORD(idx), ++ 0, 8); ++ *dp = qb_attr_code_decode(&code_wred_parm_dp, p); ++} ++ ++/* Query CGR/CCGR/CQ statistics */ ++static struct qb_attr_code code_cgr_stat_ct = QB_CODE(4, 0, 32); ++static struct qb_attr_code code_cgr_stat_frame_cnt_lo = QB_CODE(4, 0, 32); ++static struct qb_attr_code code_cgr_stat_frame_cnt_hi = QB_CODE(5, 0, 8); ++static struct qb_attr_code code_cgr_stat_byte_cnt_lo = QB_CODE(6, 0, 32); ++static struct qb_attr_code code_cgr_stat_byte_cnt_hi = QB_CODE(7, 0, 16); ++static int qbman_cgr_statistics_query(struct qbman_swp *s, uint32_t cgid, ++ int clear, uint32_t command_type, ++ uint64_t *frame_cnt, uint64_t *byte_cnt) ++{ ++ uint32_t *p; ++ uint32_t verb, rslt; ++ uint32_t query_verb; ++ uint32_t hi, lo; ++ ++ p = qbman_swp_mc_start(s); ++ if (!p) ++ return -EBUSY; ++ ++ qb_attr_code_encode(&code_cgr_cgid, p, cgid); ++ if (command_type < 2) ++ qb_attr_code_encode(&code_cgr_stat_ct, p, command_type); ++ query_verb = clear ? ++ QBMAN_CGR_STAT_QUERY_CLR : QBMAN_CGR_STAT_QUERY; ++ p = qbman_swp_mc_complete(s, p, p[0] | query_verb); ++ ++ /* Decode the outcome */ ++ verb = qb_attr_code_decode(&code_generic_verb, p); ++ rslt = qb_attr_code_decode(&code_generic_rslt, p); ++ BUG_ON(verb != query_verb); ++ ++ /* Determine success or failure */ ++ if (unlikely(rslt != QBMAN_MC_RSLT_OK)) { ++ pr_err("Query statistics of CGID 0x%x failed,", cgid); ++ pr_err(" verb=0x%02x code=0x%02x\n", verb, rslt); ++ return -EIO; ++ } ++ ++ if (*frame_cnt) { ++ hi = qb_attr_code_decode(&code_cgr_stat_frame_cnt_hi, p); ++ lo = qb_attr_code_decode(&code_cgr_stat_frame_cnt_lo, p); ++ *frame_cnt = ((uint64_t)hi << 32) | (uint64_t)lo; ++ } ++ if (*byte_cnt) { ++ hi = qb_attr_code_decode(&code_cgr_stat_byte_cnt_hi, p); ++ lo = qb_attr_code_decode(&code_cgr_stat_byte_cnt_lo, p); ++ *byte_cnt = ((uint64_t)hi << 32) | (uint64_t)lo; ++ } ++ ++ return 0; ++} ++ ++int qbman_cgr_reject_statistics(struct qbman_swp *s, uint32_t cgid, int clear, ++ uint64_t *frame_cnt, uint64_t *byte_cnt) ++{ ++ return qbman_cgr_statistics_query(s, cgid, clear, 0xff, ++ frame_cnt, byte_cnt); ++} ++ ++int qbman_ccgr_reject_statistics(struct qbman_swp *s, uint32_t cgid, int clear, ++ uint64_t *frame_cnt, uint64_t *byte_cnt) ++{ ++ return qbman_cgr_statistics_query(s, cgid, clear, 1, ++ frame_cnt, byte_cnt); ++} ++ ++int qbman_cq_dequeue_statistics(struct qbman_swp *s, uint32_t cgid, int clear, ++ uint64_t *frame_cnt, uint64_t *byte_cnt) ++{ ++ return qbman_cgr_statistics_query(s, cgid, clear, 0, ++ frame_cnt, byte_cnt); ++} ++ ++/* WQ Chan Query */ ++static struct qb_attr_code code_wqchan_chanid = QB_CODE(0, 16, 16); ++static struct qb_attr_code code_wqchan_cdan_ctx_lo = QB_CODE(2, 0, 32); ++static struct qb_attr_code code_wqchan_cdan_ctx_hi = QB_CODE(3, 0, 32); ++static struct qb_attr_code code_wqchan_cdan_wqid = QB_CODE(1, 16, 16); ++static struct qb_attr_code code_wqchan_ctrl = QB_CODE(1, 8, 8); ++ ++static void qbman_wqchan_attr_clear(struct qbman_attr *a) ++{ ++ memset(a, 0, sizeof(*a)); ++ attr_type_set(a, qbman_attr_usage_wqchan); ++} ++ ++int qbman_wqchan_query(struct qbman_swp *s, uint16_t chanid, ++ struct qbman_attr *a) ++{ ++ uint32_t *p; ++ uint32_t rslt; ++ uint32_t *attr = ATTR32(a); ++ ++ qbman_wqchan_attr_clear(a); ++ ++ /* Start the management command */ ++ p = qbman_swp_mc_start(s); ++ if (!p) ++ return -EBUSY; ++ ++ /* Encode the caller-provided attributes */ ++ qb_attr_code_encode(&code_wqchan_chanid, p, chanid); ++ ++ /* Complete the management command */ ++ p = qbman_swp_mc_complete(s, p, p[0] | QBMAN_WQ_QUERY); ++ ++ /* Decode the outcome */ ++ rslt = qb_attr_code_decode(&code_generic_rslt, p); ++ BUG_ON(qb_attr_code_decode(&code_generic_verb, p); != QBMAN_WQ_QUERY); ++ ++ /* Determine success or failure */ ++ if (unlikely(rslt != QBMAN_MC_RSLT_OK)) { ++ pr_err("Query of WQCHAN 0x%x failed, code=0x%02x\n", ++ chanid, rslt); ++ return -EIO; ++ } ++ ++ /* For the query, word[0] of the result contains only the ++ * verb/rslt fields, so skip word[0]. ++ */ ++ word_copy(&attr[1], &p[1], 15); ++ return 0; ++} ++ ++void qbman_wqchan_attr_get_wqlen(struct qbman_attr *attr, int wq, uint32_t *len) ++{ ++ uint32_t *p = ATTR32(attr); ++ struct qb_attr_code code_wqchan_len = QB_CODE(wq + 8, 0, 24); ++ *len = qb_attr_code_decode(&code_wqchan_len, p); ++} ++ ++void qbman_wqchan_attr_get_cdan_ctx(struct qbman_attr *attr, uint64_t *cdan_ctx) ++{ ++ uint32_t lo, hi; ++ uint32_t *p = ATTR32(attr); ++ ++ lo = qb_attr_code_decode(&code_wqchan_cdan_ctx_lo, p); ++ hi = qb_attr_code_decode(&code_wqchan_cdan_ctx_hi, p); ++ *cdan_ctx = ((uint64_t)hi << 32) | (uint64_t)lo; ++} ++ ++void qbman_wqchan_attr_get_cdan_wqid(struct qbman_attr *attr, ++ uint16_t *cdan_wqid) ++{ ++ uint32_t *p = ATTR32(attr); ++ *cdan_wqid = (uint16_t)qb_attr_code_decode(&code_wqchan_cdan_wqid, p); ++} ++ ++void qbman_wqchan_attr_get_ctrl(struct qbman_attr *attr, uint8_t *ctrl) ++{ ++ uint32_t *p = ATTR32(attr); ++ *ctrl = (uint8_t)qb_attr_code_decode(&code_wqchan_ctrl, p); ++} ++ ++void qbman_wqchan_attr_get_chanid(struct qbman_attr *attr, uint16_t *chanid) ++{ ++ uint32_t *p = ATTR32(attr); ++ *chanid = (uint16_t)qb_attr_code_decode(&code_wqchan_chanid, p); ++} +diff --git a/drivers/net/dpaa2/qbman/driver/qbman_debug.h b/drivers/net/dpaa2/qbman/driver/qbman_debug.h +new file mode 100644 +index 0000000..4d586a6 +--- /dev/null ++++ b/drivers/net/dpaa2/qbman/driver/qbman_debug.h +@@ -0,0 +1,140 @@ ++/* Copyright (C) 2015 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY ++ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++struct qbman_attr { ++ uint32_t dont_manipulate_directly[40]; ++}; ++ ++/* Buffer pool query commands */ ++int qbman_bp_query(struct qbman_swp *s, uint32_t bpid, ++ struct qbman_attr *a); ++void qbman_bp_attr_get_bdi(struct qbman_attr *a, int *bdi, int *va, int *wae); ++void qbman_bp_attr_get_swdet(struct qbman_attr *a, uint32_t *swdet); ++void qbman_bp_attr_get_swdxt(struct qbman_attr *a, uint32_t *swdxt); ++void qbman_bp_attr_get_hwdet(struct qbman_attr *a, uint32_t *hwdet); ++void qbman_bp_attr_get_hwdxt(struct qbman_attr *a, uint32_t *hwdxt); ++void qbman_bp_attr_get_swset(struct qbman_attr *a, uint32_t *swset); ++void qbman_bp_attr_get_swsxt(struct qbman_attr *a, uint32_t *swsxt); ++void qbman_bp_attr_get_vbpid(struct qbman_attr *a, uint32_t *vbpid); ++void qbman_bp_attr_get_icid(struct qbman_attr *a, uint32_t *icid, int *pl); ++void qbman_bp_attr_get_bpscn_addr(struct qbman_attr *a, uint64_t *bpscn_addr); ++void qbman_bp_attr_get_bpscn_ctx(struct qbman_attr *a, uint64_t *bpscn_ctx); ++void qbman_bp_attr_get_hw_targ(struct qbman_attr *a, uint32_t *hw_targ); ++int qbman_bp_info_has_free_bufs(struct qbman_attr *a); ++int qbman_bp_info_is_depleted(struct qbman_attr *a); ++int qbman_bp_info_is_surplus(struct qbman_attr *a); ++uint32_t qbman_bp_info_num_free_bufs(struct qbman_attr *a); ++uint32_t qbman_bp_info_hdptr(struct qbman_attr *a); ++uint32_t qbman_bp_info_sdcnt(struct qbman_attr *a); ++uint32_t qbman_bp_info_hdcnt(struct qbman_attr *a); ++uint32_t qbman_bp_info_sscnt(struct qbman_attr *a); ++ ++/* FQ query function for programmable fields */ ++int qbman_fq_query(struct qbman_swp *s, uint32_t fqid, ++ struct qbman_attr *desc); ++void qbman_fq_attr_get_fqctrl(struct qbman_attr *d, uint32_t *fqctrl); ++void qbman_fq_attr_get_cgrid(struct qbman_attr *d, uint32_t *cgrid); ++void qbman_fq_attr_get_destwq(struct qbman_attr *d, uint32_t *destwq); ++void qbman_fq_attr_get_icscred(struct qbman_attr *d, uint32_t *icscred); ++void qbman_fq_attr_get_tdthresh(struct qbman_attr *d, uint32_t *tdthresh); ++void qbman_fq_attr_get_oa(struct qbman_attr *d, ++ int *oa_ics, int *oa_cgr, int32_t *oa_len); ++void qbman_fq_attr_get_mctl(struct qbman_attr *d, ++ int *bdi, int *ff, int *va, int *ps); ++void qbman_fq_attr_get_ctx(struct qbman_attr *d, uint32_t *hi, uint32_t *lo); ++void qbman_fq_attr_get_icid(struct qbman_attr *d, uint32_t *icid, int *pl); ++void qbman_fq_attr_get_vfqid(struct qbman_attr *d, uint32_t *vfqid); ++void qbman_fq_attr_get_erfqid(struct qbman_attr *d, uint32_t *erfqid); ++ ++/* FQ query command for non-programmable fields*/ ++enum qbman_fq_schedstate_e { ++ qbman_fq_schedstate_oos = 0, ++ qbman_fq_schedstate_retired, ++ qbman_fq_schedstate_tentatively_scheduled, ++ qbman_fq_schedstate_truly_scheduled, ++ qbman_fq_schedstate_parked, ++ qbman_fq_schedstate_held_active, ++}; ++ ++int qbman_fq_query_state(struct qbman_swp *s, uint32_t fqid, ++ struct qbman_attr *state); ++uint32_t qbman_fq_state_schedstate(const struct qbman_attr *state); ++int qbman_fq_state_force_eligible(const struct qbman_attr *state); ++int qbman_fq_state_xoff(const struct qbman_attr *state); ++int qbman_fq_state_retirement_pending(const struct qbman_attr *state); ++int qbman_fq_state_overflow_error(const struct qbman_attr *state); ++uint32_t qbman_fq_state_frame_count(const struct qbman_attr *state); ++uint32_t qbman_fq_state_byte_count(const struct qbman_attr *state); ++ ++/* CGR query */ ++int qbman_cgr_query(struct qbman_swp *s, uint32_t cgid, ++ struct qbman_attr *attr); ++void qbman_cgr_attr_get_ctl1(struct qbman_attr *d, int *cscn_wq_en_enter, ++ int *cscn_wq_en_exit, int *cscn_wq_icd); ++void qbman_cgr_attr_get_mode(struct qbman_attr *d, uint32_t *mode, ++ int *rej_cnt_mode, int *cscn_bdi); ++void qbman_cgr_attr_get_ctl2(struct qbman_attr *d, int *cscn_wr_en_enter, ++ int *cscn_wr_en_exit, int *cg_wr_ae, ++ int *cscn_dcp_en, int *cg_wr_va); ++void qbman_cgr_attr_get_iwc(struct qbman_attr *d, int *i_cnt_wr_en, ++ uint32_t *i_cnt_wr_bnd); ++void qbman_cgr_attr_get_tdc(struct qbman_attr *d, int *td_en); ++void qbman_cgr_attr_get_cs_thres(struct qbman_attr *d, uint32_t *cs_thres); ++void qbman_cgr_attr_get_cs_thres_x(struct qbman_attr *d, ++ uint32_t *cs_thres_x); ++void qbman_cgr_attr_get_td_thres(struct qbman_attr *d, uint32_t *td_thres); ++void qbman_cgr_attr_get_cscn_tdcp(struct qbman_attr *d, uint32_t *cscn_tdcp); ++void qbman_cgr_attr_get_cscn_wqid(struct qbman_attr *d, uint32_t *cscn_wqid); ++void qbman_cgr_attr_get_cscn_vcgid(struct qbman_attr *d, ++ uint32_t *cscn_vcgid); ++void qbman_cgr_attr_get_cg_icid(struct qbman_attr *d, uint32_t *icid, ++ int *pl); ++void qbman_cgr_attr_get_cg_wr_addr(struct qbman_attr *d, ++ uint64_t *cg_wr_addr); ++void qbman_cgr_attr_get_cscn_ctx(struct qbman_attr *d, uint64_t *cscn_ctx); ++void qbman_cgr_attr_wred_get_edp(struct qbman_attr *d, uint32_t idx, ++ int *edp); ++void qbman_cgr_attr_wred_dp_decompose(uint32_t dp, uint64_t *minth, ++ uint64_t *maxth, uint8_t *maxp); ++void qbman_cgr_attr_wred_get_parm_dp(struct qbman_attr *d, uint32_t idx, ++ uint32_t *dp); ++ ++/* CGR/CCGR/CQ statistics query */ ++int qbman_cgr_reject_statistics(struct qbman_swp *s, uint32_t cgid, int clear, ++ uint64_t *frame_cnt, uint64_t *byte_cnt); ++int qbman_ccgr_reject_statistics(struct qbman_swp *s, uint32_t cgid, int clear, ++ uint64_t *frame_cnt, uint64_t *byte_cnt); ++int qbman_cq_dequeue_statistics(struct qbman_swp *s, uint32_t cgid, int clear, ++ uint64_t *frame_cnt, uint64_t *byte_cnt); ++ ++/* Query Work Queue Channel */ ++int qbman_wqchan_query(struct qbman_swp *s, uint16_t chanid, ++ struct qbman_attr *attr); ++void qbman_wqchan_attr_get_wqlen(struct qbman_attr *attr, int wq, uint32_t *len); ++void qbman_wqchan_attr_get_cdan_ctx(struct qbman_attr *attr, uint64_t *cdan_ctx); ++void qbman_wqchan_attr_get_cdan_wqid(struct qbman_attr *attr, ++ uint16_t *cdan_wqid); ++void qbman_wqchan_attr_get_ctrl(struct qbman_attr *attr, uint8_t *ctrl); ++void qbman_wqchan_attr_get_chanid(struct qbman_attr *attr, uint16_t *chanid); +diff --git a/drivers/net/dpaa2/qbman/driver/qbman_portal.c b/drivers/net/dpaa2/qbman/driver/qbman_portal.c +new file mode 100644 +index 0000000..52e1f64 +--- /dev/null ++++ b/drivers/net/dpaa2/qbman/driver/qbman_portal.c +@@ -0,0 +1,1441 @@ ++/* Copyright (C) 2014 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY ++ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include "qbman_portal.h" ++ ++/* QBMan portal management command codes */ ++#define QBMAN_MC_ACQUIRE 0x30 ++#define QBMAN_WQCHAN_CONFIGURE 0x46 ++ ++/* CINH register offsets */ ++#define QBMAN_CINH_SWP_EQCR_PI 0x800 ++#define QBMAN_CINH_SWP_EQCR_CI 0x840 ++#define QBMAN_CINH_SWP_EQAR 0x8c0 ++#define QBMAN_CINH_SWP_DQPI 0xa00 ++#define QBMAN_CINH_SWP_DCAP 0xac0 ++#define QBMAN_CINH_SWP_SDQCR 0xb00 ++#define QBMAN_CINH_SWP_RAR 0xcc0 ++#define QBMAN_CINH_SWP_ISR 0xe00 ++#define QBMAN_CINH_SWP_IER 0xe40 ++#define QBMAN_CINH_SWP_ISDR 0xe80 ++#define QBMAN_CINH_SWP_IIR 0xec0 ++ ++/* CENA register offsets */ ++#define QBMAN_CENA_SWP_EQCR(n) (0x000 + ((uint32_t)(n) << 6)) ++#define QBMAN_CENA_SWP_DQRR(n) (0x200 + ((uint32_t)(n) << 6)) ++#define QBMAN_CENA_SWP_RCR(n) (0x400 + ((uint32_t)(n) << 6)) ++#define QBMAN_CENA_SWP_CR 0x600 ++#define QBMAN_CENA_SWP_RR(vb) (0x700 + ((uint32_t)(vb) >> 1)) ++#define QBMAN_CENA_SWP_VDQCR 0x780 ++#define QBMAN_CENA_SWP_EQCR_CI 0x840 ++ ++/* Reverse mapping of QBMAN_CENA_SWP_DQRR() */ ++#define QBMAN_IDX_FROM_DQRR(p) (((unsigned long)p & 0x1ff) >> 6) ++ ++/* QBMan FQ management command codes */ ++#define QBMAN_FQ_SCHEDULE 0x48 ++#define QBMAN_FQ_FORCE 0x49 ++#define QBMAN_FQ_XON 0x4d ++#define QBMAN_FQ_XOFF 0x4e ++ ++/*******************************/ ++/* Pre-defined attribute codes */ ++/*******************************/ ++ ++struct qb_attr_code code_generic_verb = QB_CODE(0, 0, 7); ++struct qb_attr_code code_generic_rslt = QB_CODE(0, 8, 8); ++ ++/*************************/ ++/* SDQCR attribute codes */ ++/*************************/ ++ ++/* we put these here because at least some of them are required by ++ * qbman_swp_init() */ ++struct qb_attr_code code_sdqcr_dct = QB_CODE(0, 24, 2); ++struct qb_attr_code code_sdqcr_fc = QB_CODE(0, 29, 1); ++struct qb_attr_code code_sdqcr_tok = QB_CODE(0, 16, 8); ++static struct qb_attr_code code_eq_dca_idx; ++#define CODE_SDQCR_DQSRC(n) QB_CODE(0, n, 1) ++enum qbman_sdqcr_dct { ++ qbman_sdqcr_dct_null = 0, ++ qbman_sdqcr_dct_prio_ics, ++ qbman_sdqcr_dct_active_ics, ++ qbman_sdqcr_dct_active ++}; ++ ++enum qbman_sdqcr_fc { ++ qbman_sdqcr_fc_one = 0, ++ qbman_sdqcr_fc_up_to_3 = 1 ++}; ++ ++struct qb_attr_code code_sdqcr_dqsrc = QB_CODE(0, 0, 16); ++ ++/*********************************/ ++/* Portal constructor/destructor */ ++/*********************************/ ++ ++/* Software portals should always be in the power-on state when we initialise, ++ * due to the CCSR-based portal reset functionality that MC has. ++ * ++ * Erk! Turns out that QMan versions prior to 4.1 do not correctly reset DQRR ++ * valid-bits, so we need to support a workaround where we don't trust ++ * valid-bits when detecting new entries until any stale ring entries have been ++ * overwritten at least once. The idea is that we read PI for the first few ++ * entries, then switch to valid-bit after that. The trick is to clear the ++ * bug-work-around boolean once the PI wraps around the ring for the first time. ++ * ++ * Note: this still carries a slight additional cost once the decrementer hits ++ * zero. ++ */ ++struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d) ++{ ++ int ret; ++ uint32_t eqcr_pi; ++ struct qbman_swp *p = kmalloc(sizeof(*p), GFP_KERNEL); ++ ++ if (!p) ++ return NULL; ++ p->desc = d; ++#ifdef QBMAN_CHECKING ++ p->mc.check = swp_mc_can_start; ++#endif ++ p->mc.valid_bit = QB_VALID_BIT; ++ p->sdq = 0; ++ qb_attr_code_encode(&code_sdqcr_dct, &p->sdq, qbman_sdqcr_dct_prio_ics); ++ qb_attr_code_encode(&code_sdqcr_fc, &p->sdq, qbman_sdqcr_fc_up_to_3); ++ qb_attr_code_encode(&code_sdqcr_tok, &p->sdq, 0xbb); ++ atomic_set(&p->vdq.busy, 1); ++ p->vdq.valid_bit = QB_VALID_BIT; ++ p->dqrr.next_idx = 0; ++ p->dqrr.valid_bit = QB_VALID_BIT; ++ qman_version = p->desc->qman_version; ++ if ((qman_version & 0xFFFF0000) < QMAN_REV_4100) { ++ p->dqrr.dqrr_size = 4; ++ p->dqrr.reset_bug = 1; ++ /* Set size of DQRR to 4, encoded in 2 bits */ ++ code_eq_dca_idx = (struct qb_attr_code)QB_CODE(0, 8, 2); ++ } else { ++ p->dqrr.dqrr_size = 8; ++ p->dqrr.reset_bug = 0; ++ /* Set size of DQRR to 8, encoded in 3 bits */ ++ code_eq_dca_idx = (struct qb_attr_code)QB_CODE(0, 8, 3); ++ } ++ ++ ret = qbman_swp_sys_init(&p->sys, d, p->dqrr.dqrr_size); ++ if (ret) { ++ kfree(p); ++ pr_err("qbman_swp_sys_init() failed %d\n", ret); ++ return NULL; ++ } ++ /* SDQCR needs to be initialized to 0 when no channels are ++ being dequeued from or else the QMan HW will indicate an ++ error. The values that were calculated above will be ++ applied when dequeues from a specific channel are enabled */ ++ qbman_cinh_write(&p->sys, QBMAN_CINH_SWP_SDQCR, 0); ++ eqcr_pi = qbman_cinh_read(&p->sys, QBMAN_CINH_SWP_EQCR_PI); ++ p->eqcr.pi = eqcr_pi & 0xF; ++ p->eqcr.pi_vb = eqcr_pi & QB_VALID_BIT; ++ p->eqcr.ci = qbman_cinh_read(&p->sys, QBMAN_CINH_SWP_EQCR_CI) & 0xF; ++ p->eqcr.available = QBMAN_EQCR_SIZE - qm_cyc_diff(QBMAN_EQCR_SIZE, ++ p->eqcr.ci, p->eqcr.pi); ++ ++ return p; ++} ++ ++void qbman_swp_finish(struct qbman_swp *p) ++{ ++#ifdef QBMAN_CHECKING ++ BUG_ON(p->mc.check != swp_mc_can_start); ++#endif ++ qbman_swp_sys_finish(&p->sys); ++ kfree(p); ++} ++ ++const struct qbman_swp_desc *qbman_swp_get_desc(struct qbman_swp *p) ++{ ++ return p->desc; ++} ++ ++/**************/ ++/* Interrupts */ ++/**************/ ++ ++uint32_t qbman_swp_interrupt_get_vanish(struct qbman_swp *p) ++{ ++ return qbman_cinh_read(&p->sys, QBMAN_CINH_SWP_ISDR); ++} ++ ++void qbman_swp_interrupt_set_vanish(struct qbman_swp *p, uint32_t mask) ++{ ++ qbman_cinh_write(&p->sys, QBMAN_CINH_SWP_ISDR, mask); ++} ++ ++uint32_t qbman_swp_interrupt_read_status(struct qbman_swp *p) ++{ ++ return qbman_cinh_read(&p->sys, QBMAN_CINH_SWP_ISR); ++} ++ ++void qbman_swp_interrupt_clear_status(struct qbman_swp *p, uint32_t mask) ++{ ++ qbman_cinh_write(&p->sys, QBMAN_CINH_SWP_ISR, mask); ++} ++ ++uint32_t qbman_swp_interrupt_get_trigger(struct qbman_swp *p) ++{ ++ return qbman_cinh_read(&p->sys, QBMAN_CINH_SWP_IER); ++} ++ ++void qbman_swp_interrupt_set_trigger(struct qbman_swp *p, uint32_t mask) ++{ ++ qbman_cinh_write(&p->sys, QBMAN_CINH_SWP_IER, mask); ++} ++ ++int qbman_swp_interrupt_get_inhibit(struct qbman_swp *p) ++{ ++ return qbman_cinh_read(&p->sys, QBMAN_CINH_SWP_IIR); ++} ++ ++void qbman_swp_interrupt_set_inhibit(struct qbman_swp *p, int inhibit) ++{ ++ qbman_cinh_write(&p->sys, QBMAN_CINH_SWP_IIR, inhibit ? 0xffffffff : 0); ++} ++ ++/***********************/ ++/* Management commands */ ++/***********************/ ++ ++/* ++ * Internal code common to all types of management commands. ++ */ ++ ++void *qbman_swp_mc_start(struct qbman_swp *p) ++{ ++ void *ret; ++#ifdef QBMAN_CHECKING ++ BUG_ON(p->mc.check != swp_mc_can_start); ++#endif ++ ret = qbman_cena_write_start(&p->sys, QBMAN_CENA_SWP_CR); ++#ifdef QBMAN_CHECKING ++ if (!ret) ++ p->mc.check = swp_mc_can_submit; ++#endif ++ return ret; ++} ++ ++void qbman_swp_mc_submit(struct qbman_swp *p, void *cmd, uint32_t cmd_verb) ++{ ++ uint32_t *v = cmd; ++#ifdef QBMAN_CHECKING ++ BUG_ON(!p->mc.check != swp_mc_can_submit); ++#endif ++ /* TBD: "|=" is going to hurt performance. Need to move as many fields ++ * out of word zero, and for those that remain, the "OR" needs to occur ++ * at the caller side. This debug check helps to catch cases where the ++ * caller wants to OR but has forgotten to do so. */ ++ BUG_ON((*v & cmd_verb) != *v); ++ *v = cmd_verb | p->mc.valid_bit; ++ qbman_cena_write_complete(&p->sys, QBMAN_CENA_SWP_CR, cmd); ++#ifdef QBMAN_CHECKING ++ p->mc.check = swp_mc_can_poll; ++#endif ++} ++ ++void *qbman_swp_mc_result(struct qbman_swp *p) ++{ ++ uint32_t *ret, verb; ++#ifdef QBMAN_CHECKING ++ BUG_ON(p->mc.check != swp_mc_can_poll); ++#endif ++ qbman_cena_invalidate_prefetch(&p->sys, ++ QBMAN_CENA_SWP_RR(p->mc.valid_bit)); ++ ret = qbman_cena_read(&p->sys, QBMAN_CENA_SWP_RR(p->mc.valid_bit)); ++ /* Remove the valid-bit - command completed iff the rest is non-zero */ ++ verb = ret[0] & ~QB_VALID_BIT; ++ if (!verb) ++ return NULL; ++#ifdef QBMAN_CHECKING ++ p->mc.check = swp_mc_can_start; ++#endif ++ p->mc.valid_bit ^= QB_VALID_BIT; ++ return ret; ++} ++ ++/***********/ ++/* Enqueue */ ++/***********/ ++ ++/* These should be const, eventually */ ++static struct qb_attr_code code_eq_cmd = QB_CODE(0, 0, 2); ++static struct qb_attr_code code_eq_eqdi = QB_CODE(0, 3, 1); ++static struct qb_attr_code code_eq_dca_en = QB_CODE(0, 15, 1); ++static struct qb_attr_code code_eq_dca_pk = QB_CODE(0, 14, 1); ++/* Can't set code_eq_dca_idx width. Need qman version. Read at runtime */ ++static struct qb_attr_code code_eq_orp_en = QB_CODE(0, 2, 1); ++static struct qb_attr_code code_eq_orp_is_nesn = QB_CODE(0, 31, 1); ++static struct qb_attr_code code_eq_orp_nlis = QB_CODE(0, 30, 1); ++static struct qb_attr_code code_eq_orp_seqnum = QB_CODE(0, 16, 14); ++static struct qb_attr_code code_eq_opr_id = QB_CODE(1, 0, 16); ++static struct qb_attr_code code_eq_tgt_id = QB_CODE(2, 0, 24); ++/* static struct qb_attr_code code_eq_tag = QB_CODE(3, 0, 32); */ ++static struct qb_attr_code code_eq_qd_en = QB_CODE(0, 4, 1); ++static struct qb_attr_code code_eq_qd_bin = QB_CODE(4, 0, 16); ++static struct qb_attr_code code_eq_qd_pri = QB_CODE(4, 16, 4); ++static struct qb_attr_code code_eq_rsp_stash = QB_CODE(5, 16, 1); ++static struct qb_attr_code code_eq_rsp_id = QB_CODE(5, 24, 8); ++static struct qb_attr_code code_eq_rsp_lo = QB_CODE(6, 0, 32); ++ ++enum qbman_eq_cmd_e { ++ /* No enqueue, primarily for plugging ORP gaps for dropped frames */ ++ qbman_eq_cmd_empty, ++ /* DMA an enqueue response once complete */ ++ qbman_eq_cmd_respond, ++ /* DMA an enqueue response only if the enqueue fails */ ++ qbman_eq_cmd_respond_reject ++}; ++ ++void qbman_eq_desc_clear(struct qbman_eq_desc *d) ++{ ++ memset(d, 0, sizeof(*d)); ++} ++ ++void qbman_eq_desc_set_no_orp(struct qbman_eq_desc *d, int respond_success) ++{ ++ uint32_t *cl = qb_cl(d); ++ ++ qb_attr_code_encode(&code_eq_orp_en, cl, 0); ++ qb_attr_code_encode(&code_eq_cmd, cl, ++ respond_success ? qbman_eq_cmd_respond : ++ qbman_eq_cmd_respond_reject); ++} ++ ++void qbman_eq_desc_set_orp(struct qbman_eq_desc *d, int respond_success, ++ uint32_t opr_id, uint32_t seqnum, int incomplete) ++{ ++ uint32_t *cl = qb_cl(d); ++ ++ qb_attr_code_encode(&code_eq_orp_en, cl, 1); ++ qb_attr_code_encode(&code_eq_cmd, cl, ++ respond_success ? qbman_eq_cmd_respond : ++ qbman_eq_cmd_respond_reject); ++ qb_attr_code_encode(&code_eq_opr_id, cl, opr_id); ++ qb_attr_code_encode(&code_eq_orp_seqnum, cl, seqnum); ++ qb_attr_code_encode(&code_eq_orp_nlis, cl, !!incomplete); ++} ++ ++void qbman_eq_desc_set_orp_hole(struct qbman_eq_desc *d, uint32_t opr_id, ++ uint32_t seqnum) ++{ ++ uint32_t *cl = qb_cl(d); ++ ++ qb_attr_code_encode(&code_eq_orp_en, cl, 1); ++ qb_attr_code_encode(&code_eq_cmd, cl, qbman_eq_cmd_empty); ++ qb_attr_code_encode(&code_eq_opr_id, cl, opr_id); ++ qb_attr_code_encode(&code_eq_orp_seqnum, cl, seqnum); ++ qb_attr_code_encode(&code_eq_orp_nlis, cl, 0); ++ qb_attr_code_encode(&code_eq_orp_is_nesn, cl, 0); ++} ++ ++void qbman_eq_desc_set_orp_nesn(struct qbman_eq_desc *d, uint32_t opr_id, ++ uint32_t seqnum) ++{ ++ uint32_t *cl = qb_cl(d); ++ ++ qb_attr_code_encode(&code_eq_orp_en, cl, 1); ++ qb_attr_code_encode(&code_eq_cmd, cl, qbman_eq_cmd_empty); ++ qb_attr_code_encode(&code_eq_opr_id, cl, opr_id); ++ qb_attr_code_encode(&code_eq_orp_seqnum, cl, seqnum); ++ qb_attr_code_encode(&code_eq_orp_nlis, cl, 0); ++ qb_attr_code_encode(&code_eq_orp_is_nesn, cl, 1); ++} ++ ++void qbman_eq_desc_set_response(struct qbman_eq_desc *d, ++ dma_addr_t storage_phys, ++ int stash) ++{ ++ uint32_t *cl = qb_cl(d); ++ ++ qb_attr_code_encode_64(&code_eq_rsp_lo, (uint64_t *)cl, storage_phys); ++ qb_attr_code_encode(&code_eq_rsp_stash, cl, !!stash); ++} ++ ++void qbman_eq_desc_set_token(struct qbman_eq_desc *d, uint8_t token) ++{ ++ uint32_t *cl = qb_cl(d); ++ ++ qb_attr_code_encode(&code_eq_rsp_id, cl, (uint32_t)token); ++} ++ ++void qbman_eq_desc_set_fq(struct qbman_eq_desc *d, uint32_t fqid) ++{ ++ uint32_t *cl = qb_cl(d); ++ ++ qb_attr_code_encode(&code_eq_qd_en, cl, 0); ++ qb_attr_code_encode(&code_eq_tgt_id, cl, fqid); ++} ++ ++void qbman_eq_desc_set_qd(struct qbman_eq_desc *d, uint32_t qdid, ++ uint32_t qd_bin, uint32_t qd_prio) ++{ ++ uint32_t *cl = qb_cl(d); ++ ++ qb_attr_code_encode(&code_eq_qd_en, cl, 1); ++ qb_attr_code_encode(&code_eq_tgt_id, cl, qdid); ++ qb_attr_code_encode(&code_eq_qd_bin, cl, qd_bin); ++ qb_attr_code_encode(&code_eq_qd_pri, cl, qd_prio); ++} ++ ++void qbman_eq_desc_set_eqdi(struct qbman_eq_desc *d, int enable) ++{ ++ uint32_t *cl = qb_cl(d); ++ ++ qb_attr_code_encode(&code_eq_eqdi, cl, !!enable); ++} ++ ++void qbman_eq_desc_set_dca(struct qbman_eq_desc *d, int enable, ++ uint32_t dqrr_idx, int park) ++{ ++ uint32_t *cl = qb_cl(d); ++ ++ qb_attr_code_encode(&code_eq_dca_en, cl, !!enable); ++ if (enable) { ++ qb_attr_code_encode(&code_eq_dca_pk, cl, !!park); ++ qb_attr_code_encode(&code_eq_dca_idx, cl, dqrr_idx); ++ } ++} ++ ++#define EQAR_IDX(eqar) ((eqar) & 0x7) ++#define EQAR_VB(eqar) ((eqar) & 0x80) ++#define EQAR_SUCCESS(eqar) ((eqar) & 0x100) ++static int qbman_swp_enqueue_array_mode(struct qbman_swp *s, ++ const struct qbman_eq_desc *d, ++ const struct qbman_fd *fd) ++{ ++ uint32_t *p; ++ const uint32_t *cl = qb_cl(d); ++ uint32_t eqar = qbman_cinh_read(&s->sys, QBMAN_CINH_SWP_EQAR); ++ ++ pr_debug("EQAR=%08x\n", eqar); ++ if (!EQAR_SUCCESS(eqar)) ++ return -EBUSY; ++ p = qbman_cena_write_start_wo_shadow(&s->sys, ++ QBMAN_CENA_SWP_EQCR(EQAR_IDX(eqar))); ++ word_copy(&p[1], &cl[1], 7); ++ word_copy(&p[8], fd, sizeof(*fd) >> 2); ++ /* Set the verb byte, have to substitute in the valid-bit */ ++ lwsync(); ++ p[0] = cl[0] | EQAR_VB(eqar); ++ qbman_cena_write_complete_wo_shadow(&s->sys, ++ QBMAN_CENA_SWP_EQCR(EQAR_IDX(eqar))); ++ return 0; ++} ++ ++static int qbman_swp_enqueue_ring_mode(struct qbman_swp *s, ++ const struct qbman_eq_desc *d, ++ const struct qbman_fd *fd) ++{ ++ uint32_t *p; ++ const uint32_t *cl = qb_cl(d); ++ uint32_t eqcr_ci; ++ uint8_t diff; ++ ++ if (!s->eqcr.available) { ++ eqcr_ci = s->eqcr.ci; ++ s->eqcr.ci = qbman_cena_read_reg(&s->sys, ++ QBMAN_CENA_SWP_EQCR_CI) & 0xF; ++ diff = qm_cyc_diff(QBMAN_EQCR_SIZE, ++ eqcr_ci, s->eqcr.ci); ++ s->eqcr.available += diff; ++ if (!diff) ++ return -EBUSY; ++ } ++ ++ p = qbman_cena_write_start_wo_shadow(&s->sys, ++ QBMAN_CENA_SWP_EQCR(s->eqcr.pi & 7)); ++ word_copy(&p[1], &cl[1], 7); ++ word_copy(&p[8], fd, sizeof(*fd) >> 2); ++ lwsync(); ++ /* Set the verb byte, have to substitute in the valid-bit */ ++ p[0] = cl[0] | s->eqcr.pi_vb; ++ qbman_cena_write_complete_wo_shadow(&s->sys, ++ QBMAN_CENA_SWP_EQCR(s->eqcr.pi & 7)); ++ s->eqcr.pi++; ++ s->eqcr.pi &= 0xF; ++ s->eqcr.available--; ++ if (!(s->eqcr.pi & 7)) ++ s->eqcr.pi_vb ^= QB_VALID_BIT; ++ return 0; ++} ++ ++int qbman_swp_fill_ring(struct qbman_swp *s, ++ const struct qbman_eq_desc *d, ++ const struct qbman_fd *fd, ++ __attribute__((unused)) uint8_t burst_index) ++{ ++ uint32_t *p; ++ const uint32_t *cl = qb_cl(d); ++ uint32_t eqcr_ci; ++ uint8_t diff; ++ ++ if (!s->eqcr.available) { ++ eqcr_ci = s->eqcr.ci; ++ s->eqcr.ci = qbman_cena_read_reg(&s->sys, ++ QBMAN_CENA_SWP_EQCR_CI) & 0xF; ++ diff = qm_cyc_diff(QBMAN_EQCR_SIZE, ++ eqcr_ci, s->eqcr.ci); ++ s->eqcr.available += diff; ++ if (!diff) ++ return -EBUSY; ++ ++ } ++ p = qbman_cena_write_start_wo_shadow(&s->sys, ++ QBMAN_CENA_SWP_EQCR((s->eqcr.pi/* +burst_index */) & 7)); ++ /* word_copy(&p[1], &cl[1], 7); */ ++ memcpy(&p[1], &cl[1], 7*4); ++ /* word_copy(&p[8], fd, sizeof(*fd) >> 2); */ ++ memcpy(&p[8], fd, sizeof(struct qbman_fd)); ++ ++ /* lwsync(); */ ++ p[0] = cl[0] | s->eqcr.pi_vb; ++ ++ s->eqcr.pi++; ++ s->eqcr.pi &= 0xF; ++ s->eqcr.available--; ++ if (!(s->eqcr.pi & 7)) ++ s->eqcr.pi_vb ^= QB_VALID_BIT; ++ ++ return 0; ++} ++ ++int qbman_swp_flush_ring(struct qbman_swp *s) ++{ ++ void *ptr = s->sys.addr_cena; ++ ++ dcbf((uint64_t)ptr); ++ dcbf((uint64_t)ptr + 0x40); ++ dcbf((uint64_t)ptr + 0x80); ++ dcbf((uint64_t)ptr + 0xc0); ++ dcbf((uint64_t)ptr + 0x100); ++ dcbf((uint64_t)ptr + 0x140); ++ dcbf((uint64_t)ptr + 0x180); ++ dcbf((uint64_t)ptr + 0x1c0); ++ ++ return 0; ++} ++ ++void qbman_sync(void) ++{ ++ lwsync(); ++} ++ ++int qbman_swp_enqueue(struct qbman_swp *s, const struct qbman_eq_desc *d, ++ const struct qbman_fd *fd) ++{ ++ if (s->sys.eqcr_mode == qman_eqcr_vb_array) ++ return qbman_swp_enqueue_array_mode(s, d, fd); ++ else /* Use ring mode by default */ ++ return qbman_swp_enqueue_ring_mode(s, d, fd); ++} ++ ++/*************************/ ++/* Static (push) dequeue */ ++/*************************/ ++ ++void qbman_swp_push_get(struct qbman_swp *s, uint8_t channel_idx, int *enabled) ++{ ++ struct qb_attr_code code = CODE_SDQCR_DQSRC(channel_idx); ++ ++ BUG_ON(channel_idx > 15); ++ *enabled = (int)qb_attr_code_decode(&code, &s->sdq); ++} ++ ++void qbman_swp_push_set(struct qbman_swp *s, uint8_t channel_idx, int enable) ++{ ++ uint16_t dqsrc; ++ struct qb_attr_code code = CODE_SDQCR_DQSRC(channel_idx); ++ ++ BUG_ON(channel_idx > 15); ++ qb_attr_code_encode(&code, &s->sdq, !!enable); ++ /* Read make the complete src map. If no channels are enabled ++ the SDQCR must be 0 or else QMan will assert errors */ ++ dqsrc = (uint16_t)qb_attr_code_decode(&code_sdqcr_dqsrc, &s->sdq); ++ if (dqsrc != 0) ++ qbman_cinh_write(&s->sys, QBMAN_CINH_SWP_SDQCR, s->sdq); ++ else ++ qbman_cinh_write(&s->sys, QBMAN_CINH_SWP_SDQCR, 0); ++} ++ ++/***************************/ ++/* Volatile (pull) dequeue */ ++/***************************/ ++ ++/* These should be const, eventually */ ++static struct qb_attr_code code_pull_dct = QB_CODE(0, 0, 2); ++static struct qb_attr_code code_pull_dt = QB_CODE(0, 2, 2); ++static struct qb_attr_code code_pull_rls = QB_CODE(0, 4, 1); ++static struct qb_attr_code code_pull_stash = QB_CODE(0, 5, 1); ++static struct qb_attr_code code_pull_numframes = QB_CODE(0, 8, 4); ++static struct qb_attr_code code_pull_token = QB_CODE(0, 16, 8); ++static struct qb_attr_code code_pull_dqsource = QB_CODE(1, 0, 24); ++static struct qb_attr_code code_pull_rsp_lo = QB_CODE(2, 0, 32); ++ ++enum qb_pull_dt_e { ++ qb_pull_dt_channel, ++ qb_pull_dt_workqueue, ++ qb_pull_dt_framequeue ++}; ++ ++void qbman_pull_desc_clear(struct qbman_pull_desc *d) ++{ ++ memset(d, 0, sizeof(*d)); ++} ++ ++void qbman_pull_desc_set_storage(struct qbman_pull_desc *d, ++ struct qbman_result *storage, ++ dma_addr_t storage_phys, ++ int stash) ++{ ++ uint32_t *cl = qb_cl(d); ++ /* Squiggle the pointer 'storage' into the extra 2 words of the ++ * descriptor (which aren't copied to the hw command) */ ++ *(void **)&cl[4] = storage; ++ if (!storage) { ++ qb_attr_code_encode(&code_pull_rls, cl, 0); ++ return; ++ } ++ qb_attr_code_encode(&code_pull_rls, cl, 1); ++ qb_attr_code_encode(&code_pull_stash, cl, !!stash); ++ qb_attr_code_encode_64(&code_pull_rsp_lo, (uint64_t *)cl, storage_phys); ++} ++ ++void qbman_pull_desc_set_numframes(struct qbman_pull_desc *d, uint8_t numframes) ++{ ++ uint32_t *cl = qb_cl(d); ++ ++ BUG_ON(!numframes || (numframes > 16)); ++ qb_attr_code_encode(&code_pull_numframes, cl, ++ (uint32_t)(numframes - 1)); ++} ++ ++void qbman_pull_desc_set_token(struct qbman_pull_desc *d, uint8_t token) ++{ ++ uint32_t *cl = qb_cl(d); ++ ++ qb_attr_code_encode(&code_pull_token, cl, token); ++} ++ ++void qbman_pull_desc_set_fq(struct qbman_pull_desc *d, uint32_t fqid) ++{ ++ uint32_t *cl = qb_cl(d); ++ ++ qb_attr_code_encode(&code_pull_dct, cl, 1); ++ qb_attr_code_encode(&code_pull_dt, cl, qb_pull_dt_framequeue); ++ qb_attr_code_encode(&code_pull_dqsource, cl, fqid); ++} ++ ++void qbman_pull_desc_set_wq(struct qbman_pull_desc *d, uint32_t wqid, ++ enum qbman_pull_type_e dct) ++{ ++ uint32_t *cl = qb_cl(d); ++ ++ qb_attr_code_encode(&code_pull_dct, cl, dct); ++ qb_attr_code_encode(&code_pull_dt, cl, qb_pull_dt_workqueue); ++ qb_attr_code_encode(&code_pull_dqsource, cl, wqid); ++} ++ ++void qbman_pull_desc_set_channel(struct qbman_pull_desc *d, uint32_t chid, ++ enum qbman_pull_type_e dct) ++{ ++ uint32_t *cl = qb_cl(d); ++ ++ qb_attr_code_encode(&code_pull_dct, cl, dct); ++ qb_attr_code_encode(&code_pull_dt, cl, qb_pull_dt_channel); ++ qb_attr_code_encode(&code_pull_dqsource, cl, chid); ++} ++ ++int qbman_swp_pull(struct qbman_swp *s, struct qbman_pull_desc *d) ++{ ++ uint32_t *p; ++ uint32_t *cl = qb_cl(d); ++ ++ if (!atomic_dec_and_test(&s->vdq.busy)) { ++ atomic_inc(&s->vdq.busy); ++ return -EBUSY; ++ } ++ s->vdq.storage = *(void **)&cl[4]; ++ qb_attr_code_encode(&code_pull_token, cl, 1); ++ p = qbman_cena_write_start_wo_shadow(&s->sys, QBMAN_CENA_SWP_VDQCR); ++ word_copy(&p[1], &cl[1], 3); ++ /* Set the verb byte, have to substitute in the valid-bit */ ++ lwsync(); ++ p[0] = cl[0] | s->vdq.valid_bit; ++ s->vdq.valid_bit ^= QB_VALID_BIT; ++ qbman_cena_write_complete_wo_shadow(&s->sys, QBMAN_CENA_SWP_VDQCR); ++ return 0; ++} ++ ++/****************/ ++/* Polling DQRR */ ++/****************/ ++ ++static struct qb_attr_code code_dqrr_verb = QB_CODE(0, 0, 8); ++static struct qb_attr_code code_dqrr_response = QB_CODE(0, 0, 7); ++static struct qb_attr_code code_dqrr_stat = QB_CODE(0, 8, 8); ++static struct qb_attr_code code_dqrr_seqnum = QB_CODE(0, 16, 14); ++static struct qb_attr_code code_dqrr_odpid = QB_CODE(1, 0, 16); ++/* static struct qb_attr_code code_dqrr_tok = QB_CODE(1, 24, 8); */ ++static struct qb_attr_code code_dqrr_fqid = QB_CODE(2, 0, 24); ++static struct qb_attr_code code_dqrr_byte_count = QB_CODE(4, 0, 32); ++static struct qb_attr_code code_dqrr_frame_count = QB_CODE(5, 0, 24); ++static struct qb_attr_code code_dqrr_ctx_lo = QB_CODE(6, 0, 32); ++ ++#define QBMAN_RESULT_DQ 0x60 ++#define QBMAN_RESULT_FQRN 0x21 ++#define QBMAN_RESULT_FQRNI 0x22 ++#define QBMAN_RESULT_FQPN 0x24 ++#define QBMAN_RESULT_FQDAN 0x25 ++#define QBMAN_RESULT_CDAN 0x26 ++#define QBMAN_RESULT_CSCN_MEM 0x27 ++#define QBMAN_RESULT_CGCU 0x28 ++#define QBMAN_RESULT_BPSCN 0x29 ++#define QBMAN_RESULT_CSCN_WQ 0x2a ++ ++static struct qb_attr_code code_dqpi_pi = QB_CODE(0, 0, 4); ++ ++/* NULL return if there are no unconsumed DQRR entries. Returns a DQRR entry ++ * only once, so repeated calls can return a sequence of DQRR entries, without ++ * requiring they be consumed immediately or in any particular order. */ ++const struct qbman_result *qbman_swp_dqrr_next(struct qbman_swp *s) ++{ ++ uint32_t verb; ++ uint32_t response_verb; ++ uint32_t flags; ++ const struct qbman_result *dq; ++ const uint32_t *p; ++ ++ /* Before using valid-bit to detect if something is there, we have to ++ * handle the case of the DQRR reset bug... */ ++ if (unlikely(s->dqrr.reset_bug)) { ++ /* We pick up new entries by cache-inhibited producer index, ++ * which means that a non-coherent mapping would require us to ++ * invalidate and read *only* once that PI has indicated that ++ * there's an entry here. The first trip around the DQRR ring ++ * will be much less efficient than all subsequent trips around ++ * it... ++ */ ++ uint32_t dqpi = qbman_cinh_read(&s->sys, QBMAN_CINH_SWP_DQPI); ++ uint32_t pi = qb_attr_code_decode(&code_dqpi_pi, &dqpi); ++ /* there are new entries iff pi != next_idx */ ++ if (pi == s->dqrr.next_idx) ++ return NULL; ++ /* if next_idx is/was the last ring index, and 'pi' is ++ * different, we can disable the workaround as all the ring ++ * entries have now been DMA'd to so valid-bit checking is ++ * repaired. Note: this logic needs to be based on next_idx ++ * (which increments one at a time), rather than on pi (which ++ * can burst and wrap-around between our snapshots of it). ++ */ ++ BUG_ON((s->dqrr.dqrr_size - 1) < 0); ++ if (s->dqrr.next_idx == (s->dqrr.dqrr_size - 1u)) { ++ pr_debug("DEBUG: next_idx=%d, pi=%d, clear reset bug\n", ++ s->dqrr.next_idx, pi); ++ s->dqrr.reset_bug = 0; ++ } ++ qbman_cena_invalidate_prefetch(&s->sys, ++ QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)); ++ } ++ dq = qbman_cena_read_wo_shadow(&s->sys, ++ QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)); ++ p = qb_cl(dq); ++ verb = qb_attr_code_decode(&code_dqrr_verb, p); ++ /* If the valid-bit isn't of the expected polarity, nothing there. Note, ++ * in the DQRR reset bug workaround, we shouldn't need to skip these ++ * check, because we've already determined that a new entry is available ++ * and we've invalidated the cacheline before reading it, so the ++ * valid-bit behaviour is repaired and should tell us what we already ++ * knew from reading PI. ++ */ ++ if ((verb & QB_VALID_BIT) != s->dqrr.valid_bit) ++ return NULL; ++ ++ /* There's something there. Move "next_idx" attention to the next ring ++ * entry (and prefetch it) before returning what we found. */ ++ s->dqrr.next_idx++; ++ if (s->dqrr.next_idx == s->dqrr.dqrr_size) { ++ s->dqrr.next_idx = 0; ++ s->dqrr.valid_bit ^= QB_VALID_BIT; ++ } ++ /* If this is the final response to a volatile dequeue command ++ indicate that the vdq is no longer busy */ ++ flags = qbman_result_DQ_flags(dq); ++ response_verb = qb_attr_code_decode(&code_dqrr_response, &verb); ++ if ((response_verb == QBMAN_RESULT_DQ) && ++ (flags & QBMAN_DQ_STAT_VOLATILE) && ++ (flags & QBMAN_DQ_STAT_EXPIRED)) ++ atomic_inc(&s->vdq.busy); ++ ++ return dq; ++} ++ ++/* Consume DQRR entries previously returned from qbman_swp_dqrr_next(). */ ++void qbman_swp_dqrr_consume(struct qbman_swp *s, ++ const struct qbman_result *dq) ++{ ++ qbman_cinh_write(&s->sys, QBMAN_CINH_SWP_DCAP, QBMAN_IDX_FROM_DQRR(dq)); ++} ++ ++/*********************************/ ++/* Polling user-provided storage */ ++/*********************************/ ++ ++int qbman_result_has_new_result(__attribute__((unused)) struct qbman_swp *s, ++ const struct qbman_result *dq) ++{ ++ /* To avoid converting the little-endian DQ entry to host-endian prior ++ * to us knowing whether there is a valid entry or not (and run the ++ * risk of corrupting the incoming hardware LE write), we detect in ++ * hardware endianness rather than host. This means we need a different ++ * "code" depending on whether we are BE or LE in software, which is ++ * where DQRR_TOK_OFFSET comes in... */ ++ static struct qb_attr_code code_dqrr_tok_detect = ++ QB_CODE(0, DQRR_TOK_OFFSET, 8); ++ /* The user trying to poll for a result treats "dq" as const. It is ++ * however the same address that was provided to us non-const in the ++ * first place, for directing hardware DMA to. So we can cast away the ++ * const because it is mutable from our perspective. */ ++ uint32_t *p = (uint32_t *)(unsigned long)qb_cl(dq); ++ uint32_t token; ++ ++ token = qb_attr_code_decode(&code_dqrr_tok_detect, &p[1]); ++ if (token != 1) ++ return 0; ++ qb_attr_code_encode(&code_dqrr_tok_detect, &p[1], 0); ++ ++ /* Only now do we convert from hardware to host endianness. Also, as we ++ * are returning success, the user has promised not to call us again, so ++ * there's no risk of us converting the endianness twice... */ ++ make_le32_n(p, 16); ++ return 1; ++} ++ ++int qbman_check_command_complete(struct qbman_swp *s, ++ const struct qbman_result *dq) ++{ ++ /* To avoid converting the little-endian DQ entry to host-endian prior ++ * to us knowing whether there is a valid entry or not (and run the ++ * risk of corrupting the incoming hardware LE write), we detect in ++ * hardware endianness rather than host. This means we need a different ++ * "code" depending on whether we are BE or LE in software, which is ++ * where DQRR_TOK_OFFSET comes in... */ ++ static struct qb_attr_code code_dqrr_tok_detect = ++ QB_CODE(0, DQRR_TOK_OFFSET, 8); ++ /* The user trying to poll for a result treats "dq" as const. It is ++ * however the same address that was provided to us non-const in the ++ * first place, for directing hardware DMA to. So we can cast away the ++ * const because it is mutable from our perspective. */ ++ uint32_t *p = (uint32_t *)(unsigned long)qb_cl(dq); ++ uint32_t token; ++ ++ token = qb_attr_code_decode(&code_dqrr_tok_detect, &p[1]); ++ if (token != 1) ++ return 0; ++ /*When token is set it indicates that VDQ command has been fetched by qbman and ++ *is working on it. It is safe for software to issue another VDQ command, so ++ *incrementing the busy variable.*/ ++ if (s->vdq.storage == dq) { ++ s->vdq.storage = NULL; ++ atomic_inc(&s->vdq.busy); ++ } ++ return 1; ++} ++ ++/********************************/ ++/* Categorising qbman results */ ++/********************************/ ++ ++static struct qb_attr_code code_result_in_mem = ++ QB_CODE(0, QBMAN_RESULT_VERB_OFFSET_IN_MEM, 7); ++ ++static inline int __qbman_result_is_x(const struct qbman_result *dq, ++ uint32_t x) ++{ ++ const uint32_t *p = qb_cl(dq); ++ uint32_t response_verb = qb_attr_code_decode(&code_dqrr_response, p); ++ ++ return (response_verb == x); ++} ++ ++static inline int __qbman_result_is_x_in_mem(const struct qbman_result *dq, ++ uint32_t x) ++{ ++ const uint32_t *p = qb_cl(dq); ++ uint32_t response_verb = qb_attr_code_decode(&code_result_in_mem, p); ++ ++ return (response_verb == x); ++} ++ ++int qbman_result_is_DQ(const struct qbman_result *dq) ++{ ++ return __qbman_result_is_x(dq, QBMAN_RESULT_DQ); ++} ++ ++int qbman_result_is_FQDAN(const struct qbman_result *dq) ++{ ++ return __qbman_result_is_x(dq, QBMAN_RESULT_FQDAN); ++} ++ ++int qbman_result_is_CDAN(const struct qbman_result *dq) ++{ ++ return __qbman_result_is_x(dq, QBMAN_RESULT_CDAN); ++} ++ ++int qbman_result_is_CSCN(const struct qbman_result *dq) ++{ ++ return __qbman_result_is_x_in_mem(dq, QBMAN_RESULT_CSCN_MEM) || ++ __qbman_result_is_x(dq, QBMAN_RESULT_CSCN_WQ); ++} ++ ++int qbman_result_is_BPSCN(const struct qbman_result *dq) ++{ ++ return __qbman_result_is_x_in_mem(dq, QBMAN_RESULT_BPSCN); ++} ++ ++int qbman_result_is_CGCU(const struct qbman_result *dq) ++{ ++ return __qbman_result_is_x_in_mem(dq, QBMAN_RESULT_CGCU); ++} ++ ++int qbman_result_is_FQRN(const struct qbman_result *dq) ++{ ++ return __qbman_result_is_x_in_mem(dq, QBMAN_RESULT_FQRN); ++} ++ ++int qbman_result_is_FQRNI(const struct qbman_result *dq) ++{ ++ return __qbman_result_is_x_in_mem(dq, QBMAN_RESULT_FQRNI); ++} ++ ++int qbman_result_is_FQPN(const struct qbman_result *dq) ++{ ++ return __qbman_result_is_x(dq, QBMAN_RESULT_FQPN); ++} ++ ++/*********************************/ ++/* Parsing frame dequeue results */ ++/*********************************/ ++ ++/* These APIs assume qbman_result_is_DQ() is TRUE */ ++ ++uint32_t qbman_result_DQ_flags(const struct qbman_result *dq) ++{ ++ const uint32_t *p = qb_cl(dq); ++ ++ return qb_attr_code_decode(&code_dqrr_stat, p); ++} ++ ++uint16_t qbman_result_DQ_seqnum(const struct qbman_result *dq) ++{ ++ const uint32_t *p = qb_cl(dq); ++ ++ return (uint16_t)qb_attr_code_decode(&code_dqrr_seqnum, p); ++} ++ ++uint16_t qbman_result_DQ_odpid(const struct qbman_result *dq) ++{ ++ const uint32_t *p = qb_cl(dq); ++ ++ return (uint16_t)qb_attr_code_decode(&code_dqrr_odpid, p); ++} ++ ++uint32_t qbman_result_DQ_fqid(const struct qbman_result *dq) ++{ ++ const uint32_t *p = qb_cl(dq); ++ ++ return qb_attr_code_decode(&code_dqrr_fqid, p); ++} ++ ++uint32_t qbman_result_DQ_byte_count(const struct qbman_result *dq) ++{ ++ const uint32_t *p = qb_cl(dq); ++ ++ return qb_attr_code_decode(&code_dqrr_byte_count, p); ++} ++ ++uint32_t qbman_result_DQ_frame_count(const struct qbman_result *dq) ++{ ++ const uint32_t *p = qb_cl(dq); ++ ++ return qb_attr_code_decode(&code_dqrr_frame_count, p); ++} ++ ++uint64_t qbman_result_DQ_fqd_ctx(const struct qbman_result *dq) ++{ ++ const uint64_t *p = (const uint64_t *)qb_cl(dq); ++ ++ return qb_attr_code_decode_64(&code_dqrr_ctx_lo, p); ++} ++ ++const struct qbman_fd *qbman_result_DQ_fd(const struct qbman_result *dq) ++{ ++ const uint32_t *p = qb_cl(dq); ++ ++ return (const struct qbman_fd *)&p[8]; ++} ++ ++/**************************************/ ++/* Parsing state-change notifications */ ++/**************************************/ ++ ++static struct qb_attr_code code_scn_state = QB_CODE(0, 16, 8); ++static struct qb_attr_code code_scn_rid = QB_CODE(1, 0, 24); ++static struct qb_attr_code code_scn_state_in_mem = ++ QB_CODE(0, SCN_STATE_OFFSET_IN_MEM, 8); ++static struct qb_attr_code code_scn_rid_in_mem = ++ QB_CODE(1, SCN_RID_OFFSET_IN_MEM, 24); ++static struct qb_attr_code code_scn_ctx_lo = QB_CODE(2, 0, 32); ++ ++uint8_t qbman_result_SCN_state(const struct qbman_result *scn) ++{ ++ const uint32_t *p = qb_cl(scn); ++ ++ return (uint8_t)qb_attr_code_decode(&code_scn_state, p); ++} ++ ++uint32_t qbman_result_SCN_rid(const struct qbman_result *scn) ++{ ++ const uint32_t *p = qb_cl(scn); ++ ++ return qb_attr_code_decode(&code_scn_rid, p); ++} ++ ++uint64_t qbman_result_SCN_ctx(const struct qbman_result *scn) ++{ ++ const uint64_t *p = (const uint64_t *)qb_cl(scn); ++ ++ return qb_attr_code_decode_64(&code_scn_ctx_lo, p); ++} ++ ++uint8_t qbman_result_SCN_state_in_mem(const struct qbman_result *scn) ++{ ++ const uint32_t *p = qb_cl(scn); ++ ++ return (uint8_t)qb_attr_code_decode(&code_scn_state_in_mem, p); ++} ++ ++uint32_t qbman_result_SCN_rid_in_mem(const struct qbman_result *scn) ++{ ++ const uint32_t *p = qb_cl(scn); ++ uint32_t result_rid; ++ ++ result_rid = qb_attr_code_decode(&code_scn_rid_in_mem, p); ++ return make_le24(result_rid); ++} ++ ++/*****************/ ++/* Parsing BPSCN */ ++/*****************/ ++uint16_t qbman_result_bpscn_bpid(const struct qbman_result *scn) ++{ ++ return (uint16_t)qbman_result_SCN_rid_in_mem(scn) & 0x3FFF; ++} ++ ++int qbman_result_bpscn_has_free_bufs(const struct qbman_result *scn) ++{ ++ return !(int)(qbman_result_SCN_state_in_mem(scn) & 0x1); ++} ++ ++int qbman_result_bpscn_is_depleted(const struct qbman_result *scn) ++{ ++ return (int)(qbman_result_SCN_state_in_mem(scn) & 0x2); ++} ++ ++int qbman_result_bpscn_is_surplus(const struct qbman_result *scn) ++{ ++ return (int)(qbman_result_SCN_state_in_mem(scn) & 0x4); ++} ++ ++uint64_t qbman_result_bpscn_ctx(const struct qbman_result *scn) ++{ ++ uint64_t ctx; ++ uint32_t ctx_hi, ctx_lo; ++ ++ ctx = qbman_result_SCN_ctx(scn); ++ ctx_hi = upper32(ctx); ++ ctx_lo = lower32(ctx); ++ return ((uint64_t)make_le32(ctx_hi) << 32 | ++ (uint64_t)make_le32(ctx_lo)); ++} ++ ++/*****************/ ++/* Parsing CGCU */ ++/*****************/ ++uint16_t qbman_result_cgcu_cgid(const struct qbman_result *scn) ++{ ++ return (uint16_t)qbman_result_SCN_rid_in_mem(scn) & 0xFFFF; ++} ++ ++uint64_t qbman_result_cgcu_icnt(const struct qbman_result *scn) ++{ ++ uint64_t ctx; ++ uint32_t ctx_hi, ctx_lo; ++ ++ ctx = qbman_result_SCN_ctx(scn); ++ ctx_hi = upper32(ctx); ++ ctx_lo = lower32(ctx); ++ return ((uint64_t)(make_le32(ctx_hi) & 0xFF) << 32) | ++ (uint64_t)make_le32(ctx_lo); ++} ++ ++/******************/ ++/* Buffer release */ ++/******************/ ++ ++/* These should be const, eventually */ ++/* static struct qb_attr_code code_release_num = QB_CODE(0, 0, 3); */ ++static struct qb_attr_code code_release_set_me = QB_CODE(0, 5, 1); ++static struct qb_attr_code code_release_rcdi = QB_CODE(0, 6, 1); ++static struct qb_attr_code code_release_bpid = QB_CODE(0, 16, 16); ++ ++void qbman_release_desc_clear(struct qbman_release_desc *d) ++{ ++ uint32_t *cl; ++ ++ memset(d, 0, sizeof(*d)); ++ cl = qb_cl(d); ++ qb_attr_code_encode(&code_release_set_me, cl, 1); ++} ++ ++void qbman_release_desc_set_bpid(struct qbman_release_desc *d, uint32_t bpid) ++{ ++ uint32_t *cl = qb_cl(d); ++ ++ qb_attr_code_encode(&code_release_bpid, cl, bpid); ++} ++ ++void qbman_release_desc_set_rcdi(struct qbman_release_desc *d, int enable) ++{ ++ uint32_t *cl = qb_cl(d); ++ ++ qb_attr_code_encode(&code_release_rcdi, cl, !!enable); ++} ++ ++#define RAR_IDX(rar) ((rar) & 0x7) ++#define RAR_VB(rar) ((rar) & 0x80) ++#define RAR_SUCCESS(rar) ((rar) & 0x100) ++ ++int qbman_swp_release(struct qbman_swp *s, const struct qbman_release_desc *d, ++ const uint64_t *buffers, unsigned int num_buffers) ++{ ++ uint32_t *p; ++ const uint32_t *cl = qb_cl(d); ++ uint32_t rar = qbman_cinh_read(&s->sys, QBMAN_CINH_SWP_RAR); ++ ++ pr_debug("RAR=%08x\n", rar); ++ if (!RAR_SUCCESS(rar)) ++ return -EBUSY; ++ BUG_ON(!num_buffers || (num_buffers > 7)); ++ /* Start the release command */ ++ p = qbman_cena_write_start_wo_shadow(&s->sys, ++ QBMAN_CENA_SWP_RCR(RAR_IDX(rar))); ++ /* Copy the caller's buffer pointers to the command */ ++ u64_to_le32_copy(&p[2], buffers, num_buffers); ++ /* Set the verb byte, have to substitute in the valid-bit and the number ++ * of buffers. */ ++ lwsync(); ++ p[0] = cl[0] | RAR_VB(rar) | num_buffers; ++ qbman_cena_write_complete_wo_shadow(&s->sys, ++ QBMAN_CENA_SWP_RCR(RAR_IDX(rar))); ++ return 0; ++} ++ ++/*******************/ ++/* Buffer acquires */ ++/*******************/ ++ ++/* These should be const, eventually */ ++static struct qb_attr_code code_acquire_bpid = QB_CODE(0, 16, 16); ++static struct qb_attr_code code_acquire_num = QB_CODE(1, 0, 3); ++static struct qb_attr_code code_acquire_r_num = QB_CODE(1, 0, 3); ++ ++int qbman_swp_acquire(struct qbman_swp *s, uint32_t bpid, uint64_t *buffers, ++ unsigned int num_buffers) ++{ ++ uint32_t *p; ++ uint32_t rslt, num; ++ ++ BUG_ON(!num_buffers || (num_buffers > 7)); ++ ++ /* Start the management command */ ++ p = qbman_swp_mc_start(s); ++ ++ if (!p) ++ return -EBUSY; ++ ++ /* Encode the caller-provided attributes */ ++ qb_attr_code_encode(&code_acquire_bpid, p, bpid); ++ qb_attr_code_encode(&code_acquire_num, p, num_buffers); ++ ++ /* Complete the management command */ ++ p = qbman_swp_mc_complete(s, p, p[0] | QBMAN_MC_ACQUIRE); ++ ++ /* Decode the outcome */ ++ rslt = qb_attr_code_decode(&code_generic_rslt, p); ++ num = qb_attr_code_decode(&code_acquire_r_num, p); ++ BUG_ON(qb_attr_code_decode(&code_generic_verb, p) != QBMAN_MC_ACQUIRE); ++ ++ /* Determine success or failure */ ++ if (unlikely(rslt != QBMAN_MC_RSLT_OK)) { ++ pr_err("Acquire buffers from BPID 0x%x failed, code=0x%02x\n", ++ bpid, rslt); ++ return -EIO; ++ } ++ BUG_ON(num > num_buffers); ++ /* Copy the acquired buffers to the caller's array */ ++ u64_from_le32_copy(buffers, &p[2], num); ++ return (int)num; ++} ++ ++/*****************/ ++/* FQ management */ ++/*****************/ ++ ++static struct qb_attr_code code_fqalt_fqid = QB_CODE(1, 0, 32); ++ ++static int qbman_swp_alt_fq_state(struct qbman_swp *s, uint32_t fqid, ++ uint8_t alt_fq_verb) ++{ ++ uint32_t *p; ++ uint32_t rslt; ++ ++ /* Start the management command */ ++ p = qbman_swp_mc_start(s); ++ if (!p) ++ return -EBUSY; ++ ++ qb_attr_code_encode(&code_fqalt_fqid, p, fqid); ++ /* Complete the management command */ ++ p = qbman_swp_mc_complete(s, p, p[0] | alt_fq_verb); ++ ++ /* Decode the outcome */ ++ rslt = qb_attr_code_decode(&code_generic_rslt, p); ++ BUG_ON(qb_attr_code_decode(&code_generic_verb, p) != alt_fq_verb); ++ ++ /* Determine success or failure */ ++ if (unlikely(rslt != QBMAN_MC_RSLT_OK)) { ++ pr_err("ALT FQID %d failed: verb = 0x%08x, code = 0x%02x\n", ++ fqid, alt_fq_verb, rslt); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++int qbman_swp_fq_schedule(struct qbman_swp *s, uint32_t fqid) ++{ ++ return qbman_swp_alt_fq_state(s, fqid, QBMAN_FQ_SCHEDULE); ++} ++ ++int qbman_swp_fq_force(struct qbman_swp *s, uint32_t fqid) ++{ ++ return qbman_swp_alt_fq_state(s, fqid, QBMAN_FQ_FORCE); ++} ++ ++int qbman_swp_fq_xon(struct qbman_swp *s, uint32_t fqid) ++{ ++ return qbman_swp_alt_fq_state(s, fqid, QBMAN_FQ_XON); ++} ++ ++int qbman_swp_fq_xoff(struct qbman_swp *s, uint32_t fqid) ++{ ++ return qbman_swp_alt_fq_state(s, fqid, QBMAN_FQ_XOFF); ++} ++ ++/**********************/ ++/* Channel management */ ++/**********************/ ++ ++static struct qb_attr_code code_cdan_cid = QB_CODE(0, 16, 12); ++static struct qb_attr_code code_cdan_we = QB_CODE(1, 0, 8); ++static struct qb_attr_code code_cdan_en = QB_CODE(1, 8, 1); ++static struct qb_attr_code code_cdan_ctx_lo = QB_CODE(2, 0, 32); ++ ++/* Hide "ICD" for now as we don't use it, don't set it, and don't test it, so it ++ * would be irresponsible to expose it. */ ++#define CODE_CDAN_WE_EN 0x1 ++#define CODE_CDAN_WE_CTX 0x4 ++ ++static int qbman_swp_CDAN_set(struct qbman_swp *s, uint16_t channelid, ++ uint8_t we_mask, uint8_t cdan_en, ++ uint64_t ctx) ++{ ++ uint32_t *p; ++ uint32_t rslt; ++ ++ /* Start the management command */ ++ p = qbman_swp_mc_start(s); ++ if (!p) ++ return -EBUSY; ++ ++ /* Encode the caller-provided attributes */ ++ qb_attr_code_encode(&code_cdan_cid, p, channelid); ++ qb_attr_code_encode(&code_cdan_we, p, we_mask); ++ qb_attr_code_encode(&code_cdan_en, p, cdan_en); ++ qb_attr_code_encode_64(&code_cdan_ctx_lo, (uint64_t *)p, ctx); ++ /* Complete the management command */ ++ p = qbman_swp_mc_complete(s, p, p[0] | QBMAN_WQCHAN_CONFIGURE); ++ ++ /* Decode the outcome */ ++ rslt = qb_attr_code_decode(&code_generic_rslt, p); ++ BUG_ON(qb_attr_code_decode(&code_generic_verb, p) ++ != QBMAN_WQCHAN_CONFIGURE); ++ ++ /* Determine success or failure */ ++ if (unlikely(rslt != QBMAN_MC_RSLT_OK)) { ++ pr_err("CDAN cQID %d failed: code = 0x%02x\n", ++ channelid, rslt); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++int qbman_swp_CDAN_set_context(struct qbman_swp *s, uint16_t channelid, ++ uint64_t ctx) ++{ ++ return qbman_swp_CDAN_set(s, channelid, ++ CODE_CDAN_WE_CTX, ++ 0, ctx); ++} ++ ++int qbman_swp_CDAN_enable(struct qbman_swp *s, uint16_t channelid) ++{ ++ return qbman_swp_CDAN_set(s, channelid, ++ CODE_CDAN_WE_EN, ++ 1, 0); ++} ++ ++int qbman_swp_CDAN_disable(struct qbman_swp *s, uint16_t channelid) ++{ ++ return qbman_swp_CDAN_set(s, channelid, ++ CODE_CDAN_WE_EN, ++ 0, 0); ++} ++ ++int qbman_swp_CDAN_set_context_enable(struct qbman_swp *s, uint16_t channelid, ++ uint64_t ctx) ++{ ++ return qbman_swp_CDAN_set(s, channelid, ++ CODE_CDAN_WE_EN | CODE_CDAN_WE_CTX, ++ 1, ctx); ++} ++ ++uint8_t qbman_get_dqrr_idx(struct qbman_result *dqrr) ++{ ++ return QBMAN_IDX_FROM_DQRR(dqrr); ++} ++ ++struct qbman_result *qbman_get_dqrr_from_idx(struct qbman_swp *s, uint8_t idx) ++{ ++ struct qbman_result *dq; ++ ++ dq = qbman_cena_read(&s->sys, QBMAN_CENA_SWP_DQRR(idx)); ++ return dq; ++} ++ ++int qbman_swp_send_multiple(struct qbman_swp *s, ++ const struct qbman_eq_desc *d, ++ const struct qbman_fd *fd, ++ int frames_to_send) ++{ ++ uint32_t *p; ++ const uint32_t *cl = qb_cl(d); ++ uint32_t eqcr_ci; ++ uint8_t diff; ++ int sent = 0; ++ int i; ++ int initial_pi = s->eqcr.pi; ++ uint64_t start_pointer; ++ ++ if (!s->eqcr.available) { ++ eqcr_ci = s->eqcr.ci; ++ s->eqcr.ci = qbman_cena_read_reg(&s->sys, ++ QBMAN_CENA_SWP_EQCR_CI) & 0xF; ++ diff = qm_cyc_diff(QBMAN_EQCR_SIZE, ++ eqcr_ci, s->eqcr.ci); ++ if (!diff) ++ goto done; ++ s->eqcr.available += diff; ++ } ++ ++ /* we are trying to send frames_to_send if we have enough space in the ring */ ++ while (s->eqcr.available && frames_to_send--) { ++ p = qbman_cena_write_start_wo_shadow_fast(&s->sys, ++ QBMAN_CENA_SWP_EQCR((initial_pi) & 7)); ++ /* Write command (except of first byte) and FD */ ++ memcpy(&p[1], &cl[1], 7*4); ++ memcpy(&p[8], &fd[sent], sizeof(struct qbman_fd)); ++ ++ initial_pi++; ++ initial_pi &= 0xF; ++ s->eqcr.available--; ++ sent++; ++ } ++ ++ done: ++ initial_pi = s->eqcr.pi; ++ lwsync(); ++ ++ /* in order for flushes to complete faster */ ++ /*For that we use a following trick: we record all lines in 32 bit word */ ++ ++ initial_pi = s->eqcr.pi; ++ for (i = 0; i < sent; i++) { ++ p = qbman_cena_write_start_wo_shadow_fast(&s->sys, ++ QBMAN_CENA_SWP_EQCR((initial_pi) & 7)); ++ ++ p[0] = cl[0] | s->eqcr.pi_vb; ++ initial_pi++; ++ initial_pi &= 0xF; ++ ++ if (!(initial_pi & 7)) ++ s->eqcr.pi_vb ^= QB_VALID_BIT; ++ } ++ ++ initial_pi = s->eqcr.pi; ++ ++ /* We need to flush all the lines but without load/store operations between them */ ++ /* We assign start_pointer before we start loop so that in loop we do not read it from memory */ ++ start_pointer = (uint64_t)s->sys.addr_cena; ++ for (i = 0; i < sent; i++) { ++ p = (uint32_t *)(start_pointer + QBMAN_CENA_SWP_EQCR(initial_pi & 7)); ++ dcbf((uint64_t)p); ++ initial_pi++; ++ initial_pi &= 0xF; ++ } ++ ++ /* Update producer index for the next call */ ++ s->eqcr.pi = initial_pi; ++ ++ return sent; ++} +diff --git a/drivers/net/dpaa2/qbman/driver/qbman_portal.h b/drivers/net/dpaa2/qbman/driver/qbman_portal.h +new file mode 100644 +index 0000000..17f1c53 +--- /dev/null ++++ b/drivers/net/dpaa2/qbman/driver/qbman_portal.h +@@ -0,0 +1,270 @@ ++/* Copyright (C) 2014 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY ++ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include "qbman_private.h" ++#include ++ ++uint32_t qman_version; ++/* All QBMan command and result structures use this "valid bit" encoding */ ++#define QB_VALID_BIT ((uint32_t)0x80) ++ ++/* Management command result codes */ ++#define QBMAN_MC_RSLT_OK 0xf0 ++ ++/* QBMan DQRR size is set at runtime in qbman_portal.c */ ++ ++#define QBMAN_EQCR_SIZE 8 ++ ++static inline u8 qm_cyc_diff(u8 ringsize, u8 first, u8 last) ++{ ++ /* 'first' is included, 'last' is excluded */ ++ if (first <= last) ++ return last - first; ++ return (2 * ringsize) + last - first; ++} ++ ++/* --------------------- */ ++/* portal data structure */ ++/* --------------------- */ ++ ++struct qbman_swp { ++ const struct qbman_swp_desc *desc; ++ /* The qbman_sys (ie. arch/OS-specific) support code can put anything it ++ * needs in here. */ ++ struct qbman_swp_sys sys; ++ /* Management commands */ ++ struct { ++#ifdef QBMAN_CHECKING ++ enum swp_mc_check { ++ swp_mc_can_start, /* call __qbman_swp_mc_start() */ ++ swp_mc_can_submit, /* call __qbman_swp_mc_submit() */ ++ swp_mc_can_poll, /* call __qbman_swp_mc_result() */ ++ } check; ++#endif ++ uint32_t valid_bit; /* 0x00 or 0x80 */ ++ } mc; ++ /* Push dequeues */ ++ uint32_t sdq; ++ /* Volatile dequeues */ ++ struct { ++ /* VDQCR supports a "1 deep pipeline", meaning that if you know ++ * the last-submitted command is already executing in the ++ * hardware (as evidenced by at least 1 valid dequeue result), ++ * you can write another dequeue command to the register, the ++ * hardware will start executing it as soon as the ++ * already-executing command terminates. (This minimises latency ++ * and stalls.) With that in mind, this "busy" variable refers ++ * to whether or not a command can be submitted, not whether or ++ * not a previously-submitted command is still executing. In ++ * other words, once proof is seen that the previously-submitted ++ * command is executing, "vdq" is no longer "busy". */ ++ atomic_t busy; ++ uint32_t valid_bit; /* 0x00 or 0x80 */ ++ /* We need to determine when vdq is no longer busy. This depends ++ * on whether the "busy" (last-submitted) dequeue command is ++ * targeting DQRR or main-memory, and detected is based on the ++ * presence of the dequeue command's "token" showing up in ++ * dequeue entries in DQRR or main-memory (respectively). */ ++ struct qbman_result *storage; /* NULL if DQRR */ ++ } vdq; ++ /* DQRR */ ++ struct { ++ uint32_t next_idx; ++ uint32_t valid_bit; ++ uint8_t dqrr_size; ++ int reset_bug; ++ } dqrr; ++ struct { ++ uint32_t pi; ++ uint32_t pi_vb; ++ uint32_t ci; ++ int available; ++ } eqcr; ++}; ++ ++/* -------------------------- */ ++/* portal management commands */ ++/* -------------------------- */ ++ ++/* Different management commands all use this common base layer of code to issue ++ * commands and poll for results. The first function returns a pointer to where ++ * the caller should fill in their MC command (though they should ignore the ++ * verb byte), the second function commits merges in the caller-supplied command ++ * verb (which should not include the valid-bit) and submits the command to ++ * hardware, and the third function checks for a completed response (returns ++ * non-NULL if only if the response is complete). */ ++void *qbman_swp_mc_start(struct qbman_swp *p); ++void qbman_swp_mc_submit(struct qbman_swp *p, void *cmd, uint32_t cmd_verb); ++void *qbman_swp_mc_result(struct qbman_swp *p); ++ ++/* Wraps up submit + poll-for-result */ ++static inline void *qbman_swp_mc_complete(struct qbman_swp *swp, void *cmd, ++ uint32_t cmd_verb) ++{ ++ int loopvar; ++ ++ qbman_swp_mc_submit(swp, cmd, cmd_verb); ++ DBG_POLL_START(loopvar); ++ do { ++ DBG_POLL_CHECK(loopvar); ++ cmd = qbman_swp_mc_result(swp); ++ } while (!cmd); ++ return cmd; ++} ++ ++/* ------------ */ ++/* qb_attr_code */ ++/* ------------ */ ++ ++/* This struct locates a sub-field within a QBMan portal (CENA) cacheline which ++ * is either serving as a configuration command or a query result. The ++ * representation is inherently little-endian, as the indexing of the words is ++ * itself little-endian in nature and DPAA2 QBMan is little endian for anything ++ * that crosses a word boundary too (64-bit fields are the obvious examples). ++ */ ++struct qb_attr_code { ++ unsigned int word; /* which uint32_t[] array member encodes the field */ ++ unsigned int lsoffset; /* encoding offset from ls-bit */ ++ unsigned int width; /* encoding width. (bool must be 1.) */ ++}; ++ ++/* Some pre-defined codes */ ++extern struct qb_attr_code code_generic_verb; ++extern struct qb_attr_code code_generic_rslt; ++ ++/* Macros to define codes */ ++#define QB_CODE(a, b, c) { a, b, c} ++#define QB_CODE_NULL \ ++ QB_CODE((unsigned int)-1, (unsigned int)-1, (unsigned int)-1) ++ ++/* Rotate a code "ms", meaning that it moves from less-significant bytes to ++ * more-significant, from less-significant words to more-significant, etc. The ++ * "ls" version does the inverse, from more-significant towards ++ * less-significant. ++ */ ++static inline void qb_attr_code_rotate_ms(struct qb_attr_code *code, ++ unsigned int bits) ++{ ++ code->lsoffset += bits; ++ while (code->lsoffset > 31) { ++ code->word++; ++ code->lsoffset -= 32; ++ } ++} ++ ++static inline void qb_attr_code_rotate_ls(struct qb_attr_code *code, ++ unsigned int bits) ++{ ++ /* Don't be fooled, this trick should work because the types are ++ * unsigned. So the case that interests the while loop (the rotate has ++ * gone too far and the word count needs to compensate for it), is ++ * manifested when lsoffset is negative. But that equates to a really ++ * large unsigned value, starting with lots of "F"s. As such, we can ++ * continue adding 32 back to it until it wraps back round above zero, ++ * to a value of 31 or less... ++ */ ++ code->lsoffset -= bits; ++ while (code->lsoffset > 31) { ++ code->word--; ++ code->lsoffset += 32; ++ } ++} ++ ++/* Implement a loop of code rotations until 'expr' evaluates to FALSE (0). */ ++#define qb_attr_code_for_ms(code, bits, expr) \ ++ for (; expr; qb_attr_code_rotate_ms(code, bits)) ++#define qb_attr_code_for_ls(code, bits, expr) \ ++ for (; expr; qb_attr_code_rotate_ls(code, bits)) ++ ++/* decode a field from a cacheline */ ++static inline uint32_t qb_attr_code_decode(const struct qb_attr_code *code, ++ const uint32_t *cacheline) ++{ ++ return d32_uint32_t(code->lsoffset, code->width, cacheline[code->word]); ++} ++ ++static inline uint64_t qb_attr_code_decode_64(const struct qb_attr_code *code, ++ const uint64_t *cacheline) ++{ ++ return cacheline[code->word / 2]; ++} ++ ++/* encode a field to a cacheline */ ++static inline void qb_attr_code_encode(const struct qb_attr_code *code, ++ uint32_t *cacheline, uint32_t val) ++{ ++ cacheline[code->word] = ++ r32_uint32_t(code->lsoffset, code->width, cacheline[code->word]) ++ | e32_uint32_t(code->lsoffset, code->width, val); ++} ++ ++static inline void qb_attr_code_encode_64(const struct qb_attr_code *code, ++ uint64_t *cacheline, uint64_t val) ++{ ++ cacheline[code->word / 2] = val; ++} ++ ++/* Small-width signed values (two's-complement) will decode into medium-width ++ * positives. (Eg. for an 8-bit signed field, which stores values from -128 to ++ * +127, a setting of -7 would appear to decode to the 32-bit unsigned value ++ * 249. Likewise -120 would decode as 136.) This function allows the caller to ++ * "re-sign" such fields to 32-bit signed. (Eg. -7, which was 249 with an 8-bit ++ * encoding, will become 0xfffffff9 if you cast the return value to uint32_t). ++ */ ++static inline int32_t qb_attr_code_makesigned(const struct qb_attr_code *code, ++ uint32_t val) ++{ ++ BUG_ON(val >= (1u << code->width)); ++ /* code->width should never exceed the width of val. If it does then a ++ * different function with larger val size must be used to translate ++ * from unsigned to signed */ ++ BUG_ON(code->width > sizeof(val) * CHAR_BIT); ++ /* If the high bit was set, it was encoding a negative */ ++ if (val >= 1u << (code->width - 1)) ++ return (int32_t)0 - (int32_t)(((uint32_t)1 << code->width) - ++ val); ++ /* Otherwise, it was encoding a positive */ ++ return (int32_t)val; ++} ++ ++/* ---------------------- */ ++/* Descriptors/cachelines */ ++/* ---------------------- */ ++ ++/* To avoid needless dynamic allocation, the driver API often gives the caller ++ * a "descriptor" type that the caller can instantiate however they like. ++ * Ultimately though, it is just a cacheline of binary storage (or something ++ * smaller when it is known that the descriptor doesn't need all 64 bytes) for ++ * holding pre-formatted pieces of hardware commands. The performance-critical ++ * code can then copy these descriptors directly into hardware command ++ * registers more efficiently than trying to construct/format commands ++ * on-the-fly. The API user sees the descriptor as an array of 32-bit words in ++ * order for the compiler to know its size, but the internal details are not ++ * exposed. The following macro is used within the driver for converting *any* ++ * descriptor pointer to a usable array pointer. The use of a macro (instead of ++ * an inline) is necessary to work with different descriptor types and to work ++ * correctly with const and non-const inputs (and similarly-qualified outputs). ++ */ ++#define qb_cl(d) (&(d)->dont_manipulate_directly[0]) +diff --git a/drivers/net/dpaa2/qbman/driver/qbman_private.h b/drivers/net/dpaa2/qbman/driver/qbman_private.h +new file mode 100644 +index 0000000..624ede1 +--- /dev/null ++++ b/drivers/net/dpaa2/qbman/driver/qbman_private.h +@@ -0,0 +1,168 @@ ++/* Copyright (C) 2014 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY ++ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++*/ ++ ++/* Perform extra checking */ ++#define QBMAN_CHECKING ++ ++/* To maximise the amount of logic that is common between the Linux driver and ++ * other targets (such as the embedded MC firmware), we pivot here between the ++ * inclusion of two platform-specific headers. ++ * ++ * The first, qbman_sys_decl.h, includes any and all required system headers as ++ * well as providing any definitions for the purposes of compatibility. The ++ * second, qbman_sys.h, is where platform-specific routines go. ++ * ++ * The point of the split is that the platform-independent code (including this ++ * header) may depend on platform-specific declarations, yet other ++ * platform-specific routines may depend on platform-independent definitions. ++ */ ++ ++#include "qbman_sys_decl.h" ++ ++/* When things go wrong, it is a convenient trick to insert a few FOO() ++ * statements in the code to trace progress. TODO: remove this once we are ++ * hacking the code less actively. ++ */ ++#define FOO() fsl_os_print("FOO: %s:%d\n", __FILE__, __LINE__) ++ ++/* Any time there is a register interface which we poll on, this provides a ++ * "break after x iterations" scheme for it. It's handy for debugging, eg. ++ * where you don't want millions of lines of log output from a polling loop ++ * that won't, because such things tend to drown out the earlier log output ++ * that might explain what caused the problem. (NB: put ";" after each macro!) ++ * TODO: we should probably remove this once we're done sanitising the ++ * simulator... ++ */ ++#define DBG_POLL_START(loopvar) (loopvar = 10) ++#define DBG_POLL_CHECK(loopvar) \ ++ do {if (!(loopvar--)) BUG_ON(NULL == "DBG_POLL_CHECK"); } while (0) ++ ++/* For CCSR or portal-CINH registers that contain fields at arbitrary offsets ++ * and widths, these macro-generated encode/decode/isolate/remove inlines can ++ * be used. ++ * ++ * Eg. to "d"ecode a 14-bit field out of a register (into a "uint16_t" type), ++ * where the field is located 3 bits "up" from the least-significant bit of the ++ * register (ie. the field location within the 32-bit register corresponds to a ++ * mask of 0x0001fff8), you would do; ++ * uint16_t field = d32_uint16_t(3, 14, reg_value); ++ * ++ * Or to "e"ncode a 1-bit boolean value (input type is "int", zero is FALSE, ++ * non-zero is TRUE, so must convert all non-zero inputs to 1, hence the "!!" ++ * operator) into a register at bit location 0x00080000 (19 bits "in" from the ++ * LS bit), do; ++ * reg_value |= e32_int(19, 1, !!field); ++ * ++ * If you wish to read-modify-write a register, such that you leave the 14-bit ++ * field as-is but have all other fields set to zero, then "i"solate the 14-bit ++ * value using; ++ * reg_value = i32_uint16_t(3, 14, reg_value); ++ * ++ * Alternatively, you could "r"emove the 1-bit boolean field (setting it to ++ * zero) but leaving all other fields as-is; ++ * reg_val = r32_int(19, 1, reg_value); ++ * ++ */ ++#define MAKE_MASK32(width) (width == 32 ? 0xffffffff : \ ++ (uint32_t)((1 << width) - 1)) ++#define DECLARE_CODEC32(t) \ ++static inline uint32_t e32_##t(uint32_t lsoffset, uint32_t width, t val) \ ++{ \ ++ BUG_ON(width > (sizeof(t) * 8)); \ ++ return ((uint32_t)val & MAKE_MASK32(width)) << lsoffset; \ ++} \ ++static inline t d32_##t(uint32_t lsoffset, uint32_t width, uint32_t val) \ ++{ \ ++ BUG_ON(width > (sizeof(t) * 8)); \ ++ return (t)((val >> lsoffset) & MAKE_MASK32(width)); \ ++} \ ++static inline uint32_t i32_##t(uint32_t lsoffset, uint32_t width, \ ++ uint32_t val) \ ++{ \ ++ BUG_ON(width > (sizeof(t) * 8)); \ ++ return e32_##t(lsoffset, width, d32_##t(lsoffset, width, val)); \ ++} \ ++static inline uint32_t r32_##t(uint32_t lsoffset, uint32_t width, \ ++ uint32_t val) \ ++{ \ ++ BUG_ON(width > (sizeof(t) * 8)); \ ++ return ~(MAKE_MASK32(width) << lsoffset) & val; \ ++} ++DECLARE_CODEC32(uint32_t) ++DECLARE_CODEC32(uint16_t) ++DECLARE_CODEC32(uint8_t) ++DECLARE_CODEC32(int) ++ ++ /*********************/ ++ /* Debugging assists */ ++ /*********************/ ++ ++static inline void __hexdump(unsigned long start, unsigned long end, ++ unsigned long p, size_t sz, const unsigned char *c) ++{ ++ while (start < end) { ++ unsigned int pos = 0; ++ char buf[64]; ++ int nl = 0; ++ ++ pos += sprintf(buf + pos, "%08lx: ", start); ++ do { ++ if ((start < p) || (start >= (p + sz))) ++ pos += sprintf(buf + pos, ".."); ++ else ++ pos += sprintf(buf + pos, "%02x", *(c++)); ++ if (!(++start & 15)) { ++ buf[pos++] = '\n'; ++ nl = 1; ++ } else { ++ nl = 0; ++ if (!(start & 1)) ++ buf[pos++] = ' '; ++ if (!(start & 3)) ++ buf[pos++] = ' '; ++ } ++ } while (start & 15); ++ if (!nl) ++ buf[pos++] = '\n'; ++ buf[pos] = '\0'; ++ pr_info("%s", buf); ++ } ++} ++ ++static inline void hexdump(const void *ptr, size_t sz) ++{ ++ unsigned long p = (unsigned long)ptr; ++ unsigned long start = p & ~(unsigned long)15; ++ unsigned long end = (p + sz + 15) & ~(unsigned long)15; ++ const unsigned char *c = ptr; ++ ++ __hexdump(start, end, p, sz, c); ++} ++ ++#define QMAN_REV_4000 0x04000000 ++#define QMAN_REV_4100 0x04010000 ++#define QMAN_REV_4101 0x04010001 ++ ++#include "qbman_sys.h" +diff --git a/drivers/net/dpaa2/qbman/driver/qbman_sys.h b/drivers/net/dpaa2/qbman/driver/qbman_sys.h +new file mode 100644 +index 0000000..a39fa71 +--- /dev/null ++++ b/drivers/net/dpaa2/qbman/driver/qbman_sys.h +@@ -0,0 +1,373 @@ ++/* Copyright (C) 2014 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY ++ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++/* qbman_sys_decl.h and qbman_sys.h are the two platform-specific files in the ++ * driver. They are only included via qbman_private.h, which is itself a ++ * platform-independent file and is included by all the other driver source. ++ * ++ * qbman_sys_decl.h is included prior to all other declarations and logic, and ++ * it exists to provide compatibility with any linux interfaces our ++ * single-source driver code is dependent on (eg. kmalloc). Ie. this file ++ * provides linux compatibility. ++ * ++ * This qbman_sys.h header, on the other hand, is included *after* any common ++ * and platform-neutral declarations and logic in qbman_private.h, and exists to ++ * implement any platform-specific logic of the qbman driver itself. Ie. it is ++ * *not* to provide linux compatibility. ++ */ ++ ++/* Trace the 3 different classes of read/write access to QBMan. #undef as ++ * required. */ ++#undef QBMAN_CCSR_TRACE ++#undef QBMAN_CINH_TRACE ++#undef QBMAN_CENA_TRACE ++ ++static inline void word_copy(void *d, const void *s, unsigned int cnt) ++{ ++ uint32_t *dd = d; ++ const uint32_t *ss = s; ++ ++ while (cnt--) ++ *(dd++) = *(ss++); ++} ++ ++/* Currently, the CENA support code expects each 32-bit word to be written in ++ * host order, and these are converted to hardware (little-endian) order on ++ * command submission. However, 64-bit quantities are must be written (and read) ++ * as two 32-bit words with the least-significant word first, irrespective of ++ * host endianness. */ ++static inline void u64_to_le32_copy(void *d, const uint64_t *s, ++ unsigned int cnt) ++{ ++ uint32_t *dd = d; ++ const uint32_t *ss = (const uint32_t *)s; ++ ++ while (cnt--) { ++ /* TBD: the toolchain was choking on the use of 64-bit types up ++ * until recently so this works entirely with 32-bit variables. ++ * When 64-bit types become usable again, investigate better ++ * ways of doing this. */ ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ++ *(dd++) = ss[1]; ++ *(dd++) = ss[0]; ++ ss += 2; ++#else ++ *(dd++) = *(ss++); ++ *(dd++) = *(ss++); ++#endif ++ } ++} ++ ++static inline void u64_from_le32_copy(uint64_t *d, const void *s, ++ unsigned int cnt) ++{ ++ const uint32_t *ss = s; ++ uint32_t *dd = (uint32_t *)d; ++ ++ while (cnt--) { ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ++ dd[1] = *(ss++); ++ dd[0] = *(ss++); ++ dd += 2; ++#else ++ *(dd++) = *(ss++); ++ *(dd++) = *(ss++); ++#endif ++ } ++} ++ ++/* Convert a host-native 32bit value into little endian */ ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ++static inline uint32_t make_le32(uint32_t val) ++{ ++ return ((val & 0xff) << 24) | ((val & 0xff00) << 8) | ++ ((val & 0xff0000) >> 8) | ((val & 0xff000000) >> 24); ++} ++ ++static inline uint32_t make_le24(uint32_t val) ++{ ++ return (((val & 0xff) << 16) | (val & 0xff00) | ++ ((val & 0xff0000) >> 16)); ++} ++#else ++#define make_le32(val) (val) ++#define make_le24(val) (val) ++#endif ++static inline void make_le32_n(uint32_t *val, unsigned int num) ++{ ++ while (num--) { ++ *val = make_le32(*val); ++ val++; ++ } ++} ++ ++ /******************/ ++ /* Portal access */ ++ /******************/ ++struct qbman_swp_sys { ++ /* On GPP, the sys support for qbman_swp is here. The CENA region isi ++ * not an mmap() of the real portal registers, but an allocated ++ * place-holder, because the actual writes/reads to/from the portal are ++ * marshalled from these allocated areas using QBMan's "MC access ++ * registers". CINH accesses are atomic so there's no need for a ++ * place-holder. */ ++ uint8_t *cena; ++ uint8_t __iomem *addr_cena; ++ uint8_t __iomem *addr_cinh; ++ uint32_t idx; ++ enum qbman_eqcr_mode eqcr_mode; ++}; ++ ++/* P_OFFSET is (ACCESS_CMD,0,12) - offset within the portal ++ * C is (ACCESS_CMD,12,1) - is inhibited? (0==CENA, 1==CINH) ++ * SWP_IDX is (ACCESS_CMD,16,10) - Software portal index ++ * P is (ACCESS_CMD,28,1) - (0==special portal, 1==any portal) ++ * T is (ACCESS_CMD,29,1) - Command type (0==READ, 1==WRITE) ++ * E is (ACCESS_CMD,31,1) - Command execute (1 to issue, poll for 0==complete) ++ */ ++ ++static inline void qbman_cinh_write(struct qbman_swp_sys *s, uint32_t offset, ++ uint32_t val) ++{ ++ __raw_writel(val, s->addr_cinh + offset); ++#ifdef QBMAN_CINH_TRACE ++ pr_info("qbman_cinh_write(%p:%d:0x%03x) 0x%08x\n", ++ s->addr_cinh, s->idx, offset, val); ++#endif ++} ++ ++static inline uint32_t qbman_cinh_read(struct qbman_swp_sys *s, uint32_t offset) ++{ ++ uint32_t reg = __raw_readl(s->addr_cinh + offset); ++#ifdef QBMAN_CINH_TRACE ++ pr_info("qbman_cinh_read(%p:%d:0x%03x) 0x%08x\n", ++ s->addr_cinh, s->idx, offset, reg); ++#endif ++ return reg; ++} ++ ++static inline void *qbman_cena_write_start(struct qbman_swp_sys *s, ++ uint32_t offset) ++{ ++ void *shadow = s->cena + offset; ++ ++#ifdef QBMAN_CENA_TRACE ++ pr_info("qbman_cena_write_start(%p:%d:0x%03x) %p\n", ++ s->addr_cena, s->idx, offset, shadow); ++#endif ++ BUG_ON(offset & 63); ++ dcbz(shadow); ++ return shadow; ++} ++ ++static inline void *qbman_cena_write_start_wo_shadow(struct qbman_swp_sys *s, ++ uint32_t offset) ++{ ++#ifdef QBMAN_CENA_TRACE ++ pr_info("qbman_cena_write_start(%p:%d:0x%03x)\n", ++ s->addr_cena, s->idx, offset); ++#endif ++ BUG_ON(offset & 63); ++ return (s->addr_cena + offset); ++} ++ ++static inline void qbman_cena_write_complete(struct qbman_swp_sys *s, ++ uint32_t offset, void *cmd) ++{ ++ const uint32_t *shadow = cmd; ++ int loop; ++#ifdef QBMAN_CENA_TRACE ++ pr_info("qbman_cena_write_complete(%p:%d:0x%03x) %p\n", ++ s->addr_cena, s->idx, offset, shadow); ++ hexdump(cmd, 64); ++#endif ++ for (loop = 15; loop >= 1; loop--) ++ __raw_writel(shadow[loop], s->addr_cena + ++ offset + loop * 4); ++ lwsync(); ++ __raw_writel(shadow[0], s->addr_cena + offset); ++ dcbf(s->addr_cena + offset); ++} ++ ++static inline void qbman_cena_write_complete_wo_shadow(struct qbman_swp_sys *s, ++ uint32_t offset) ++{ ++#ifdef QBMAN_CENA_TRACE ++ pr_info("qbman_cena_write_complete(%p:%d:0x%03x)\n", ++ s->addr_cena, s->idx, offset); ++ hexdump(cmd, 64); ++#endif ++ dcbf(s->addr_cena + offset); ++} ++ ++static inline uint32_t qbman_cena_read_reg(struct qbman_swp_sys *s, ++ uint32_t offset) ++{ ++ return __raw_readl(s->addr_cena + offset); ++} ++ ++static inline void *qbman_cena_read(struct qbman_swp_sys *s, uint32_t offset) ++{ ++ uint32_t *shadow = (uint32_t *)(s->cena + offset); ++ unsigned int loop; ++#ifdef QBMAN_CENA_TRACE ++ pr_info("qbman_cena_read(%p:%d:0x%03x) %p\n", ++ s->addr_cena, s->idx, offset, shadow); ++#endif ++ ++ for (loop = 0; loop < 16; loop++) ++ shadow[loop] = __raw_readl(s->addr_cena + offset ++ + loop * 4); ++#ifdef QBMAN_CENA_TRACE ++ hexdump(shadow, 64); ++#endif ++ return shadow; ++} ++ ++static inline void *qbman_cena_read_wo_shadow(struct qbman_swp_sys *s, ++ uint32_t offset) ++{ ++#ifdef QBMAN_CENA_TRACE ++ pr_info("qbman_cena_read(%p:%d:0x%03x) %p\n", ++ s->addr_cena, s->idx, offset, shadow); ++#endif ++ ++#ifdef QBMAN_CENA_TRACE ++ hexdump(shadow, 64); ++#endif ++ return s->addr_cena + offset; ++} ++ ++static inline void qbman_cena_invalidate(struct qbman_swp_sys *s, ++ uint32_t offset) ++{ ++ dccivac(s->addr_cena + offset); ++} ++ ++static inline void qbman_cena_invalidate_prefetch(struct qbman_swp_sys *s, ++ uint32_t offset) ++{ ++ dccivac(s->addr_cena + offset); ++ prefetch_for_load(s->addr_cena + offset); ++} ++ ++static inline void qbman_cena_prefetch(struct qbman_swp_sys *s, ++ uint32_t offset) ++{ ++ prefetch_for_load(s->addr_cena + offset); ++} ++ ++ /******************/ ++ /* Portal support */ ++ /******************/ ++ ++/* The SWP_CFG portal register is special, in that it is used by the ++ * platform-specific code rather than the platform-independent code in ++ * qbman_portal.c. So use of it is declared locally here. */ ++#define QBMAN_CINH_SWP_CFG 0xd00 ++ ++/* For MC portal use, we always configure with ++ * DQRR_MF is (SWP_CFG,20,3) - DQRR max fill (<- 0x4) ++ * EST is (SWP_CFG,16,3) - EQCR_CI stashing threshold (<- 0x2) ++ * RPM is (SWP_CFG,12,2) - RCR production notification mode (<- 0x3) ++ * DCM is (SWP_CFG,10,2) - DQRR consumption notification mode (<- 0x2) ++ * EPM is (SWP_CFG,8,2) - EQCR production notification mode (<- 0x2) ++ * SD is (SWP_CFG,5,1) - memory stashing drop enable (<- TRUE) ++ * SP is (SWP_CFG,4,1) - memory stashing priority (<- TRUE) ++ * SE is (SWP_CFG,3,1) - memory stashing enable (<- TRUE) ++ * DP is (SWP_CFG,2,1) - dequeue stashing priority (<- TRUE) ++ * DE is (SWP_CFG,1,1) - dequeue stashing enable (<- TRUE) ++ * EP is (SWP_CFG,0,1) - EQCR_CI stashing priority (<- TRUE) ++ */ ++static inline uint32_t qbman_set_swp_cfg(uint8_t max_fill, uint8_t wn, ++ uint8_t est, uint8_t rpm, uint8_t dcm, ++ uint8_t epm, int sd, int sp, int se, ++ int dp, int de, int ep) ++{ ++ uint32_t reg; ++ ++ reg = e32_uint8_t(20, (uint32_t)(3 + (max_fill >> 3)), max_fill) | ++ e32_uint8_t(16, 3, est) | ++ e32_uint8_t(12, 2, rpm) | e32_uint8_t(10, 2, dcm) | ++ e32_uint8_t(8, 2, epm) | e32_int(5, 1, sd) | ++ e32_int(4, 1, sp) | e32_int(3, 1, se) | e32_int(2, 1, dp) | ++ e32_int(1, 1, de) | e32_int(0, 1, ep) | e32_uint8_t(14, 1, wn); ++ return reg; ++} ++ ++static inline int qbman_swp_sys_init(struct qbman_swp_sys *s, ++ const struct qbman_swp_desc *d, ++ uint8_t dqrr_size) ++{ ++ uint32_t reg; ++ ++ s->addr_cena = d->cena_bar; ++ s->addr_cinh = d->cinh_bar; ++ s->idx = (uint32_t)d->idx; ++ s->cena = (void *)get_zeroed_page(GFP_KERNEL); ++ if (!s->cena) { ++ pr_err("Could not allocate page for cena shadow\n"); ++ return -1; ++ } ++ s->eqcr_mode = d->eqcr_mode; ++ BUG_ON(d->idx < 0); ++#ifdef QBMAN_CHECKING ++ /* We should never be asked to initialise for a portal that isn't in ++ * the power-on state. (Ie. don't forget to reset portals when they are ++ * decommissioned!) ++ */ ++ reg = qbman_cinh_read(s, QBMAN_CINH_SWP_CFG); ++ BUG_ON(reg); ++#endif ++ if (s->eqcr_mode == qman_eqcr_vb_array) ++ reg = qbman_set_swp_cfg(dqrr_size, 0, 0, 3, 2, 3, 1, 1, 1, 1, ++ 1, 1); ++ else ++ reg = qbman_set_swp_cfg(dqrr_size, 0, 2, 3, 2, 2, 1, 1, 1, 1, ++ 1, 1); ++ qbman_cinh_write(s, QBMAN_CINH_SWP_CFG, reg); ++ reg = qbman_cinh_read(s, QBMAN_CINH_SWP_CFG); ++ if (!reg) { ++ pr_err("The portal %d is not enabled!\n", s->idx); ++ kfree(s->cena); ++ return -1; ++ } ++ return 0; ++} ++ ++static inline void qbman_swp_sys_finish(struct qbman_swp_sys *s) ++{ ++ free_page((unsigned long)s->cena); ++} ++ ++static inline void *qbman_cena_write_start_wo_shadow_fast(struct qbman_swp_sys *s, ++ uint32_t offset) ++{ ++#ifdef QBMAN_CENA_TRACE ++ pr_info("qbman_cena_write_start(%p:%d:0x%03x)\n", ++ s->addr_cena, s->idx, offset); ++#endif ++ BUG_ON(offset & 63); ++ return (s->addr_cena + offset); ++} +diff --git a/drivers/net/dpaa2/qbman/driver/qbman_sys_decl.h b/drivers/net/dpaa2/qbman/driver/qbman_sys_decl.h +new file mode 100644 +index 0000000..bbf3627 +--- /dev/null ++++ b/drivers/net/dpaa2/qbman/driver/qbman_sys_decl.h +@@ -0,0 +1,69 @@ ++/* Copyright (C) 2014 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY ++ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++#include ++#include ++ ++/* Sanity check */ ++#if (__BYTE_ORDER__ != __ORDER_BIG_ENDIAN__) && \ ++ (__BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__) ++#error "Unknown endianness!" ++#endif ++ ++/* The platform-independent code shouldn't need endianness, except for ++ * weird/fast-path cases like qbman_result_has_token(), which needs to ++ * perform a passive and endianness-specific test on a read-only data structure ++ * very quickly. It's an exception, and this symbol is used for that case. */ ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ++#define DQRR_TOK_OFFSET 0 ++#define QBMAN_RESULT_VERB_OFFSET_IN_MEM 24 ++#define SCN_STATE_OFFSET_IN_MEM 8 ++#define SCN_RID_OFFSET_IN_MEM 8 ++#else ++#define DQRR_TOK_OFFSET 24 ++#define QBMAN_RESULT_VERB_OFFSET_IN_MEM 0 ++#define SCN_STATE_OFFSET_IN_MEM 16 ++#define SCN_RID_OFFSET_IN_MEM 0 ++#endif ++ ++/* Similarly-named functions */ ++#define upper32(a) upper_32_bits(a) ++#define lower32(a) lower_32_bits(a) ++ ++ /****************/ ++ /* arch assists */ ++ /****************/ ++#define dcbz(p) { asm volatile("dc zva, %0" : : "r" (p) : "memory"); } ++#define lwsync() { asm volatile("dmb st" : : : "memory"); } ++#define dcbf(p) { asm volatile("dc cvac, %0" : : "r"(p) : "memory"); } ++#define dccivac(p) { asm volatile("dc civac, %0" : : "r"(p) : "memory"); } ++static inline void prefetch_for_load(void *p) ++{ ++ asm volatile("prfm pldl1keep, [%0, #64]" : : "r" (p)); ++} ++ ++static inline void prefetch_for_store(void *p) ++{ ++ asm volatile("prfm pstl1keep, [%0, #64]" : : "r" (p)); ++} +diff --git a/drivers/net/dpaa2/qbman/include/compat.h b/drivers/net/dpaa2/qbman/include/compat.h +new file mode 100644 +index 0000000..456f938 +--- /dev/null ++++ b/drivers/net/dpaa2/qbman/include/compat.h +@@ -0,0 +1,637 @@ ++/* Copyright (c) 2008-2011 Freescale Semiconductor, Inc. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY ++ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#ifndef HEADER_COMPAT_H ++#define HEADER_COMPAT_H ++ ++#include ++ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE ++#endif ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* The following definitions are primarily to allow the single-source driver ++ * interfaces to be included by arbitrary program code. Ie. for interfaces that ++ * are also available in kernel-space, these definitions provide compatibility ++ * with certain attributes and types used in those interfaces. */ ++ ++/* Required compiler attributes */ ++#define __maybe_unused __attribute__((unused)) ++#define __always_unused __attribute__((unused)) ++#define __packed __attribute__((__packed__)) ++#define __user ++#define likely(x) __builtin_expect(!!(x), 1) ++#define unlikely(x) __builtin_expect(!!(x), 0) ++#define ____cacheline_aligned __attribute__((aligned(L1_CACHE_BYTES))) ++#undef container_of ++#define container_of(ptr, type, member) ({ \ ++ typeof(((type *)0)->member)(*__mptr) = (ptr); \ ++ (type *)((char *)__mptr - offsetof(type, member)); }) ++#define __stringify_1(x) #x ++#define __stringify(x) __stringify_1(x) ++#define panic(x) \ ++do { \ ++ printf("panic: %s", x); \ ++ abort(); \ ++} while (0) ++ ++#ifdef ARRAY_SIZE ++#undef ARRAY_SIZE ++#endif ++#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) ++ ++/* Required types */ ++typedef uint8_t u8; ++typedef uint16_t u16; ++typedef uint32_t u32; ++typedef uint64_t u64; ++typedef uint64_t dma_addr_t; ++typedef cpu_set_t cpumask_t; ++#define spinlock_t pthread_mutex_t ++typedef u32 compat_uptr_t; ++static inline void __user *compat_ptr(compat_uptr_t uptr) ++{ ++ return (void __user *)(unsigned long)uptr; ++} ++ ++static inline compat_uptr_t ptr_to_compat(void __user *uptr) ++{ ++ return (u32)(unsigned long)uptr; ++} ++ ++/* I/O operations */ ++static inline u32 in_be32(volatile void *__p) ++{ ++ volatile u32 *p = __p; ++ return *p; ++} ++ ++static inline void out_be32(volatile void *__p, u32 val) ++{ ++ volatile u32 *p = __p; ++ *p = val; ++} ++ ++/* Debugging */ ++#define prflush(fmt, args...) \ ++ do { \ ++ printf(fmt, ##args); \ ++ fflush(stdout); \ ++ } while (0) ++#define pr_crit(fmt, args...) prflush("CRIT:" fmt, ##args) ++#define pr_err(fmt, args...) prflush("ERR:" fmt, ##args) ++#define pr_warn(fmt, args...) prflush("WARN:" fmt, ##args) ++#define pr_info(fmt, args...) prflush(fmt, ##args) ++ ++#define BUG() abort() ++#ifdef CONFIG_BUGON ++#ifdef pr_debug ++#undef pr_debug ++#endif ++#define pr_debug(fmt, args...) printf(fmt, ##args) ++#define BUG_ON(c) \ ++do { \ ++ if (c) { \ ++ pr_crit("BUG: %s:%d\n", __FILE__, __LINE__); \ ++ abort(); \ ++ } \ ++} while (0) ++#define might_sleep_if(c) BUG_ON(c) ++#define msleep(x) \ ++do { \ ++ pr_crit("BUG: illegal call %s:%d\n", __FILE__, __LINE__); \ ++ exit(EXIT_FAILURE); \ ++} while (0) ++#else ++#ifdef pr_debug ++#undef pr_debug ++#endif ++#define pr_debug(fmt, args...) do { ; } while (0) ++#define BUG_ON(c) do { ; } while (0) ++#define might_sleep_if(c) do { ; } while (0) ++#define msleep(x) do { ; } while (0) ++#endif ++#define WARN_ON(c, str) \ ++do { \ ++ static int warned_##__LINE__; \ ++ if ((c) && !warned_##__LINE__) { \ ++ pr_warn("%s\n", str); \ ++ pr_warn("(%s:%d)\n", __FILE__, __LINE__); \ ++ warned_##__LINE__ = 1; \ ++ } \ ++} while (0) ++ ++#define ALIGN(x, a) (((x) + ((typeof(x))(a) - 1)) & ~((typeof(x))(a) - 1)) ++ ++/****************/ ++/* Linked-lists */ ++/****************/ ++ ++struct list_head { ++ struct list_head *prev; ++ struct list_head *next; ++}; ++ ++#define LIST_HEAD(n) \ ++struct list_head n = { \ ++ .prev = &n, \ ++ .next = &n \ ++} ++ ++#define INIT_LIST_HEAD(p) \ ++do { \ ++ struct list_head *__p298 = (p); \ ++ __p298->prev = __p298->next = __p298; \ ++} while (0) ++#define list_entry(node, type, member) \ ++ (type *)((void *)node - offsetof(type, member)) ++#define list_empty(p) \ ++({ \ ++ const struct list_head *__p298 = (p); \ ++ ((__p298->next == __p298) && (__p298->prev == __p298)); \ ++}) ++#define list_add(p, l) \ ++do { \ ++ struct list_head *__p298 = (p); \ ++ struct list_head *__l298 = (l); \ ++ __p298->next = __l298->next; \ ++ __p298->prev = __l298; \ ++ __l298->next->prev = __p298; \ ++ __l298->next = __p298; \ ++} while (0) ++#define list_add_tail(p, l) \ ++do { \ ++ struct list_head *__p298 = (p); \ ++ struct list_head *__l298 = (l); \ ++ __p298->prev = __l298->prev; \ ++ __p298->next = __l298; \ ++ __l298->prev->next = __p298; \ ++ __l298->prev = __p298; \ ++} while (0) ++#define list_for_each(i, l) \ ++ for (i = (l)->next; i != (l); i = i->next) ++#define list_for_each_safe(i, j, l) \ ++ for (i = (l)->next, j = i->next; i != (l); \ ++ i = j, j = i->next) ++#define list_for_each_entry(i, l, name) \ ++ for (i = list_entry((l)->next, typeof(*i), name); &i->name != (l); \ ++ i = list_entry(i->name.next, typeof(*i), name)) ++#define list_for_each_entry_safe(i, j, l, name) \ ++ for (i = list_entry((l)->next, typeof(*i), name), \ ++ j = list_entry(i->name.next, typeof(*j), name); \ ++ &i->name != (l); \ ++ i = j, j = list_entry(j->name.next, typeof(*j), name)) ++#define list_del(i) \ ++do { \ ++ (i)->next->prev = (i)->prev; \ ++ (i)->prev->next = (i)->next; \ ++} while (0) ++ ++/* Other miscellaneous interfaces our APIs depend on; */ ++ ++#define lower_32_bits(x) ((u32)(x)) ++#define upper_32_bits(x) ((u32)(((x) >> 16) >> 16)) ++ ++/* Compiler/type stuff */ ++typedef unsigned int gfp_t; ++typedef uint32_t phandle; ++ ++#define noinline __attribute__((noinline)) ++#define __iomem ++#define EINTR 4 ++#define ENODEV 19 ++#define MODULE_AUTHOR(s) ++#define MODULE_LICENSE(s) ++#define MODULE_DESCRIPTION(s) ++#define MODULE_PARM_DESC(x, y) ++#define EXPORT_SYMBOL(x) ++#define module_init(fn) int m_##fn(void) { return fn(); } ++#define module_exit(fn) void m_##fn(void) { fn(); } ++#define module_param(x, y, z) ++#define module_param_string(w, x, y, z) ++#define GFP_KERNEL 0 ++#define __KERNEL__ ++#define __init ++#define __raw_readb(p) *(const volatile unsigned char *)(p) ++#define __raw_readl(p) *(const volatile unsigned int *)(p) ++#define __raw_writel(v, p) \ ++do { \ ++ *(volatile unsigned int *)(p) = (v); \ ++} while (0) ++ ++/* printk() stuff */ ++#define printk(fmt, args...) do_not_use_printk ++#define nada(fmt, args...) do { ; } while (0) ++ ++/* Interrupt stuff */ ++typedef uint32_t irqreturn_t; ++#define IRQ_HANDLED 0 ++ ++/* memcpy() stuff - when you know alignments in advance */ ++#ifdef CONFIG_TRY_BETTER_MEMCPY ++static inline void copy_words(void *dest, const void *src, size_t sz) ++{ ++ u32 *__dest = dest; ++ const u32 *__src = src; ++ size_t __sz = sz >> 2; ++ ++ BUG_ON((unsigned long)dest & 0x3); ++ BUG_ON((unsigned long)src & 0x3); ++ BUG_ON(sz & 0x3); ++ while (__sz--) ++ *(__dest++) = *(__src++); ++} ++ ++static inline void copy_shorts(void *dest, const void *src, size_t sz) ++{ ++ u16 *__dest = dest; ++ const u16 *__src = src; ++ size_t __sz = sz >> 1; ++ ++ BUG_ON((unsigned long)dest & 0x1); ++ BUG_ON((unsigned long)src & 0x1); ++ BUG_ON(sz & 0x1); ++ while (__sz--) ++ *(__dest++) = *(__src++); ++} ++ ++static inline void copy_bytes(void *dest, const void *src, size_t sz) ++{ ++ u8 *__dest = dest; ++ const u8 *__src = src; ++ ++ while (sz--) ++ *(__dest++) = *(__src++); ++} ++#else ++#define copy_words memcpy ++#define copy_shorts memcpy ++#define copy_bytes memcpy ++#endif ++ ++/* Spinlock stuff */ ++#define spinlock_t pthread_mutex_t ++#define __SPIN_LOCK_UNLOCKED(x) PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP ++#define DEFINE_SPINLOCK(x) spinlock_t x = __SPIN_LOCK_UNLOCKED(x) ++#define spin_lock_init(x) \ ++ do { \ ++ __maybe_unused int __foo; \ ++ pthread_mutexattr_t __foo_attr; \ ++ __foo = pthread_mutexattr_init(&__foo_attr); \ ++ BUG_ON(__foo); \ ++ __foo = pthread_mutexattr_settype(&__foo_attr, \ ++ PTHREAD_MUTEX_ADAPTIVE_NP); \ ++ BUG_ON(__foo); \ ++ __foo = pthread_mutex_init(x, &__foo_attr); \ ++ BUG_ON(__foo); \ ++ } while (0) ++#define spin_lock(x) \ ++ do { \ ++ __maybe_unused int __foo = pthread_mutex_lock(x); \ ++ BUG_ON(__foo); \ ++ } while (0) ++#define spin_unlock(x) \ ++ do { \ ++ __maybe_unused int __foo = pthread_mutex_unlock(x); \ ++ BUG_ON(__foo); \ ++ } while (0) ++#define spin_lock_irq(x) do { \ ++ local_irq_disable(); \ ++ spin_lock(x); \ ++ } while (0) ++#define spin_unlock_irq(x) do { \ ++ spin_unlock(x); \ ++ local_irq_enable(); \ ++ } while (0) ++#define spin_lock_irqsave(x, f) do { spin_lock_irq(x); } while (0) ++#define spin_unlock_irqrestore(x, f) do { spin_unlock_irq(x); } while (0) ++ ++#define raw_spinlock_t spinlock_t ++#define raw_spin_lock_init(x) spin_lock_init(x) ++#define raw_spin_lock_irqsave(x, f) spin_lock(x) ++#define raw_spin_unlock_irqrestore(x, f) spin_unlock(x) ++ ++/* Completion stuff */ ++#define DECLARE_COMPLETION(n) int n = 0; ++#define complete(n) \ ++do { \ ++ *n = 1; \ ++} while (0) ++#define wait_for_completion(n) \ ++do { \ ++ while (!*n) { \ ++ bman_poll(); \ ++ qman_poll(); \ ++ } \ ++ *n = 0; \ ++} while (0) ++ ++/* Platform device stuff */ ++struct platform_device { void *dev; }; ++static inline struct ++platform_device *platform_device_alloc(const char *name __always_unused, ++ int id __always_unused) ++{ ++ struct platform_device *ret = malloc(sizeof(*ret)); ++ ++ if (ret) ++ ret->dev = NULL; ++ return ret; ++} ++ ++#define platform_device_add(pdev) 0 ++#define platform_device_del(pdev) do { ; } while (0) ++static inline void platform_device_put(struct platform_device *pdev) ++{ ++ free(pdev); ++} ++ ++struct resource { ++ int unused; ++}; ++ ++/* Allocator stuff */ ++#define kmalloc(sz, t) malloc(sz) ++#define vmalloc(sz) malloc(sz) ++#define kfree(p) do { if (p) free(p); } while (0) ++static inline void *kzalloc(size_t sz, gfp_t __foo __always_unused) ++{ ++ void *ptr = malloc(sz); ++ ++ if (ptr) ++ memset(ptr, 0, sz); ++ return ptr; ++} ++ ++static inline unsigned long get_zeroed_page(gfp_t __foo __always_unused) ++{ ++ void *p; ++ ++ if (posix_memalign(&p, 4096, 4096)) ++ return 0; ++ memset(p, 0, 4096); ++ return (unsigned long)p; ++} ++ ++static inline void free_page(unsigned long p) ++{ ++ free((void *)p); ++} ++ ++struct kmem_cache { ++ size_t sz; ++ size_t align; ++}; ++ ++#define SLAB_HWCACHE_ALIGN 0 ++static inline struct kmem_cache *kmem_cache_create(const char *n __always_unused, ++ size_t sz, size_t align, unsigned long flags __always_unused, ++ void (*c)(void *) __always_unused) ++{ ++ struct kmem_cache *ret = malloc(sizeof(*ret)); ++ ++ if (ret) { ++ ret->sz = sz; ++ ret->align = align; ++ } ++ return ret; ++} ++ ++static inline void kmem_cache_destroy(struct kmem_cache *c) ++{ ++ free(c); ++} ++ ++static inline void *kmem_cache_alloc(struct kmem_cache *c, gfp_t f __always_unused) ++{ ++ void *p; ++ ++ if (posix_memalign(&p, c->align, c->sz)) ++ return NULL; ++ return p; ++} ++ ++static inline void kmem_cache_free(struct kmem_cache *c __always_unused, void *p) ++{ ++ free(p); ++} ++ ++static inline void *kmem_cache_zalloc(struct kmem_cache *c, gfp_t f) ++{ ++ void *ret = kmem_cache_alloc(c, f); ++ ++ if (ret) ++ memset(ret, 0, c->sz); ++ return ret; ++} ++ ++/* Bitfield stuff. */ ++#define BITS_PER_ULONG (sizeof(unsigned long) << 3) ++#define SHIFT_PER_ULONG (((1 << 5) == BITS_PER_ULONG) ? 5 : 6) ++#define BITS_MASK(idx) ((unsigned long)1 << ((idx) & (BITS_PER_ULONG - 1))) ++#define BITS_IDX(idx) ((idx) >> SHIFT_PER_ULONG) ++static inline unsigned long test_bits(unsigned long mask, ++ volatile unsigned long *p) ++{ ++ return *p & mask; ++} ++ ++static inline int test_bit(int idx, volatile unsigned long *bits) ++{ ++ return test_bits(BITS_MASK(idx), bits + BITS_IDX(idx)); ++} ++ ++static inline void set_bits(unsigned long mask, volatile unsigned long *p) ++{ ++ *p |= mask; ++} ++ ++static inline void set_bit(int idx, volatile unsigned long *bits) ++{ ++ set_bits(BITS_MASK(idx), bits + BITS_IDX(idx)); ++} ++ ++static inline void clear_bits(unsigned long mask, volatile unsigned long *p) ++{ ++ *p &= ~mask; ++} ++ ++static inline void clear_bit(int idx, volatile unsigned long *bits) ++{ ++ clear_bits(BITS_MASK(idx), bits + BITS_IDX(idx)); ++} ++ ++static inline unsigned long test_and_set_bits(unsigned long mask, ++ volatile unsigned long *p) ++{ ++ unsigned long ret = test_bits(mask, p); ++ ++ set_bits(mask, p); ++ return ret; ++} ++ ++static inline int test_and_set_bit(int idx, volatile unsigned long *bits) ++{ ++ int ret = test_bit(idx, bits); ++ ++ set_bit(idx, bits); ++ return ret; ++} ++ ++static inline int test_and_clear_bit(int idx, volatile unsigned long *bits) ++{ ++ int ret = test_bit(idx, bits); ++ ++ clear_bit(idx, bits); ++ return ret; ++} ++ ++static inline int find_next_zero_bit(unsigned long *bits, int limit, int idx) ++{ ++ while ((++idx < limit) && test_bit(idx, bits)) ++ ; ++ return idx; ++} ++ ++static inline int find_first_zero_bit(unsigned long *bits, int limit) ++{ ++ int idx = 0; ++ ++ while (test_bit(idx, bits) && (++idx < limit)) ++ ; ++ return idx; ++} ++ ++static inline u64 div64_u64(u64 n, u64 d) ++{ ++ return n / d; ++} ++ ++#define dmb(opt) { asm volatile("dmb " #opt : : : "memory"); } ++#define smp_mb() dmb(ish) ++ ++/* Atomic stuff */ ++typedef struct { ++ int counter; ++} atomic_t; ++ ++#define atomic_read(v) (*(volatile int *)&(v)->counter) ++#define atomic_set(v, i) (((v)->counter) = (i)) ++static inline void atomic_add(int i, atomic_t *v) ++{ ++ unsigned long tmp; ++ int result; ++ ++ asm volatile("// atomic_add\n" ++ "1: ldxr %w0, %2\n" ++ " add %w0, %w0, %w3\n" ++ " stxr %w1, %w0, %2\n" ++ " cbnz %w1, 1b" ++ : "=&r" (result), "=&r" (tmp), "+Q" (v->counter) ++ : "Ir" (i)); ++} ++ ++static inline int atomic_add_return(int i, atomic_t *v) ++{ ++ unsigned long tmp; ++ int result; ++ ++ asm volatile("// atomic_add_return\n" ++ "1: ldxr %w0, %2\n" ++ " add %w0, %w0, %w3\n" ++ " stlxr %w1, %w0, %2\n" ++ " cbnz %w1, 1b" ++ : "=&r" (result), "=&r" (tmp), "+Q" (v->counter) ++ : "Ir" (i) ++ : "memory"); ++ ++ smp_mb(); ++ return result; ++} ++ ++static inline void atomic_sub(int i, atomic_t *v) ++{ ++ unsigned long tmp; ++ int result; ++ ++ asm volatile("// atomic_sub\n" ++ "1: ldxr %w0, %2\n" ++ " sub %w0, %w0, %w3\n" ++ " stxr %w1, %w0, %2\n" ++ " cbnz %w1, 1b" ++ : "=&r" (result), "=&r" (tmp), "+Q" (v->counter) ++ : "Ir" (i)); ++} ++ ++static inline int atomic_sub_return(int i, atomic_t *v) ++{ ++ unsigned long tmp; ++ int result; ++ ++ asm volatile("// atomic_sub_return\n" ++ "1: ldxr %w0, %2\n" ++ " sub %w0, %w0, %w3\n" ++ " stlxr %w1, %w0, %2\n" ++ " cbnz %w1, 1b" ++ : "=&r" (result), "=&r" (tmp), "+Q" (v->counter) ++ : "Ir" (i) ++ : "memory"); ++ ++ smp_mb(); ++ return result; ++} ++ ++#define atomic_inc(v) atomic_add(1, v) ++#define atomic_dec(v) atomic_sub(1, v) ++ ++#define atomic_inc_and_test(v) (atomic_add_return(1, v) == 0) ++#define atomic_dec_and_test(v) (atomic_sub_return(1, v) == 0) ++#define atomic_inc_return(v) (atomic_add_return(1, v)) ++#define atomic_dec_return(v) (atomic_sub_return(1, v)) ++#define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0) ++ ++#endif /* HEADER_COMPAT_H */ +diff --git a/drivers/net/dpaa2/qbman/include/drivers/fsl_qbman_base.h b/drivers/net/dpaa2/qbman/include/drivers/fsl_qbman_base.h +new file mode 100644 +index 0000000..4cb784c +--- /dev/null ++++ b/drivers/net/dpaa2/qbman/include/drivers/fsl_qbman_base.h +@@ -0,0 +1,151 @@ ++/* Copyright (C) 2014 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY ++ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_QBMAN_BASE_H ++#define _FSL_QBMAN_BASE_H ++ ++/** ++ * DOC: QBMan basic structures ++ * ++ * The QBMan block descriptor, software portal descriptor and Frame descriptor ++ * are defined here. ++ * ++ */ ++ ++/** ++ * struct qbman_block_desc - qbman block descriptor structure ++ * @ccsr_reg_bar: CCSR register map. ++ * @irq_rerr: Recoverable error interrupt line. ++ * @irq_nrerr: Non-recoverable error interrupt line ++ * ++ * Descriptor for a QBMan instance on the SoC. On partitions/targets that do not ++ * control this QBMan instance, these values may simply be place-holders. The ++ * idea is simply that we be able to distinguish between them, eg. so that SWP ++ * descriptors can identify which QBMan instance they belong to. ++ */ ++struct qbman_block_desc { ++ void *ccsr_reg_bar; ++ int irq_rerr; ++ int irq_nrerr; ++}; ++ ++enum qbman_eqcr_mode { ++ qman_eqcr_vb_ring = 2, /* Valid bit, with eqcr in ring mode */ ++ qman_eqcr_vb_array, /* Valid bit, with eqcr in array mode */ ++}; ++ ++/** ++ * struct qbman_swp_desc - qbman software portal descriptor structure ++ * @block: The QBMan instance. ++ * @cena_bar: Cache-enabled portal register map. ++ * @cinh_bar: Cache-inhibited portal register map. ++ * @irq: -1 if unused (or unassigned) ++ * @idx: SWPs within a QBMan are indexed. -1 if opaque to the user. ++ * @qman_version: the qman version. ++ * @eqcr_mode: Select the eqcr mode, currently only valid bit ring mode and ++ * valid bit array mode are supported. ++ * ++ * Descriptor for a QBMan software portal, expressed in terms that make sense to ++ * the user context. Ie. on MC, this information is likely to be true-physical, ++ * and instantiated statically at compile-time. On GPP, this information is ++ * likely to be obtained via "discovery" over a partition's "MC bus" ++ * (ie. in response to a MC portal command), and would take into account any ++ * virtualisation of the GPP user's address space and/or interrupt numbering. ++ */ ++struct qbman_swp_desc { ++ const struct qbman_block_desc *block; ++ uint8_t *cena_bar; ++ uint8_t *cinh_bar; ++ int irq; ++ int idx; ++ uint32_t qman_version; ++ enum qbman_eqcr_mode eqcr_mode; ++}; ++ ++/* Driver object for managing a QBMan portal */ ++struct qbman_swp; ++ ++/** ++ * struct qbman_fd - basci structure for qbman frame descriptor ++ * @words: for easier/faster copying the whole FD structure. ++ * @addr_lo: the lower 32 bits of the address in FD. ++ * @addr_hi: the upper 32 bits of the address in FD. ++ * @len: the length field in FD. ++ * @bpid_offset: represent the bpid and offset fields in FD. offset in ++ * the MS 16 bits, BPID in the LS 16 bits. ++ * @frc: frame context ++ * @ctrl: the 32bit control bits including dd, sc,... va, err. ++ * @flc_lo: the lower 32bit of flow context. ++ * @flc_hi: the upper 32bits of flow context. ++ * ++ * Place-holder for FDs, we represent it via the simplest form that we need for ++ * now. Different overlays may be needed to support different options, etc. (It ++ * is impractical to define One True Struct, because the resulting encoding ++ * routines (lots of read-modify-writes) would be worst-case performance whether ++ * or not circumstances required them.) ++ * ++ * Note, as with all data-structures exchanged between software and hardware (be ++ * they located in the portal register map or DMA'd to and from main-memory), ++ * the driver ensures that the caller of the driver API sees the data-structures ++ * in host-endianness. "struct qbman_fd" is no exception. The 32-bit words ++ * contained within this structure are represented in host-endianness, even if ++ * hardware always treats them as little-endian. As such, if any of these fields ++ * are interpreted in a binary (rather than numerical) fashion by hardware ++ * blocks (eg. accelerators), then the user should be careful. We illustrate ++ * with an example; ++ * ++ * Suppose the desired behaviour of an accelerator is controlled by the "frc" ++ * field of the FDs that are sent to it. Suppose also that the behaviour desired ++ * by the user corresponds to an "frc" value which is expressed as the literal ++ * sequence of bytes 0xfe, 0xed, 0xab, and 0xba. So "frc" should be the 32-bit ++ * value in which 0xfe is the first byte and 0xba is the last byte, and as ++ * hardware is little-endian, this amounts to a 32-bit "value" of 0xbaabedfe. If ++ * the software is little-endian also, this can simply be achieved by setting ++ * frc=0xbaabedfe. On the other hand, if software is big-endian, it should set ++ * frc=0xfeedabba! The best away of avoiding trouble with this sort of thing is ++ * to treat the 32-bit words as numerical values, in which the offset of a field ++ * from the beginning of the first byte (as required or generated by hardware) ++ * is numerically encoded by a left-shift (ie. by raising the field to a ++ * corresponding power of 2). Ie. in the current example, software could set ++ * "frc" in the following way, and it would work correctly on both little-endian ++ * and big-endian operation; ++ * fd.frc = (0xfe << 0) | (0xed << 8) | (0xab << 16) | (0xba << 24); ++ */ ++struct qbman_fd { ++ union { ++ uint32_t words[8]; ++ struct qbman_fd_simple { ++ uint32_t addr_lo; ++ uint32_t addr_hi; ++ uint32_t len; ++ uint32_t bpid_offset; ++ uint32_t frc; ++ uint32_t ctrl; ++ uint32_t flc_lo; ++ uint32_t flc_hi; ++ } simple; ++ }; ++}; ++ ++#endif /* !_FSL_QBMAN_BASE_H */ +diff --git a/drivers/net/dpaa2/qbman/include/drivers/fsl_qbman_portal.h b/drivers/net/dpaa2/qbman/include/drivers/fsl_qbman_portal.h +new file mode 100644 +index 0000000..9e8e5f2 +--- /dev/null ++++ b/drivers/net/dpaa2/qbman/include/drivers/fsl_qbman_portal.h +@@ -0,0 +1,1087 @@ ++/* Copyright (C) 2014 Freescale Semiconductor, Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY ++ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++#ifndef _FSL_QBMAN_PORTAL_H ++#define _FSL_QBMAN_PORTAL_H ++ ++#include ++ ++/** ++ * DOC - QBMan portal APIs to implement the following functions: ++ * - Initialize and destroy Software portal object. ++ * - Read and write Software portal interrupt registers. ++ * - Enqueue, including setting the enqueue descriptor, and issuing enqueue ++ * command etc. ++ * - Dequeue, including setting the dequeue descriptor, issuing dequeue command, ++ * parsing the dequeue response in DQRR and memeory, parsing the state change ++ * notifications etc. ++ * - Release, including setting the release descriptor, and issuing the buffer ++ * release command. ++ * - Acquire, acquire the buffer from the given buffer pool. ++ * - FQ management. ++ * - Channel management, enable/disable CDAN with or without context. ++ */ ++ ++/** ++ * qbman_swp_init() - Create a functional object representing the given ++ * QBMan portal descriptor. ++ * @d: the given qbman swp descriptor ++ * ++ * Return qbman_swp portal object for success, NULL if the object cannot ++ * be created. ++ */ ++struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d); ++ ++/** ++ * qbman_swp_finish() - Create and destroy a functional object representing ++ * the given QBMan portal descriptor. ++ * @p: the qbman_swp object to be destroyed. ++ * ++ */ ++void qbman_swp_finish(struct qbman_swp *p); ++ ++/** ++ * qbman_swp_get_desc() - Get the descriptor of the given portal object. ++ * @p: the given portal object. ++ * ++ * Return the descriptor for this portal. ++ */ ++const struct qbman_swp_desc *qbman_swp_get_desc(struct qbman_swp *); ++ ++ /**************/ ++ /* Interrupts */ ++ /**************/ ++ ++/* EQCR ring interrupt */ ++#define QBMAN_SWP_INTERRUPT_EQRI ((uint32_t)0x00000001) ++/* Enqueue command dispatched interrupt */ ++#define QBMAN_SWP_INTERRUPT_EQDI ((uint32_t)0x00000002) ++/* DQRR non-empty interrupt */ ++#define QBMAN_SWP_INTERRUPT_DQRI ((uint32_t)0x00000004) ++/* RCR ring interrupt */ ++#define QBMAN_SWP_INTERRUPT_RCRI ((uint32_t)0x00000008) ++/* Release command dispatched interrupt */ ++#define QBMAN_SWP_INTERRUPT_RCDI ((uint32_t)0x00000010) ++/* Volatile dequeue command interrupt */ ++#define QBMAN_SWP_INTERRUPT_VDCI ((uint32_t)0x00000020) ++ ++/** ++ * qbman_swp_interrupt_get_vanish() - Get the data in software portal ++ * interrupt status disable register. ++ * @p: the given software portal object. ++ * ++ * Return the settings in SWP_ISDR register. ++ */ ++uint32_t qbman_swp_interrupt_get_vanish(struct qbman_swp *p); ++ ++/** ++ * qbman_swp_interrupt_set_vanish() - Set the data in software portal ++ * interrupt status disable register. ++ * @p: the given software portal object. ++ * @mask: The value to set in SWP_IDSR register. ++ */ ++void qbman_swp_interrupt_set_vanish(struct qbman_swp *p, uint32_t mask); ++ ++/** ++ * qbman_swp_interrupt_read_status() - Get the data in software portal ++ * interrupt status register. ++ * @p: the given software portal object. ++ * ++ * Return the settings in SWP_ISR register. ++ */ ++uint32_t qbman_swp_interrupt_read_status(struct qbman_swp *p); ++ ++/** ++ * qbman_swp_interrupt_clear_status() - Set the data in software portal ++ * interrupt status register. ++ * @p: the given software portal object. ++ * @mask: The value to set in SWP_ISR register. ++ */ ++void qbman_swp_interrupt_clear_status(struct qbman_swp *p, uint32_t mask); ++ ++/** ++ * qbman_swp_interrupt_get_trigger() - Get the data in software portal ++ * interrupt enable register. ++ * @p: the given software portal object. ++ * ++ * Return the settings in SWP_IER register. ++ */ ++uint32_t qbman_swp_interrupt_get_trigger(struct qbman_swp *p); ++ ++/** ++ * qbman_swp_interrupt_set_trigger() - Set the data in software portal ++ * interrupt enable register. ++ * @p: the given software portal object. ++ * @mask: The value to set in SWP_IER register. ++ */ ++void qbman_swp_interrupt_set_trigger(struct qbman_swp *p, uint32_t mask); ++ ++/** ++ * qbman_swp_interrupt_get_inhibit() - Get the data in software portal ++ * interrupt inhibit register. ++ * @p: the given software portal object. ++ * ++ * Return the settings in SWP_IIR register. ++ */ ++int qbman_swp_interrupt_get_inhibit(struct qbman_swp *p); ++ ++/** ++ * qbman_swp_interrupt_set_inhibit() - Set the data in software portal ++ * interrupt inhibit register. ++ * @p: the given software portal object. ++ * @mask: The value to set in SWP_IIR register. ++ */ ++void qbman_swp_interrupt_set_inhibit(struct qbman_swp *p, int inhibit); ++ ++ /************/ ++ /* Dequeues */ ++ /************/ ++ ++/** ++ * struct qbman_result - structure for qbman dequeue response and/or ++ * notification. ++ * @dont_manipulate_directly: the 16 32bit data to represent the whole ++ * possible qbman dequeue result. ++ */ ++struct qbman_result { ++ uint32_t dont_manipulate_directly[16]; ++}; ++ ++/* TODO: ++ *A DQRI interrupt can be generated when there are dequeue results on the ++ * portal's DQRR (this mechanism does not deal with "pull" dequeues to ++ * user-supplied 'storage' addresses). There are two parameters to this ++ * interrupt source, one is a threshold and the other is a timeout. The ++ * interrupt will fire if either the fill-level of the ring exceeds 'thresh', or ++ * if the ring has been non-empty for been longer than 'timeout' nanoseconds. ++ * For timeout, an approximation to the desired nanosecond-granularity value is ++ * made, so there are get and set APIs to allow the user to see what actual ++ * timeout is set (compared to the timeout that was requested). */ ++int qbman_swp_dequeue_thresh(struct qbman_swp *s, unsigned int thresh); ++int qbman_swp_dequeue_set_timeout(struct qbman_swp *s, unsigned int timeout); ++int qbman_swp_dequeue_get_timeout(struct qbman_swp *s, unsigned int *timeout); ++ ++/* ------------------- */ ++/* Push-mode dequeuing */ ++/* ------------------- */ ++ ++/* The user of a portal can enable and disable push-mode dequeuing of up to 16 ++ * channels independently. It does not specify this toggling by channel IDs, but ++ * rather by specifying the index (from 0 to 15) that has been mapped to the ++ * desired channel. ++ */ ++ ++/** ++ * qbman_swp_push_get() - Get the push dequeue setup. ++ * @s: the software portal object. ++ * @channel_idx: the channel index to query. ++ * @enabled: returned boolean to show whether the push dequeue is enabled for ++ * the given channel. ++ */ ++void qbman_swp_push_get(struct qbman_swp *s, uint8_t channel_idx, int *enabled); ++ ++/** ++ * qbman_swp_push_set() - Enable or disable push dequeue. ++ * @s: the software portal object. ++ * @channel_idx: the channel index.. ++ * @enable: enable or disable push dequeue. ++ * ++ * The user of a portal can enable and disable push-mode dequeuing of up to 16 ++ * channels independently. It does not specify this toggling by channel IDs, but ++ * rather by specifying the index (from 0 to 15) that has been mapped to the ++ * desired channel. ++ */ ++void qbman_swp_push_set(struct qbman_swp *s, uint8_t channel_idx, int enable); ++ ++/* ------------------- */ ++/* Pull-mode dequeuing */ ++/* ------------------- */ ++ ++/** ++ * struct qbman_pull_desc - the structure for pull dequeue descriptor ++ * @dont_manipulate_directly: the 6 32bit data to represent the whole ++ * possible settings for pull dequeue descriptor. ++ */ ++struct qbman_pull_desc { ++ uint32_t dont_manipulate_directly[6]; ++}; ++ ++enum qbman_pull_type_e { ++ /* dequeue with priority precedence, respect intra-class scheduling */ ++ qbman_pull_type_prio = 1, ++ /* dequeue with active FQ precedence, respect ICS */ ++ qbman_pull_type_active, ++ /* dequeue with active FQ precedence, no ICS */ ++ qbman_pull_type_active_noics ++}; ++ ++/** ++ * qbman_pull_desc_clear() - Clear the contents of a descriptor to ++ * default/starting state. ++ * @d: the pull dequeue descriptor to be cleared. ++ */ ++void qbman_pull_desc_clear(struct qbman_pull_desc *d); ++ ++/** ++ * qbman_pull_desc_set_storage()- Set the pull dequeue storage ++ * @d: the pull dequeue descriptor to be set. ++ * @storage: the pointer of the memory to store the dequeue result. ++ * @storage_phys: the physical address of the storage memory. ++ * @stash: to indicate whether write allocate is enabled. ++ * ++ * If not called, or if called with 'storage' as NULL, the result pull dequeues ++ * will produce results to DQRR. If 'storage' is non-NULL, then results are ++ * produced to the given memory location (using the physical/DMA address which ++ * the caller provides in 'storage_phys'), and 'stash' controls whether or not ++ * those writes to main-memory express a cache-warming attribute. ++ */ ++void qbman_pull_desc_set_storage(struct qbman_pull_desc *d, ++ struct qbman_result *storage, ++ dma_addr_t storage_phys, ++ int stash); ++/** ++ * qbman_pull_desc_set_numframes() - Set the number of frames to be dequeued. ++ * @d: the pull dequeue descriptor to be set. ++ * @numframes: number of frames to be set, must be between 1 and 16, inclusive. ++ */ ++void qbman_pull_desc_set_numframes(struct qbman_pull_desc *d, ++ uint8_t numframes); ++/** ++ * qbman_pull_desc_set_token() - Set dequeue token for pull command ++ * @d: the dequeue descriptor ++ * @token: the token to be set ++ * ++ * token is the value that shows up in the dequeue response that can be used to ++ * detect when the results have been published. The easiest technique is to zero ++ * result "storage" before issuing a dequeue, and use any non-zero 'token' value ++ */ ++void qbman_pull_desc_set_token(struct qbman_pull_desc *d, uint8_t token); ++ ++/* Exactly one of the following descriptor "actions" should be set. (Calling any ++ * one of these will replace the effect of any prior call to one of these.) ++ * - pull dequeue from the given frame queue (FQ) ++ * - pull dequeue from any FQ in the given work queue (WQ) ++ * - pull dequeue from any FQ in any WQ in the given channel ++ */ ++/** ++ * qbman_pull_desc_set_fq() - Set fqid from which the dequeue command dequeues. ++ * @fqid: the frame queue index of the given FQ. ++ */ ++void qbman_pull_desc_set_fq(struct qbman_pull_desc *d, uint32_t fqid); ++ ++/** ++ * qbman_pull_desc_set_wq() - Set wqid from which the dequeue command dequeues. ++ * @wqid: composed of channel id and wqid within the channel. ++ * @dct: the dequeue command type. ++ */ ++void qbman_pull_desc_set_wq(struct qbman_pull_desc *d, uint32_t wqid, ++ enum qbman_pull_type_e dct); ++ ++/* qbman_pull_desc_set_channel() - Set channelid from which the dequeue command ++ * dequeues. ++ * @chid: the channel id to be dequeued. ++ * @dct: the dequeue command type. ++ */ ++void qbman_pull_desc_set_channel(struct qbman_pull_desc *d, uint32_t chid, ++ enum qbman_pull_type_e dct); ++ ++/** ++ * qbman_swp_pull() - Issue the pull dequeue command ++ * @s: the software portal object. ++ * @d: the software portal descriptor which has been configured with ++ * the set of qbman_pull_desc_set_*() calls. ++ * ++ * Return 0 for success, and -EBUSY if the software portal is not ready ++ * to do pull dequeue. ++ */ ++int qbman_swp_pull(struct qbman_swp *s, struct qbman_pull_desc *d); ++ ++/* -------------------------------- */ ++/* Polling DQRR for dequeue results */ ++/* -------------------------------- */ ++ ++/** ++ * qbman_swp_dqrr_next() - Get an valid DQRR entry. ++ * @s: the software portal object. ++ * ++ * Return NULL if there are no unconsumed DQRR entries. Return a DQRR entry ++ * only once, so repeated calls can return a sequence of DQRR entries, without ++ * requiring they be consumed immediately or in any particular order. ++ */ ++const struct qbman_result *qbman_swp_dqrr_next(struct qbman_swp *); ++ ++/** ++ * qbman_swp_dqrr_consume() - Consume DQRR entries previously returned from ++ * qbman_swp_dqrr_next(). ++ * @s: the software portal object. ++ * @dq: the DQRR entry to be consumed. ++ */ ++void qbman_swp_dqrr_consume(struct qbman_swp *s, const struct qbman_result *dq); ++ ++/** ++ * qbman_get_dqrr_idx() - Get dqrr index from the given dqrr ++ * @dqrr: the given dqrr object. ++ * ++ * Return dqrr index. ++ */ ++uint8_t qbman_get_dqrr_idx(struct qbman_result *dqrr); ++ ++/** ++ * qbman_get_dqrr_from_idx() - Use index to get the dqrr entry from the ++ * given portal ++ * @s: the given portal. ++ * @idx: the dqrr index. ++ * ++ * Return dqrr entry object. ++ */ ++struct qbman_result *qbman_get_dqrr_from_idx(struct qbman_swp *s, uint8_t idx); ++ ++/* ------------------------------------------------- */ ++/* Polling user-provided storage for dequeue results */ ++/* ------------------------------------------------- */ ++ ++/** ++ * qbman_result_has_new_result() - Check and get the dequeue response from the ++ * dq storage memory set in pull dequeue command ++ * @s: the software portal object. ++ * @dq: the dequeue result read from the memory. ++ * ++ * Only used for user-provided storage of dequeue results, not DQRR. For ++ * efficiency purposes, the driver will perform any required endianness ++ * conversion to ensure that the user's dequeue result storage is in host-endian ++ * format (whether or not that is the same as the little-endian format that ++ * hardware DMA'd to the user's storage). As such, once the user has called ++ * qbman_result_has_new_result() and been returned a valid dequeue result, ++ * they should not call it again on the same memory location (except of course ++ * if another dequeue command has been executed to produce a new result to that ++ * location). ++ * ++ * Return 1 for getting a valid dequeue result, or 0 for not getting a valid ++ * dequeue result. ++ */ ++int qbman_result_has_new_result(struct qbman_swp *s, ++ const struct qbman_result *dq); ++ ++/* -------------------------------------------------------- */ ++/* Parsing dequeue entries (DQRR and user-provided storage) */ ++/* -------------------------------------------------------- */ ++ ++/** ++ * qbman_result_is_DQ() - check the dequeue result is a dequeue response or not ++ * @dq: the dequeue result to be checked. ++ * ++ * DQRR entries may contain non-dequeue results, ie. notifications ++ */ ++int qbman_result_is_DQ(const struct qbman_result *); ++ ++/** ++ * qbman_result_is_SCN() - Check the dequeue result is notification or not ++ * @dq: the dequeue result to be checked. ++ * ++ * All the non-dequeue results (FQDAN/CDAN/CSCN/...) are "state change ++ * notifications" of one type or another. Some APIs apply to all of them, of the ++ * form qbman_result_SCN_***(). ++ */ ++static inline int qbman_result_is_SCN(const struct qbman_result *dq) ++{ ++ return !qbman_result_is_DQ(dq); ++} ++ ++/* Recognise different notification types, only required if the user allows for ++ * these to occur, and cares about them when they do. ++ */ ++ ++/** ++ * qbman_result_is_FQDAN() - Check for FQ Data Availability ++ * @dq: the qbman_result object. ++ * ++ * Return 1 if this is FQDAN. ++ */ ++int qbman_result_is_FQDAN(const struct qbman_result *dq); ++ ++/** ++ * qbman_result_is_CDAN() - Check for Channel Data Availability ++ * @dq: the qbman_result object to check. ++ * ++ * Return 1 if this is CDAN. ++ */ ++int qbman_result_is_CDAN(const struct qbman_result *dq); ++ ++/** ++ * qbman_result_is_CSCN() - Check for Congestion State Change ++ * @dq: the qbman_result object to check. ++ * ++ * Return 1 if this is CSCN. ++ */ ++int qbman_result_is_CSCN(const struct qbman_result *dq); ++ ++/** ++ * qbman_result_is_BPSCN() - Check for Buffer Pool State Change. ++ * @dq: the qbman_result object to check. ++ * ++ * Return 1 if this is BPSCN. ++ */ ++int qbman_result_is_BPSCN(const struct qbman_result *dq); ++ ++/** ++ * qbman_result_is_CGCU() - Check for Congestion Group Count Update. ++ * @dq: the qbman_result object to check. ++ * ++ * Return 1 if this is CGCU. ++ */ ++int qbman_result_is_CGCU(const struct qbman_result *dq); ++ ++/* Frame queue state change notifications; (FQDAN in theory counts too as it ++ * leaves a FQ parked, but it is primarily a data availability notification) ++ */ ++ ++/** ++ * qbman_result_is_FQRN() - Check for FQ Retirement Notification. ++ * @dq: the qbman_result object to check. ++ * ++ * Return 1 if this is FQRN. ++ */ ++int qbman_result_is_FQRN(const struct qbman_result *); ++ ++/** ++ * qbman_result_is_FQRNI() - Check for FQ Retirement Immediate ++ * @dq: the qbman_result object to check. ++ * ++ * Return 1 if this is FQRNI. ++ */ ++int qbman_result_is_FQRNI(const struct qbman_result *); ++ ++/** ++ * qbman_result_is_FQPN() - Check for FQ Park Notification ++ * @dq: the qbman_result object to check. ++ * ++ * Return 1 if this is FQPN. ++ */ ++int qbman_result_is_FQPN(const struct qbman_result *dq); ++ ++/* Parsing frame dequeue results (qbman_result_is_DQ() must be TRUE) ++ */ ++/* FQ empty */ ++#define QBMAN_DQ_STAT_FQEMPTY 0x80 ++/* FQ held active */ ++#define QBMAN_DQ_STAT_HELDACTIVE 0x40 ++/* FQ force eligible */ ++#define QBMAN_DQ_STAT_FORCEELIGIBLE 0x20 ++/* Valid frame */ ++#define QBMAN_DQ_STAT_VALIDFRAME 0x10 ++/* FQ ODP enable */ ++#define QBMAN_DQ_STAT_ODPVALID 0x04 ++/* Volatile dequeue */ ++#define QBMAN_DQ_STAT_VOLATILE 0x02 ++/* volatile dequeue command is expired */ ++#define QBMAN_DQ_STAT_EXPIRED 0x01 ++ ++/** ++ * qbman_result_DQ_flags() - Get the STAT field of dequeue response ++ * @dq: the dequeue result. ++ * ++ * Return the state field. ++ */ ++uint32_t qbman_result_DQ_flags(const struct qbman_result *dq); ++ ++/** ++ * qbman_result_DQ_is_pull() - Check whether the dq response is from a pull ++ * command. ++ * @dq: the dequeue result. ++ * ++ * Return 1 for volatile(pull) dequeue, 0 for static dequeue. ++ */ ++static inline int qbman_result_DQ_is_pull(const struct qbman_result *dq) ++{ ++ return (int)(qbman_result_DQ_flags(dq) & QBMAN_DQ_STAT_VOLATILE); ++} ++ ++/** ++ * qbman_result_DQ_is_pull_complete() - Check whether the pull command is ++ * completed. ++ * @dq: the dequeue result. ++ * ++ * Return boolean. ++ */ ++static inline int qbman_result_DQ_is_pull_complete( ++ const struct qbman_result *dq) ++{ ++ return (int)(qbman_result_DQ_flags(dq) & QBMAN_DQ_STAT_EXPIRED); ++} ++ ++/** ++ * qbman_result_DQ_seqnum() - Get the seqnum field in dequeue response ++ * seqnum is valid only if VALIDFRAME flag is TRUE ++ * @dq: the dequeue result. ++ * ++ * Return seqnum. ++ */ ++uint16_t qbman_result_DQ_seqnum(const struct qbman_result *dq); ++ ++/** ++ * qbman_result_DQ_odpid() - Get the seqnum field in dequeue response ++ * odpid is valid only if ODPVAILD flag is TRUE. ++ * @dq: the dequeue result. ++ * ++ * Return odpid. ++ */ ++uint16_t qbman_result_DQ_odpid(const struct qbman_result *dq); ++ ++/** ++ * qbman_result_DQ_fqid() - Get the fqid in dequeue response ++ * @dq: the dequeue result. ++ * ++ * Return fqid. ++ */ ++uint32_t qbman_result_DQ_fqid(const struct qbman_result *dq); ++ ++/** ++ * qbman_result_DQ_byte_count() - Get the byte count in dequeue response ++ * @dq: the dequeue result. ++ * ++ * Return the byte count remaining in the FQ. ++ */ ++uint32_t qbman_result_DQ_byte_count(const struct qbman_result *dq); ++ ++/** ++ * qbman_result_DQ_frame_count - Get the frame count in dequeue response ++ * @dq: the dequeue result. ++ * ++ * Return the frame count remaining in the FQ. ++ */ ++uint32_t qbman_result_DQ_frame_count(const struct qbman_result *dq); ++ ++/** ++ * qbman_result_DQ_fqd_ctx() - Get the frame queue context in dequeue response ++ * @dq: the dequeue result. ++ * ++ * Return the frame queue context. ++ */ ++uint64_t qbman_result_DQ_fqd_ctx(const struct qbman_result *dq); ++ ++/** ++ * qbman_result_DQ_fd() - Get the frame descriptor in dequeue response ++ * @dq: the dequeue result. ++ * ++ * Return the frame descriptor. ++ */ ++const struct qbman_fd *qbman_result_DQ_fd(const struct qbman_result *dq); ++ ++/* State-change notifications (FQDAN/CDAN/CSCN/...). */ ++ ++/** ++ * qbman_result_SCN_state() - Get the state field in State-change notification ++ * @scn: the state change notification. ++ * ++ * Return the state in the notifiation. ++ */ ++uint8_t qbman_result_SCN_state(const struct qbman_result *scn); ++ ++/** ++ * qbman_result_SCN_rid() - Get the resource id from the notification ++ * @scn: the state change notification. ++ * ++ * Return the resource id. ++ */ ++uint32_t qbman_result_SCN_rid(const struct qbman_result *scn); ++ ++/** ++ * qbman_result_SCN_ctx() - get the context from the notification ++ * @scn: the state change notification. ++ * ++ * Return the context. ++ */ ++uint64_t qbman_result_SCN_ctx(const struct qbman_result *scn); ++ ++/** ++ * qbman_result_SCN_state_in_mem() - Get the state in notification written ++ * in memory ++ * @scn: the state change notification. ++ * ++ * Return the state. ++ */ ++uint8_t qbman_result_SCN_state_in_mem(const struct qbman_result *scn); ++ ++/** ++ * qbman_result_SCN_rid_in_mem() - Get the resource id in notification written ++ * in memory. ++ * @scn: the state change notification. ++ * ++ * Return the resource id. ++ */ ++uint32_t qbman_result_SCN_rid_in_mem(const struct qbman_result *scn); ++ ++/* Type-specific "resource IDs". Mainly for illustration purposes, though it ++ * also gives the appropriate type widths. ++ */ ++/* Get the FQID from the FQDAN */ ++#define qbman_result_FQDAN_fqid(dq) qbman_result_SCN_rid(dq) ++/* Get the FQID from the FQRN */ ++#define qbman_result_FQRN_fqid(dq) qbman_result_SCN_rid(dq) ++/* Get the FQID from the FQRNI */ ++#define qbman_result_FQRNI_fqid(dq) qbman_result_SCN_rid(dq) ++/* Get the FQID from the FQPN */ ++#define qbman_result_FQPN_fqid(dq) qbman_result_SCN_rid(dq) ++/* Get the channel ID from the CDAN */ ++#define qbman_result_CDAN_cid(dq) ((uint16_t)qbman_result_SCN_rid(dq)) ++/* Get the CGID from the CSCN */ ++#define qbman_result_CSCN_cgid(dq) ((uint16_t)qbman_result_SCN_rid(dq)) ++ ++/** ++ * qbman_result_bpscn_bpid() - Get the bpid from BPSCN ++ * @scn: the state change notification. ++ * ++ * Return the buffer pool id. ++ */ ++uint16_t qbman_result_bpscn_bpid(const struct qbman_result *scn); ++ ++/** ++ * qbman_result_bpscn_has_free_bufs() - Check whether there are free ++ * buffers in the pool from BPSCN. ++ * @scn: the state change notification. ++ * ++ * Return the number of free buffers. ++ */ ++int qbman_result_bpscn_has_free_bufs(const struct qbman_result *scn); ++ ++/** ++ * qbman_result_bpscn_is_depleted() - Check BPSCN to see whether the ++ * buffer pool is depleted. ++ * @scn: the state change notification. ++ * ++ * Return the status of buffer pool depletion. ++ */ ++int qbman_result_bpscn_is_depleted(const struct qbman_result *scn); ++ ++/** ++ * qbman_result_bpscn_is_surplus() - Check BPSCN to see whether the buffer ++ * pool is surplus or not. ++ * @scn: the state change notification. ++ * ++ * Return the status of buffer pool surplus. ++ */ ++int qbman_result_bpscn_is_surplus(const struct qbman_result *scn); ++ ++/** ++ * qbman_result_bpscn_ctx() - Get the BPSCN CTX from BPSCN message ++ * @scn: the state change notification. ++ * ++ * Return the BPSCN context. ++ */ ++uint64_t qbman_result_bpscn_ctx(const struct qbman_result *scn); ++ ++/* Parsing CGCU */ ++/** ++ * qbman_result_cgcu_cgid() - Check CGCU resouce id, i.e. cgid ++ * @scn: the state change notification. ++ * ++ * Return the CGCU resource id. ++ */ ++uint16_t qbman_result_cgcu_cgid(const struct qbman_result *scn); ++ ++/** ++ * qbman_result_cgcu_icnt() - Get the I_CNT from CGCU ++ * @scn: the state change notification. ++ * ++ * Return instantaneous count in the CGCU notification. ++ */ ++uint64_t qbman_result_cgcu_icnt(const struct qbman_result *scn); ++ ++ /************/ ++ /* Enqueues */ ++ /************/ ++ ++/** ++ * struct qbman_eq_desc - structure of enqueue descriptor ++ * @dont_manipulate_directly: the 8 32bit data to represent the whole ++ * possible qbman enqueue setting in enqueue descriptor. ++ */ ++struct qbman_eq_desc { ++ uint32_t dont_manipulate_directly[8]; ++}; ++ ++/** ++ * struct qbman_eq_response - structure of enqueue response ++ * @dont_manipulate_directly: the 16 32bit data to represent the whole ++ * enqueue response. ++ */ ++struct qbman_eq_response { ++ uint32_t dont_manipulate_directly[16]; ++}; ++ ++/** ++ * qbman_eq_desc_clear() - Clear the contents of a descriptor to ++ * default/starting state. ++ * @d: the given enqueue descriptor. ++ */ ++void qbman_eq_desc_clear(struct qbman_eq_desc *d); ++ ++/* Exactly one of the following descriptor "actions" should be set. (Calling ++ * any one of these will replace the effect of any prior call to one of these.) ++ * - enqueue without order-restoration ++ * - enqueue with order-restoration ++ * - fill a hole in the order-restoration sequence, without any enqueue ++ * - advance NESN (Next Expected Sequence Number), without any enqueue ++ * 'respond_success' indicates whether an enqueue response should be DMA'd ++ * after success (otherwise a response is DMA'd only after failure). ++ * 'incomplete' indicates that other fragments of the same 'seqnum' are yet to ++ * be enqueued. ++ */ ++ ++/** ++ * qbman_eq_desc_set_no_orp() - Set enqueue descriptor without orp ++ * @d: the enqueue descriptor. ++ * @response_success: 1 = enqueue with response always; 0 = enqueue with ++ * rejections returned on a FQ. ++ */ ++void qbman_eq_desc_set_no_orp(struct qbman_eq_desc *d, int respond_success); ++/** ++ * qbman_eq_desc_set_orp() - Set order-resotration in the enqueue descriptor ++ * @d: the enqueue descriptor. ++ * @response_success: 1 = enqueue with response always; 0 = enqueue with ++ * rejections returned on a FQ. ++ * @opr_id: the order point record id. ++ * @seqnum: the order restoration sequence number. ++ * @incomplete: indiates whether this is the last fragments using the same ++ * sequeue number. ++ */ ++void qbman_eq_desc_set_orp(struct qbman_eq_desc *d, int respond_success, ++ uint32_t opr_id, uint32_t seqnum, int incomplete); ++ ++/** ++ * qbman_eq_desc_set_orp_hole() - fill a hole in the order-restoration sequence ++ * without any enqueue ++ * @d: the enqueue descriptor. ++ * @opr_id: the order point record id. ++ * @seqnum: the order restoration sequence number. ++ */ ++void qbman_eq_desc_set_orp_hole(struct qbman_eq_desc *d, uint32_t opr_id, ++ uint32_t seqnum); ++ ++/** ++ * qbman_eq_desc_set_orp_nesn() - advance NESN (Next Expected Sequence Number) ++ * without any enqueue ++ * @d: the enqueue descriptor. ++ * @opr_id: the order point record id. ++ * @seqnum: the order restoration sequence number. ++ */ ++void qbman_eq_desc_set_orp_nesn(struct qbman_eq_desc *d, uint32_t opr_id, ++ uint32_t seqnum); ++/** ++ * qbman_eq_desc_set_response() - Set the enqueue response info. ++ * @d: the enqueue descriptor ++ * @storage_phys: the physical address of the enqueue response in memory. ++ * @stash: indicate that the write allocation enabled or not. ++ * ++ * In the case where an enqueue response is DMA'd, this determines where that ++ * response should go. (The physical/DMA address is given for hardware's ++ * benefit, but software should interpret it as a "struct qbman_eq_response" ++ * data structure.) 'stash' controls whether or not the write to main-memory ++ * expresses a cache-warming attribute. ++ */ ++void qbman_eq_desc_set_response(struct qbman_eq_desc *d, ++ dma_addr_t storage_phys, ++ int stash); ++ ++/** ++ * qbman_eq_desc_set_token() - Set token for the enqueue command ++ * @d: the enqueue descriptor ++ * @token: the token to be set. ++ * ++ * token is the value that shows up in an enqueue response that can be used to ++ * detect when the results have been published. The easiest technique is to zero ++ * result "storage" before issuing an enqueue, and use any non-zero 'token' ++ * value. ++ */ ++void qbman_eq_desc_set_token(struct qbman_eq_desc *d, uint8_t token); ++ ++/** ++ * Exactly one of the following descriptor "targets" should be set. (Calling any ++ * one of these will replace the effect of any prior call to one of these.) ++ * - enqueue to a frame queue ++ * - enqueue to a queuing destination ++ * Note, that none of these will have any affect if the "action" type has been ++ * set to "orp_hole" or "orp_nesn". ++ */ ++/** ++ * qbman_eq_desc_set_fq() - Set Frame Queue id for the enqueue command ++ * @d: the enqueue descriptor ++ * @fqid: the id of the frame queue to be enqueued. ++ */ ++void qbman_eq_desc_set_fq(struct qbman_eq_desc *d, uint32_t fqid); ++ ++/** ++ * qbman_eq_desc_set_qd() - Set Queuing Destination for the enqueue command. ++ * @d: the enqueue descriptor ++ * @qdid: the id of the queuing destination to be enqueued. ++ * @qd_bin: the queuing destination bin ++ * @qd_prio: the queuing destination priority. ++ */ ++void qbman_eq_desc_set_qd(struct qbman_eq_desc *d, uint32_t qdid, ++ uint32_t qd_bin, uint32_t qd_prio); ++ ++/** ++ * qbman_eq_desc_set_eqdi() - enable/disable EQDI interrupt ++ * @d: the enqueue descriptor ++ * @enable: boolean to enable/disable EQDI ++ * ++ * Determines whether or not the portal's EQDI interrupt source should be ++ * asserted after the enqueue command is completed. ++ */ ++void qbman_eq_desc_set_eqdi(struct qbman_eq_desc *d, int enable); ++ ++/** ++ * qbman_eq_desc_set_dca() - Set DCA mode in the enqueue command. ++ * @d: the enqueue descriptor. ++ * @enable: enabled/disable DCA mode. ++ * @dqrr_idx: DCAP_CI, the DCAP consumer index. ++ * @park: determine the whether park the FQ or not ++ * ++ * Determines whether or not a portal DQRR entry should be consumed once the ++ * enqueue command is completed. (And if so, and the DQRR entry corresponds to a ++ * held-active (order-preserving) FQ, whether the FQ should be parked instead of ++ * being rescheduled.) ++ */ ++void qbman_eq_desc_set_dca(struct qbman_eq_desc *d, int enable, ++ uint32_t dqrr_idx, int park); ++ ++/** ++ * qbman_swp_enqueue() - Issue an enqueue command. ++ * @s: the software portal used for enqueue. ++ * @d: the enqueue descriptor. ++ * @fd: the frame descriptor to be enqueued. ++ * ++ * Please note that 'fd' should only be NULL if the "action" of the ++ * descriptor is "orp_hole" or "orp_nesn". ++ * ++ * Return 0 for a successful enqueue, -EBUSY if the EQCR is not ready. ++ */ ++int qbman_swp_enqueue(struct qbman_swp *s, const struct qbman_eq_desc *d, ++ const struct qbman_fd *fd); ++ ++/* TODO: ++ * qbman_swp_enqueue_thresh() - Set threshold for EQRI interrupt. ++ * @s: the software portal. ++ * @thresh: the threshold to trigger the EQRI interrupt. ++ * ++ * An EQRI interrupt can be generated when the fill-level of EQCR falls below ++ * the 'thresh' value set here. Setting thresh==0 (the default) disables. ++ */ ++int qbman_swp_enqueue_thresh(struct qbman_swp *s, unsigned int thresh); ++ ++ /*******************/ ++ /* Buffer releases */ ++ /*******************/ ++/** ++ * struct qbman_release_desc - The structure for buffer release descriptor ++ * @dont_manipulate_directly: the 32bit data to represent the whole ++ * possible settings of qbman release descriptor. ++ */ ++struct qbman_release_desc { ++ uint32_t dont_manipulate_directly[1]; ++}; ++ ++/** ++ * qbman_release_desc_clear() - Clear the contents of a descriptor to ++ * default/starting state. ++ * @d: the qbman release descriptor. ++ */ ++void qbman_release_desc_clear(struct qbman_release_desc *d); ++ ++/** ++ * qbman_release_desc_set_bpid() - Set the ID of the buffer pool to release to ++ * @d: the qbman release descriptor. ++ */ ++void qbman_release_desc_set_bpid(struct qbman_release_desc *d, uint32_t bpid); ++ ++/** ++ * qbman_release_desc_set_rcdi() - Determines whether or not the portal's RCDI ++ * interrupt source should be asserted after the release command is completed. ++ * @d: the qbman release descriptor. ++ */ ++void qbman_release_desc_set_rcdi(struct qbman_release_desc *d, int enable); ++ ++/** ++ * qbman_swp_release() - Issue a buffer release command. ++ * @s: the software portal object. ++ * @d: the release descriptor. ++ * @buffers: a pointer pointing to the buffer address to be released. ++ * @num_buffers: number of buffers to be released, must be less than 8. ++ * ++ * Return 0 for success, -EBUSY if the release command ring is not ready. ++ */ ++int qbman_swp_release(struct qbman_swp *s, const struct qbman_release_desc *d, ++ const uint64_t *buffers, unsigned int num_buffers); ++ ++/* TODO: ++ * qbman_swp_release_thresh() - Set threshold for RCRI interrupt ++ * @s: the software portal. ++ * @thresh: the threshold. ++ * An RCRI interrupt can be generated when the fill-level of RCR falls below ++ * the 'thresh' value set here. Setting thresh==0 (the default) disables. ++ */ ++int qbman_swp_release_thresh(struct qbman_swp *s, unsigned int thresh); ++ ++ /*******************/ ++ /* Buffer acquires */ ++ /*******************/ ++/** ++ * qbman_swp_acquire() - Issue a buffer acquire command. ++ * @s: the software portal object. ++ * @bpid: the buffer pool index. ++ * @buffers: a pointer pointing to the acquired buffer address|es. ++ * @num_buffers: number of buffers to be acquired, must be less than 8. ++ * ++ * Return 0 for success, or negative error code if the acquire command ++ * fails. ++ */ ++int qbman_swp_acquire(struct qbman_swp *s, uint32_t bpid, uint64_t *buffers, ++ unsigned int num_buffers); ++ ++ /*****************/ ++ /* FQ management */ ++ /*****************/ ++/** ++ * qbman_swp_fq_schedule() - Move the fq to the scheduled state. ++ * @s: the software portal object. ++ * @fqid: the index of frame queue to be scheduled. ++ * ++ * There are a couple of different ways that a FQ can end up parked state, ++ * This schedules it. ++ * ++ * Return 0 for success, or negative error code for failure. ++ */ ++int qbman_swp_fq_schedule(struct qbman_swp *s, uint32_t fqid); ++ ++/** ++ * qbman_swp_fq_force() - Force the FQ to fully scheduled state. ++ * @s: the software portal object. ++ * @fqid: the index of frame queue to be forced. ++ * ++ * Force eligible will force a tentatively-scheduled FQ to be fully-scheduled ++ * and thus be available for selection by any channel-dequeuing behaviour (push ++ * or pull). If the FQ is subsequently "dequeued" from the channel and is still ++ * empty at the time this happens, the resulting dq_entry will have no FD. ++ * (qbman_result_DQ_fd() will return NULL.) ++ * ++ * Return 0 for success, or negative error code for failure. ++ */ ++int qbman_swp_fq_force(struct qbman_swp *s, uint32_t fqid); ++ ++/** ++ * These functions change the FQ flow-control stuff between XON/XOFF. (The ++ * default is XON.) This setting doesn't affect enqueues to the FQ, just ++ * dequeues. XOFF FQs will remain in the tenatively-scheduled state, even when ++ * non-empty, meaning they won't be selected for scheduled dequeuing. If a FQ is ++ * changed to XOFF after it had already become truly-scheduled to a channel, and ++ * a pull dequeue of that channel occurs that selects that FQ for dequeuing, ++ * then the resulting dq_entry will have no FD. (qbman_result_DQ_fd() will ++ * return NULL.) ++ */ ++/** ++ * qbman_swp_fq_xon() - XON the frame queue. ++ * @s: the software portal object. ++ * @fqid: the index of frame queue. ++ * ++ * Return 0 for success, or negative error code for failure. ++ */ ++int qbman_swp_fq_xon(struct qbman_swp *s, uint32_t fqid); ++/** ++ * qbman_swp_fq_xoff() - XOFF the frame queue. ++ * @s: the software portal object. ++ * @fqid: the index of frame queue. ++ * ++ * Return 0 for success, or negative error code for failure. ++ */ ++int qbman_swp_fq_xoff(struct qbman_swp *s, uint32_t fqid); ++ ++ /**********************/ ++ /* Channel management */ ++ /**********************/ ++ ++/** ++ * If the user has been allocated a channel object that is going to generate ++ * CDANs to another channel, then these functions will be necessary. ++ * CDAN-enabled channels only generate a single CDAN notification, after which ++ * it they need to be reenabled before they'll generate another. (The idea is ++ * that pull dequeuing will occur in reaction to the CDAN, followed by a ++ * reenable step.) Each function generates a distinct command to hardware, so a ++ * combination function is provided if the user wishes to modify the "context" ++ * (which shows up in each CDAN message) each time they reenable, as a single ++ * command to hardware. ++ */ ++ ++/** ++ * qbman_swp_CDAN_set_context() - Set CDAN context ++ * @s: the software portal object. ++ * @channelid: the channel index. ++ * @ctx: the context to be set in CDAN. ++ * ++ * Return 0 for success, or negative error code for failure. ++ */ ++int qbman_swp_CDAN_set_context(struct qbman_swp *s, uint16_t channelid, ++ uint64_t ctx); ++ ++/** ++ * qbman_swp_CDAN_enable() - Enable CDAN for the channel. ++ * @s: the software portal object. ++ * @channelid: the index of the channel to generate CDAN. ++ * ++ * Return 0 for success, or negative error code for failure. ++ */ ++int qbman_swp_CDAN_enable(struct qbman_swp *s, uint16_t channelid); ++ ++/** ++ * qbman_swp_CDAN_disable() - disable CDAN for the channel. ++ * @s: the software portal object. ++ * @channelid: the index of the channel to generate CDAN. ++ * ++ * Return 0 for success, or negative error code for failure. ++ */ ++int qbman_swp_CDAN_disable(struct qbman_swp *s, uint16_t channelid); ++ ++/** ++ * qbman_swp_CDAN_set_context_enable() - Set CDAN contest and enable CDAN ++ * @s: the software portal object. ++ * @channelid: the index of the channel to generate CDAN. ++ * @ctx: the context set in CDAN. ++ * ++ * Return 0 for success, or negative error code for failure. ++ */ ++int qbman_swp_CDAN_set_context_enable(struct qbman_swp *s, uint16_t channelid, ++ uint64_t ctx); ++int qbman_swp_fill_ring(struct qbman_swp *s, ++ const struct qbman_eq_desc *d, ++ const struct qbman_fd *fd, ++ uint8_t burst_index); ++int qbman_swp_flush_ring(struct qbman_swp *s); ++void qbman_sync(void); ++int qbman_swp_send_multiple(struct qbman_swp *s, ++ const struct qbman_eq_desc *d, ++ const struct qbman_fd *fd, ++ int frames_to_send); ++ ++int qbman_check_command_complete(struct qbman_swp *s, ++ const struct qbman_result *dq); ++#endif /* !_FSL_QBMAN_PORTAL_H */ +diff --git a/drivers/net/dpaa2/rte_eth_dpaa2_pvt.h b/drivers/net/dpaa2/rte_eth_dpaa2_pvt.h +new file mode 100644 +index 0000000..bd5d4d5 +--- /dev/null ++++ b/drivers/net/dpaa2/rte_eth_dpaa2_pvt.h +@@ -0,0 +1,330 @@ ++/*- ++ * BSD LICENSE ++ * ++ * Copyright (c) 2014 Freescale Semiconductor, Inc. All rights reserved. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * * Neither the name of Freescale Semiconductor nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#ifndef _RTE_ETH_DPAA2_PVT_H_ ++#define _RTE_ETH_DPAA2_PVT_H_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++typedef uint64_t dma_addr_t; ++ ++#define FALSE 0 ++#define TRUE 1 ++#ifndef false ++#define false FALSE ++#endif ++#ifndef true ++#define true TRUE ++#endif ++#define lower_32_bits(x) ((uint32_t)(x)) ++#define upper_32_bits(x) ((uint32_t)(((x) >> 16) >> 16)) ++ ++#ifndef ETH_ADDR_LEN ++#define ETH_ADDR_LEN 6 ++#endif ++#ifndef ETH_VLAN_HLEN ++#define ETH_VLAN_HLEN 4 /** < Vlan Header Length */ ++#endif ++ ++#define NUM_MAX_RECV_FRAMES 16 ++ ++#define MC_PORTAL_INDEX 0 ++#define NUM_DPIO_REGIONS 2 ++#define NUM_DQS_PER_QUEUE 2 ++#define MC_PORTALS_BASE_PADDR 0x00080C000000ULL ++#define MC_PORTAL_STRIDE 0x10000 ++#define MC_PORTAL_SIZE 64 ++#define MC_PORTAL_ID_TO_PADDR(portal_id) \ ++(MC_PORTALS_BASE_PADDR + (portal_id) * MC_PORTAL_STRIDE) ++ ++struct dpaa2_dpio_dev { ++ TAILQ_ENTRY(dpaa2_dpio_dev) next; /**< Pointer to Next device instance */ ++ uint16_t index; /**< Index of a instance in the list */ ++ rte_atomic16_t ref_count; /**< How many thread contexts are sharing this.*/ ++ struct fsl_mc_io *dpio; /** handle to DPIO portal object */ ++ uint16_t token; ++ struct qbman_swp *sw_portal; /** SW portal object */ ++ const struct qbman_result *dqrr[4]; /**< DQRR Entry for this SW portal */ ++ pthread_mutex_t lock; /** Required when Portal is shared */ ++ void *mc_portal; /**< MC Portal for configuring this device */ ++ uintptr_t qbman_portal_ce_paddr; /**< Physical address of Cache Enabled Area */ ++ uintptr_t ce_size; /**< Size of the CE region */ ++ uintptr_t qbman_portal_ci_paddr; /**< Physical address of Cache Inhibit Area */ ++ uintptr_t ci_size; /**< Size of the CI region */ ++ void *intr_handle; ++ int32_t vfio_fd; /**< File descriptor received via VFIO */ ++ int32_t hw_id; /**< An unique ID of this DPIO device instance */ ++}; ++ ++struct queue_storage_info_t { ++ struct qbman_result *dq_storage[NUM_DQS_PER_QUEUE]; ++ struct qbman_result *active_dqs; ++ int toggle; ++}; ++ ++struct thread_io_info_t { ++ struct dpaa2_dpio_dev *dpio_dev; ++ struct dpaa2_dpio_dev *sec_dpio_dev; ++ struct qbman_result *global_active_dqs; ++}; ++ ++/*! Global per thread DPIO portal */ ++extern __thread struct thread_io_info_t thread_io_info; ++/*! Global MCP list */ ++extern void *(*mcp_ptr_list); ++ ++/* Refer to Table 7-3 in SEC BG */ ++struct qbman_fle { ++ uint32_t addr_lo; ++ uint32_t addr_hi; ++ uint32_t length; ++ /* FMT must be 00, MSB is final bit */ ++ uint32_t fin_bpid_offset; ++ uint32_t frc; ++ uint32_t reserved[3]; /* Not used currently */ ++}; ++ ++/* Maximum release/acquire from QBMAN */ ++#define DPAA2_MBUF_MAX_ACQ_REL 7 ++ ++#define MAX_BPID 256 ++ ++/*Macros to define operations on FD*/ ++#define DPAA2_SET_FD_ADDR(fd, addr) \ ++ fd->simple.addr_lo = lower_32_bits((uint64_t)addr); \ ++ fd->simple.addr_hi = upper_32_bits((uint64_t)addr); ++#define DPAA2_SET_FD_LEN(fd, length) fd->simple.len = length ++#define DPAA2_SET_FD_BPID(fd, bpid) fd->simple.bpid_offset |= bpid; ++#define DPAA2_SET_FD_IVP(fd) ((fd->simple.bpid_offset |= 0x00004000)) ++#define DPAA2_SET_FD_OFFSET(fd, offset) (fd->simple.bpid_offset |= (uint32_t)(offset) << 16); ++#define DPAA2_SET_FD_INTERNAL_JD(fd, len) fd->simple.frc = (0x80000000 | (len)); ++#define DPAA2_SET_FD_FRC(fd, frc) fd->simple.frc = frc; ++#define DPAA2_RESET_FD_CTRL(fd) fd->simple.ctrl = 0; ++ ++#define DPAA2_SET_FD_ASAL(fd, asal) (fd->simple.ctrl |= (asal << 16)) ++#define DPAA2_SET_FD_FLC(fd, addr) \ ++ fd->simple.flc_lo = lower_32_bits((uint64_t)addr); \ ++ fd->simple.flc_hi = upper_32_bits((uint64_t)addr); ++#define DPAA2_SET_FLE_INTERNAL_JD(fle, len) fle->frc = (0x80000000 | (len)); ++#define DPAA2_GET_FLE_ADDR(fle) \ ++ (uint64_t)((((uint64_t)(fle->addr_hi)) << 32) + fle->addr_lo) ++#define DPAA2_SET_FLE_ADDR(fle, addr) \ ++ fle->addr_lo = lower_32_bits((uint64_t)addr); \ ++ fle->addr_hi = upper_32_bits((uint64_t)addr); ++#define DPAA2_SET_FLE_OFFSET(fle, offset) (fle)->fin_bpid_offset |= (uint32_t)(offset) << 16; ++#define DPAA2_SET_FLE_BPID(fle, bpid) (fle)->fin_bpid_offset |= (uint64_t)bpid; ++#define DPAA2_GET_FLE_BPID(fle, bpid) (fle->fin_bpid_offset & 0x000000ff) ++#define DPAA2_SET_FLE_FIN(fle) fle->fin_bpid_offset |= (uint64_t)1 << 31; ++#define DPAA2_SET_FLE_IVP(fle) (((fle)->fin_bpid_offset |= 0x00004000)) ++#define DPAA2_SET_FD_COMPOUND_FMT(fd) \ ++ fd->simple.bpid_offset |= (uint32_t)1 << 28; ++#define DPAA2_GET_FD_ADDR(fd) \ ++ (uint64_t)((((uint64_t)(fd->simple.addr_hi)) << 32) + fd->simple.addr_lo) ++#define DPAA2_GET_FD_LEN(fd) (fd->simple.len) ++#define DPAA2_GET_FD_BPID(fd) ((fd->simple.bpid_offset & 0x00003FFF)) ++#define DPAA2_GET_FD_IVP(fd) ((fd->simple.bpid_offset & 0x00004000) >> 14) ++#define DPAA2_GET_FD_OFFSET(fd) ((fd->simple.bpid_offset & 0x0FFF0000) >> 16) ++#define DPAA2_GET_FD_FRC(fd) (fd->simple.frc) ++#define DPAA2_GET_FD_FLC(fd) \ ++ (uint64_t)((((uint64_t)(fd->simple.flc_hi)) << 32) + fd->simple.flc_lo) ++ ++#define DPAA2_SET_FLE_SG_EXT(fle) fle->fin_bpid_offset |= (uint64_t)1 << 29; ++#define DPAA2_IS_SET_FLE_SG_EXT(fle) \ ++ (fle->fin_bpid_offset & ((uint64_t)1 << 29)) ? 1 : 0 ++ ++#define DPAA2_INLINE_MBUF_FROM_BUF(buf, meta_data_size) \ ++ ((struct rte_mbuf *)((uint64_t)buf - meta_data_size)) ++#define DPAA2_BUF_FROM_INLINE_MBUF(mbuf, meta_data_size) \ ++ ((uint8_t *)((uint64_t)mbuf + meta_data_size)) ++ ++#define DPAA2_ASAL_VAL (DPAA2_MBUF_HW_ANNOTATION / 64) ++ ++/*Macros to define QBMAN enqueue options */ ++#define DPAA2_ETH_EQ_DISABLE 0 /*!< Dont Enqueue the Frame */ ++#define DPAA2_ETH_EQ_RESP_ON_SUCC 1 /*!< Enqueue the Frame with ++ response after success*/ ++#define DPAA2_ETH_EQ_RESP_ON_FAIL 2 /*!< Enqueue the Frame with ++ response after failure*/ ++#define DPAA2_ETH_EQ_NO_RESP 3 /*!< Enqueue the Frame without ++ response*/ ++/* Only Enqueue Error responses will be ++ * pushed on FQID_ERR of Enqueue FQ */ ++#define DPAA2_EQ_RESP_ERR_FQ 0 ++/* All Enqueue responses will be pushed on address ++ * set with qbman_eq_desc_set_response */ ++#define DPAA2_EQ_RESP_ALWAYS 1 ++ ++#define DPAA2_MAX_BUF_POOLS 8 ++ ++struct dpbp_node { ++ struct dpbp_node *next; ++ struct fsl_mc_io dpbp; ++ uint16_t token; ++ int dpbp_id; ++}; ++ ++struct buf_pool_cfg { ++ void *addr; /*!< The address from where DPAA2 will carve out the ++ * buffers. 'addr' should be 'NULL' if user wants ++ * to create buffers from the memory which user ++ * asked DPAA2 to reserve during 'nadk init' */ ++ phys_addr_t phys_addr; /*!< corresponding physical address ++ * of the memory provided in addr */ ++ uint32_t num; /*!< number of buffers */ ++ uint32_t size; /*!< size of each buffer. 'size' should include ++ * any headroom to be reserved and alignment */ ++ uint16_t align; /*!< Buffer alignment (in bytes) */ ++ uint16_t bpid; /*!< The buffer pool id. This will be filled ++ *in by DPAA2 for each buffer pool */ ++}; ++ ++struct buf_pool { ++ uint32_t size; ++ uint32_t num_bufs; ++ uint16_t bpid; ++ uint8_t *h_bpool_mem; ++ struct rte_mempool *mp; ++ struct dpbp_node *dpbp_node; ++}; ++ ++/*! ++ * Buffer pool list configuration structure. User need to give DPAA2 the ++ * valid number of 'num_buf_pools'. ++ */ ++struct dpaa2_bp_list_cfg { ++ struct buf_pool_cfg buf_pool; /* Configuration ++ * of each buffer pool */ ++}; ++ ++struct dpaa2_bp_list { ++ struct dpaa2_bp_list *next; ++ struct rte_mempool *mp; ++ struct buf_pool buf_pool; ++}; ++ ++struct bp_info { ++ uint32_t meta_data_size; ++ uint32_t bpid; ++ struct dpaa2_bp_list *bp_list; ++}; ++ ++#define mempool_to_bpinfo(mp) ((struct bp_info *)mp->pool_data) ++#define mempool_to_bpid(mp) ((mempool_to_bpinfo(mp))->bpid) ++ ++extern struct dpaa2_bp_list *h_bp_list; ++ ++/* todo - this is costly, need to write a fast coversion routine */ ++static void *dpaa2_mem_ptov(phys_addr_t paddr) ++{ ++ const struct rte_memseg *memseg = rte_eal_get_physmem_layout(); ++ int i; ++ ++ for (i = 0; i < RTE_MAX_MEMSEG && memseg[i].addr_64 != 0; i++) { ++ if (paddr >= memseg[i].phys_addr && ++ (char *)paddr < (char *)memseg[i].phys_addr + memseg[i].len) ++ return (void *)(memseg[i].addr_64 + (paddr - memseg[i].phys_addr)); ++ } ++ return NULL; ++} ++ ++static phys_addr_t dpaa2_mem_vtop(uint64_t vaddr) ++{ ++ const struct rte_memseg *memseg = rte_eal_get_physmem_layout(); ++ int i; ++ ++ for (i = 0; i < RTE_MAX_MEMSEG && memseg[i].addr_64 != 0; i++) { ++ if (vaddr >= memseg[i].addr_64 && ++ vaddr < memseg[i].addr_64 + memseg[i].len) ++ return memseg[i].phys_addr + (vaddr - memseg[i].addr_64); ++ } ++ return (phys_addr_t)(NULL); ++} ++ ++#ifdef RTE_LIBRTE_DPAA2_USE_PHYS_IOVA ++/* ++ * When we are using Physical addresses as IO Virtual Addresses, ++ * we call conversion routines nadk_mem_vtop & nadk_mem_ptov wherever required. ++ * These routines are called with help of below MACRO's ++ */ ++ ++#define DPAA2_MBUF_VADDR_TO_IOVA(mbuf) (mbuf->buf_physaddr) ++#define DPAA2_OP_VADDR_TO_IOVA(op) (op->phys_addr) ++ ++/** ++ * macro to convert Virtual address to IOVA ++ */ ++#define DPAA2_VADDR_TO_IOVA(_vaddr) dpaa2_mem_vtop((uint64_t)(_vaddr)) ++ ++/** ++ * macro to convert IOVA to Virtual address ++ */ ++#define DPAA2_IOVA_TO_VADDR(_iova) dpaa2_mem_ptov((phys_addr_t)(_iova)) ++ ++/** ++ * macro to convert modify the memory containing Virtual address to IOVA ++ */ ++#define DPAA2_MODIFY_VADDR_TO_IOVA(_mem, _type) \ ++ {_mem = (_type)(dpaa2_mem_vtop((uint64_t)(_mem))); } ++ ++/** ++ * macro to convert modify the memory containing IOVA to Virtual address ++ */ ++#define DPAA2_MODIFY_IOVA_TO_VADDR(_mem, _type) \ ++ {_mem = (_type)(dpaa2_mem_ptov((phys_addr_t)(_mem))); } ++ ++#else ++#define DPAA2_MBUF_VADDR_TO_IOVA(mbuf) (mbuf->buf_addr) ++#define DPAA2_OP_VADDR_TO_IOVA(op) (op) ++ ++#define DPAA2_VADDR_TO_IOVA(_vaddr) (_vaddr) ++#define DPAA2_IOVA_TO_VADDR(_iova) (_iova) ++#define DPAA2_MODIFY_VADDR_TO_IOVA(_mem, _type) ++#define DPAA2_MODIFY_IOVA_TO_VADDR(_mem, _type) ++#endif ++ ++/* Function definitions for Mempool operations */ ++int hw_mbuf_init(struct rte_mempool *mp, void *_m); ++int hw_mbuf_free_bulk(struct rte_mempool *pool, void * const *obj_table, ++ unsigned n); ++int hw_mbuf_alloc_bulk(struct rte_mempool *pool, void **obj_table, ++ unsigned count); ++int hw_mbuf_create_pool(struct rte_mempool *mp); ++unsigned hw_mbuf_get_count(const struct rte_mempool *mp); ++ ++#endif +diff --git a/drivers/net/dpaa2/rte_eth_dpbp.c b/drivers/net/dpaa2/rte_eth_dpbp.c +new file mode 100644 +index 0000000..a4d29c9 +--- /dev/null ++++ b/drivers/net/dpaa2/rte_eth_dpbp.c +@@ -0,0 +1,377 @@ ++/*- ++ * BSD LICENSE ++ * ++ * Copyright (c) 2014 Freescale Semiconductor, Inc. All rights reserved. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * * Neither the name of Freescale Semiconductor nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "rte_pci.h" ++#include "rte_memzone.h" ++ ++#include "rte_eth_dpaa2_pvt.h" ++#include "fsl_qbman_portal.h" ++#include ++ ++#include ++#include "dpaa2_logs.h" ++ ++static struct dpbp_node *g_dpbp_list; ++static struct dpbp_node *avail_dpbp; ++ ++struct bp_info bpid_info[MAX_BPID]; ++ ++struct dpaa2_bp_list *h_bp_list; ++ ++int ++dpaa2_create_dpbp_device( ++ int dpbp_id) ++{ ++ struct dpbp_node *dpbp_node; ++ int ret; ++ ++ /* Allocate DPAA2 dpbp handle */ ++ dpbp_node = (struct dpbp_node *)malloc(sizeof(struct dpbp_node)); ++ if (!dpbp_node) { ++ PMD_DRV_LOG(ERR, "Memory allocation failed for DPBP Device\n"); ++ return -1; ++ } ++ ++ /* Open the dpbp object */ ++ dpbp_node->dpbp.regs = mcp_ptr_list[MC_PORTAL_INDEX]; ++ ret = dpbp_open(&dpbp_node->dpbp, CMD_PRI_LOW, dpbp_id, &dpbp_node->token); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Resource allocation failure with err code: %d", ++ ret); ++ free(dpbp_node); ++ return -1; ++ } ++ ++ /* Clean the device first */ ++ ret = dpbp_reset(&dpbp_node->dpbp, CMD_PRI_LOW, dpbp_node->token); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Failure cleaning dpbp device with" ++ "error code %d\n", ret); ++ return -1; ++ } ++ ++ dpbp_node->dpbp_id = dpbp_id; ++ /* Add the dpbp handle into the global list */ ++ dpbp_node->next = g_dpbp_list; ++ g_dpbp_list = dpbp_node; ++ avail_dpbp = g_dpbp_list; ++ ++ PMD_DRV_LOG(INFO, "Buffer resource initialized"); ++ ++ return 0; ++} ++ ++int hw_mbuf_create_pool(struct rte_mempool *mp) ++{ ++ struct dpaa2_bp_list *bp_list; ++ struct dpbp_attr dpbp_attr; ++ uint32_t bpid; ++ int ret; ++ ++ if (!avail_dpbp) { ++ PMD_DRV_LOG(ERR, "DPAA2 resources not available\n"); ++ return -1; ++ } ++ ++ ret = dpbp_enable(&avail_dpbp->dpbp, CMD_PRI_LOW, avail_dpbp->token); ++ if (ret != 0) { ++ PMD_DRV_LOG(ERR, "Resource enable failure with" ++ "err code: %d\n", ret); ++ return -1; ++ } ++ ++ ret = dpbp_get_attributes(&avail_dpbp->dpbp, CMD_PRI_LOW, ++ avail_dpbp->token, &dpbp_attr); ++ if (ret != 0) { ++ PMD_DRV_LOG(ERR, "Resource read failure with" ++ "err code: %d\n", ret); ++ ret = dpbp_disable(&avail_dpbp->dpbp, CMD_PRI_LOW, ++ avail_dpbp->token); ++ return -1; ++ } ++ ++ /* Allocate the bp_list which will be added into global_bp_list */ ++ bp_list = (struct dpaa2_bp_list *)malloc(sizeof(struct dpaa2_bp_list)); ++ if (!bp_list) { ++ PMD_DRV_LOG(ERR, "No heap memory available\n"); ++ return -1; ++ } ++ ++ /* Set parameters of buffer pool list */ ++ bp_list->buf_pool.num_bufs = mp->size; ++ bp_list->buf_pool.size = mp->elt_size ++ - sizeof(struct rte_mbuf) - rte_pktmbuf_priv_size(mp); ++ bp_list->buf_pool.bpid = dpbp_attr.bpid; ++ bp_list->buf_pool.h_bpool_mem = NULL; ++ bp_list->buf_pool.mp = mp; ++ bp_list->buf_pool.dpbp_node = avail_dpbp; ++ bp_list->next = h_bp_list; ++ ++ bpid = dpbp_attr.bpid; ++ ++ /* Increment the available DPBP */ ++ avail_dpbp = avail_dpbp->next; ++ ++ bpid_info[bpid].meta_data_size = sizeof(struct rte_mbuf) ++ + rte_pktmbuf_priv_size(mp); ++ bpid_info[bpid].bp_list = bp_list; ++ bpid_info[bpid].bpid = bpid; ++ ++ mp->pool_data = (void *)&bpid_info[bpid]; ++ ++ PMD_DRV_LOG(INFO, "BP List created for bpid =%d\n", dpbp_attr.bpid); ++ ++ h_bp_list = bp_list; ++ /* TODO: Replace with mp->pool_data->flags after creating appropriate ++ * pool_data structure ++ */ ++ mp->flags |= MEMPOOL_F_HW_PKT_POOL; ++ return 0; ++} ++ ++void hw_mbuf_free_pool(struct rte_mempool *mp __rte_unused) ++{ ++ /* TODO: ++ * 1. Release bp_list memory allocation ++ * 2. opposite of dpbp_enable() ++ * ++ */ ++ struct dpaa2_bp_list *bp; ++ ++ /* Iterate over h_bp_list linked list and release each element */ ++ while (h_bp_list) { ++ bp = h_bp_list; ++ h_bp_list = bp->next; ++ ++ /* TODO: Should be changed to rte_free */ ++ free(bp); ++ } ++ ++ PMD_DRV_LOG(DEBUG, "(%s) called\n", __func__); ++ return; ++} ++ ++static inline void dpaa2_mbuf_release(uint64_t buf, uint32_t bpid) ++{ ++ struct qbman_release_desc releasedesc; ++ struct qbman_swp *swp; ++ int ret; ++ ++ if (!thread_io_info.dpio_dev) { ++ ret = dpaa2_affine_qbman_swp(); ++ if (ret != 0) { ++ PMD_DRV_LOG(ERR, "Failed to allocate IO portal"); ++ return; ++ } ++ } ++ swp = thread_io_info.dpio_dev->sw_portal; ++ ++ /* Create a release descriptor required for releasing ++ * buffers into BMAN */ ++ qbman_release_desc_clear(&releasedesc); ++ qbman_release_desc_set_bpid(&releasedesc, bpid); ++ ++ do { ++ /* Release buffer into the BMAN */ ++ ret = qbman_swp_release(swp, &releasedesc, &buf, 1); ++ } while (ret == -EBUSY); ++ PMD_TX_FREE_LOG(DEBUG, "Released %p address to BMAN\n", buf); ++} ++ ++int hw_mbuf_alloc_bulk(struct rte_mempool *pool, ++ void **obj_table, unsigned count) ++{ ++#ifdef RTE_LIBRTE_DPAA2_DEBUG_DRIVER ++ static int alloc; ++#endif ++ struct qbman_swp *swp; ++ uint32_t mbuf_size; ++ uint16_t bpid; ++ uint64_t bufs[RTE_MEMPOOL_CACHE_MAX_SIZE + 1]; ++ int ret; ++ unsigned i, n = 0; ++ struct bp_info *bp_info; ++ ++ PMD_DRV_LOG_RAW(INFO, "%s/n", __func__); ++ bp_info = mempool_to_bpinfo(pool); ++ ++ if (!(bp_info->bp_list)) { ++ printf("\nDPAA2 buffer pool not configured\n"); ++ return -2; ++ } ++ ++ bpid = bp_info->bpid; ++ ++ if (!thread_io_info.dpio_dev) { ++ ret = dpaa2_affine_qbman_swp(); ++ if (ret != 0) { ++ PMD_DRV_LOG(ERR, "Failed to allocate IO portal"); ++ return -1; ++ } ++ } ++ swp = thread_io_info.dpio_dev->sw_portal; ++ ++ /* if number of buffers requested is less than 7 */ ++ if (count < DPAA2_MBUF_MAX_ACQ_REL) { ++ ret = qbman_swp_acquire(swp, bpid, &bufs[n], count); ++ if (ret <= 0) { ++ PMD_DRV_LOG(ERR, "Failed to allocate buffers %d", ret); ++ return -1; ++ } ++ n = ret; ++ goto set_buf; ++ } ++ ++ while (n < count) { ++ ret = 0; ++ /* Acquire is all-or-nothing, so we drain in 7s, ++ * then the remainder. ++ */ ++ if ((count - n) > DPAA2_MBUF_MAX_ACQ_REL) { ++ ret = qbman_swp_acquire(swp, bpid, &bufs[n], ++ DPAA2_MBUF_MAX_ACQ_REL); ++ if (ret == DPAA2_MBUF_MAX_ACQ_REL) { ++ n += ret; ++ } ++ } else { ++ ret = qbman_swp_acquire(swp, bpid, &bufs[n], count - n); ++ if (ret > 0) { ++ PMD_DRV_LOG(DEBUG, "Drained buffer: %x", ++ bufs[n]); ++ n += ret; ++ } ++ } ++ /* In case of less than requested number of buffers available ++ * in pool, qbman_swp_acquire returns 0 ++ */ ++ if (ret <= 0) { ++ PMD_DRV_LOG(WARNING, "Buffer aquire failed with" ++ "err code: %d", ret); ++ break; ++ } ++ } ++ ++ /* This function either returns expected buffers or error */ ++ if (count != n) { ++ i = 0; ++ /* Releasing all buffers allocated */ ++ while (i < n) { ++ dpaa2_mbuf_release(bufs[i], bpid); ++ i++; ++ } ++ return -1; ++ } ++ ++ if (ret < 0 || n == 0) { ++ PMD_DRV_LOG_RAW(ERR, "Failed to allocate buffers %d", ret); ++ return -1; ++ } ++set_buf: ++ ++ mbuf_size = sizeof(struct rte_mbuf) + rte_pktmbuf_priv_size(pool); ++ ++ for (i = 0; i < n; i++) { ++ DPAA2_MODIFY_IOVA_TO_VADDR(bufs[i], uint64_t); ++ obj_table[i] = (struct rte_mbuf *)(bufs[i] - mbuf_size); ++ PMD_DRV_LOG(DEBUG, "Acquired %p address %p from BMAN\n", ++ (void *)bufs[i], (void *)obj_table[i]); ++ } ++ ++#ifdef RTE_LIBRTE_DPAA2_DEBUG_DRIVER ++ alloc += n; ++ PMD_DRV_LOG_RAW(INFO, "Total = %d , req = %d done = %d", ++ alloc, count, n); ++#endif ++ return 0; ++} ++ ++int hw_mbuf_free_bulk(struct rte_mempool *pool, void * const *obj_table, ++ unsigned n) ++{ ++ unsigned i; ++ struct bp_info *bp_info; ++ ++ PMD_DRV_LOG_RAW(INFO, "%s/n", __func__); ++ ++ bp_info = mempool_to_bpinfo(pool); ++ if (!(bp_info->bp_list)) { ++ PMD_DRV_LOG(INFO, "DPAA2 buffer pool not configured\n"); ++ return -1; ++ } ++ /* TODO - optimize it */ ++ for (i = 0; i < n; i++) { ++#ifdef RTE_LIBRTE_DPAA2_USE_PHYS_IOVA ++ dpaa2_mbuf_release( ++ (uint64_t)rte_mempool_virt2phy(pool, obj_table[i]) ++ + bp_info->meta_data_size, bp_info->bpid); ++#else ++ dpaa2_mbuf_release((uint64_t)obj_table[i] ++ + bp_info->meta_data_size, bp_info->bpid); ++#endif ++ ++ } ++ ++ return 0; ++} ++ ++unsigned hw_mbuf_get_count(const struct rte_mempool *mp __rte_unused) ++{ ++ /* TODO: incomplete */ ++ return 0; ++} ++ ++struct rte_mempool_ops dpaa2_mpool_ops = { ++ .name = "dpaa2", ++ .alloc = hw_mbuf_create_pool, ++ .free = hw_mbuf_free_pool, ++ .enqueue = hw_mbuf_free_bulk, ++ .dequeue = hw_mbuf_alloc_bulk, ++ .get_count = hw_mbuf_get_count, ++}; ++ ++MEMPOOL_REGISTER_OPS(dpaa2_mpool_ops); +diff --git a/drivers/net/dpaa2/rte_eth_dpio.c b/drivers/net/dpaa2/rte_eth_dpio.c +new file mode 100644 +index 0000000..2d06923 +--- /dev/null ++++ b/drivers/net/dpaa2/rte_eth_dpio.c +@@ -0,0 +1,336 @@ ++/*- ++ * BSD LICENSE ++ * ++ * Copyright (c) 2014 Freescale Semiconductor, Inc. All rights reserved. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * * Neither the name of Freescale Semiconductor nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "rte_pci.h" ++#include "rte_memzone.h" ++#include ++ ++#include "rte_eth_dpaa2_pvt.h" ++#include "fsl_qbman_portal.h" ++#include ++ ++#include ++#include "dpaa2_logs.h" ++ ++#define NUM_HOST_CPUS RTE_MAX_LCORE ++ ++__thread struct thread_io_info_t thread_io_info; ++ ++TAILQ_HEAD(dpio_device_list, dpaa2_dpio_dev); ++static struct dpio_device_list *dpio_dev_list; /*!< DPIO device list */ ++static uint32_t io_space_count; ++ ++/*Stashing Macros*/ ++#define DPAA2_CORE_CLUSTER_BASE 0x04 ++#define DPAA2_CORE_CLUSTER_FIRST (DPAA2_CORE_CLUSTER_BASE + 0) ++#define DPAA2_CORE_CLUSTER_SECOND (DPAA2_CORE_CLUSTER_BASE + 1) ++#define DPAA2_CORE_CLUSTER_THIRD (DPAA2_CORE_CLUSTER_BASE + 2) ++#define DPAA2_CORE_CLUSTER_FOURTH (DPAA2_CORE_CLUSTER_BASE + 3) ++ ++#define DPAA2_CORE_CLUSTER_GET(sdest, cpu_id) \ ++do { \ ++ if (cpu_id == 0 || cpu_id == 1) \ ++ sdest = DPAA2_CORE_CLUSTER_FIRST; \ ++ else if (cpu_id == 2 || cpu_id == 3) \ ++ sdest = DPAA2_CORE_CLUSTER_SECOND; \ ++ else if (cpu_id == 4 || cpu_id == 5) \ ++ sdest = DPAA2_CORE_CLUSTER_THIRD; \ ++ else \ ++ sdest = DPAA2_CORE_CLUSTER_FOURTH; \ ++} while (0) ++ ++static int ++configure_dpio_qbman_swp(struct dpaa2_dpio_dev *dpio_dev) ++{ ++ struct qbman_swp_desc p_des; ++ struct dpio_attr attr; ++ ++ dpio_dev->dpio = malloc(sizeof(struct fsl_mc_io)); ++ if (!dpio_dev->dpio) { ++ PMD_DRV_LOG(ERR, "Memory allocation failure\n"); ++ return -1; ++ } ++ ++ PMD_DRV_LOG(INFO, "\t Alocated DPIO[%p]", dpio_dev->dpio); ++ dpio_dev->dpio->regs = dpio_dev->mc_portal; ++ if (dpio_open(dpio_dev->dpio, CMD_PRI_LOW, dpio_dev->hw_id, ++ &dpio_dev->token)) { ++ PMD_DRV_LOG(ERR, "Failed to allocate IO space\n"); ++ free(dpio_dev->dpio); ++ return -1; ++ } ++ ++ if (dpio_reset(dpio_dev->dpio, CMD_PRI_LOW, dpio_dev->token)) { ++ PMD_DRV_LOG(ERR, "Failed to reset dpio\n"); ++ dpio_close(dpio_dev->dpio, CMD_PRI_LOW, dpio_dev->token); ++ free(dpio_dev->dpio); ++ return -1; ++ } ++ ++ if (dpio_enable(dpio_dev->dpio, CMD_PRI_LOW, dpio_dev->token)) { ++ PMD_DRV_LOG(ERR, "Failed to Enable dpio\n"); ++ dpio_close(dpio_dev->dpio, CMD_PRI_LOW, dpio_dev->token); ++ free(dpio_dev->dpio); ++ return -1; ++ } ++ ++ if (dpio_get_attributes(dpio_dev->dpio, CMD_PRI_LOW, ++ dpio_dev->token, &attr)) { ++ PMD_DRV_LOG(ERR, "DPIO Get attribute failed\n"); ++ dpio_disable(dpio_dev->dpio, CMD_PRI_LOW, dpio_dev->token); ++ dpio_close(dpio_dev->dpio, CMD_PRI_LOW, dpio_dev->token); ++ free(dpio_dev->dpio); ++ return -1; ++ } ++ ++ PMD_DRV_LOG(INFO, "Qbman Portal ID %d", attr.qbman_portal_id); ++ PMD_DRV_LOG(INFO, "Portal CE addr 0x%lX", attr.qbman_portal_ce_offset); ++ PMD_DRV_LOG(INFO, "Portal CI addr 0x%lX", attr.qbman_portal_ci_offset); ++ ++ /* Configure & setup SW portal */ ++ p_des.block = NULL; ++ p_des.idx = attr.qbman_portal_id; ++ p_des.cena_bar = (void *)(dpio_dev->qbman_portal_ce_paddr); ++ p_des.cinh_bar = (void *)(dpio_dev->qbman_portal_ci_paddr); ++ p_des.irq = -1; ++ p_des.qman_version = attr.qbman_version; ++ ++ PMD_DRV_LOG(INFO, "Portal CE addr 0x%p", p_des.cena_bar); ++ PMD_DRV_LOG(INFO, "Portal CI addr 0x%p", p_des.cinh_bar); ++ ++ dpio_dev->sw_portal = qbman_swp_init(&p_des); ++ if (dpio_dev->sw_portal == NULL) { ++ PMD_DRV_LOG(ERR, " QBMan SW Portal Init failed\n"); ++ dpio_close(dpio_dev->dpio, CMD_PRI_LOW, dpio_dev->token); ++ free(dpio_dev->dpio); ++ return -1; ++ } ++ ++ PMD_DRV_LOG(INFO, "QBMan SW Portal 0x%p\n", dpio_dev->sw_portal); ++ ++ return 0; ++} ++ ++int dpaa2_configure_stashing(struct dpaa2_dpio_dev *dpio_dev) ++{ ++ int sdest; ++ int cpu_id, ret; ++ ++ /* Set the Stashing Destination */ ++ cpu_id = rte_lcore_id(); ++ if (cpu_id < 0) { ++ cpu_id = rte_get_master_lcore(); ++ if (cpu_id < 0) { ++ PMD_DRV_LOG(ERR, "\tGetting CPU Index failed\n"); ++ return -1; ++ } ++ } ++ ++ /* ++ * In case of running DPDK on the Virtual Machine the Stashing ++ * Destination gets set in the H/W w.r.t. the Virtual CPU ID's. ++ * As a W.A. environment variable HOST_START_CPU tells which ++ * the offset of the host start core of the Virtual Machine threads. ++ */ ++ if (getenv("HOST_START_CPU")) { ++ cpu_id += ++ atoi(getenv("HOST_START_CPU")); ++ cpu_id = cpu_id % NUM_HOST_CPUS; ++ } ++ ++ /* Set the STASH Destination depending on Current CPU ID. ++ Valid values of SDEST are 4,5,6,7. Where, ++ CPU 0-1 will have SDEST 4 ++ CPU 2-3 will have SDEST 5.....and so on. ++ */ ++ DPAA2_CORE_CLUSTER_GET(sdest, cpu_id); ++ PMD_DRV_LOG(INFO, "Portal= %d CPU= %u SDEST= %d\n", ++ dpio_dev->index, cpu_id, sdest); ++ ++ ret = dpio_set_stashing_destination(dpio_dev->dpio, CMD_PRI_LOW, ++ dpio_dev->token, sdest); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "%d ERROR in SDEST\n", ret); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static inline struct dpaa2_dpio_dev *dpaa2_get_qbman_swp(void) ++{ ++ struct dpaa2_dpio_dev *dpio_dev = NULL; ++ int ret; ++ ++ /* Get DPIO dev handle from list using index */ ++ TAILQ_FOREACH(dpio_dev, dpio_dev_list, next) { ++ if (dpio_dev && rte_atomic16_test_and_set(&dpio_dev->ref_count)) ++ break; ++ } ++ if (!dpio_dev) ++ return NULL; ++ ++ ret = dpaa2_configure_stashing(dpio_dev); ++ if (ret) { ++ RTE_LOG(ERR, EAL, "dpaa2_configure_stashing failed"); ++ } ++ return dpio_dev; ++} ++int ++dpaa2_affine_qbman_swp(void) ++{ ++ if (thread_io_info.dpio_dev) ++ return 0; ++ ++ /* Populate the thread_io_info structure */ ++ thread_io_info.dpio_dev = dpaa2_get_qbman_swp(); ++ if (thread_io_info.dpio_dev) ++ return 0; ++ else ++ return -1; ++} ++ ++int ++dpaa2_affine_qbman_swp_sec(void) ++{ ++ if (thread_io_info.sec_dpio_dev) ++ return 0; ++ ++ /* Populate the thread_io_info structure */ ++ thread_io_info.sec_dpio_dev = dpaa2_get_qbman_swp(); ++ if (thread_io_info.sec_dpio_dev) ++ return 0; ++ else ++ return -1; ++} ++ ++int ++dpaa2_create_dpio_device(struct fsl_vfio_device *vdev, ++ struct vfio_device_info *obj_info, ++ int object_id) ++{ ++ struct dpaa2_dpio_dev *dpio_dev; ++ struct vfio_region_info reg_info = { .argsz = sizeof(reg_info)}; ++ ++ if (obj_info->num_regions < NUM_DPIO_REGIONS) { ++ PMD_DRV_LOG(ERR, "ERROR, Not sufficient number " ++ "of DPIO regions.\n"); ++ return -1; ++ } ++ ++ if (!dpio_dev_list) { ++ dpio_dev_list = malloc(sizeof(struct dpio_device_list)); ++ if (NULL == dpio_dev_list) { ++ PMD_DRV_LOG(ERR, "Memory allocation failed for DPIO list\n"); ++ return -1; ++ } ++ ++ /* Initialize the DPIO List */ ++ TAILQ_INIT(dpio_dev_list); ++ } ++ ++ dpio_dev = malloc(sizeof(struct dpaa2_dpio_dev)); ++ if (!dpio_dev) { ++ PMD_DRV_LOG(ERR, "Memory allocation failed for DPIO Device\n"); ++ return -1; ++ } ++ ++ PMD_DRV_LOG(INFO, "\t Aloocated DPIO [%p]", dpio_dev); ++ dpio_dev->dpio = NULL; ++ dpio_dev->hw_id = object_id; ++ dpio_dev->vfio_fd = vdev->fd; ++ rte_atomic16_init(&dpio_dev->ref_count); ++ /* Using single portal for all devices */ ++ dpio_dev->mc_portal = mcp_ptr_list[MC_PORTAL_INDEX]; ++ ++ reg_info.index = 0; ++ if (ioctl(dpio_dev->vfio_fd, VFIO_DEVICE_GET_REGION_INFO, ®_info)) { ++ printf("vfio: error getting region info\n"); ++ return -1; ++ } ++ ++ PMD_DRV_LOG(INFO, "\t Region Offset = %llx", reg_info.offset); ++ PMD_DRV_LOG(INFO, "\t Region Size = %llx", reg_info.size); ++ dpio_dev->ce_size = reg_info.size; ++ dpio_dev->qbman_portal_ce_paddr = (uint64_t)mmap(NULL, reg_info.size, ++ PROT_WRITE | PROT_READ, MAP_SHARED, ++ dpio_dev->vfio_fd, reg_info.offset); ++ ++ /* Create Mapping for QBMan Cache Enabled area. This is a fix for ++ SMMU fault for DQRR statshing transaction. */ ++ if (vfio_dmamap_mem_region(dpio_dev->qbman_portal_ce_paddr, ++ reg_info.offset, reg_info.size)) { ++ PMD_DRV_LOG(ERR, "DMAMAP for Portal CE area failed.\n"); ++ return -1; ++ } ++ ++ reg_info.index = 1; ++ if (ioctl(dpio_dev->vfio_fd, VFIO_DEVICE_GET_REGION_INFO, ®_info)) { ++ printf("vfio: error getting region info\n"); ++ return -1; ++ } ++ ++ PMD_DRV_LOG(INFO, "\t Region Offset = %llx", reg_info.offset); ++ PMD_DRV_LOG(INFO, "\t Region Size = %llx", reg_info.size); ++ dpio_dev->ci_size = reg_info.size; ++ dpio_dev->qbman_portal_ci_paddr = (uint64_t)mmap(NULL, reg_info.size, ++ PROT_WRITE | PROT_READ, MAP_SHARED, ++ dpio_dev->vfio_fd, reg_info.offset); ++ ++ if (configure_dpio_qbman_swp(dpio_dev)) { ++ PMD_DRV_LOG(ERR, ++ "Failed in configuring the qbman portal for dpio %d\n", ++ dpio_dev->hw_id); ++ return -1; ++ } ++ ++ io_space_count++; ++ dpio_dev->index = io_space_count; ++ TAILQ_INSERT_HEAD(dpio_dev_list, dpio_dev, next); ++ ++ return 0; ++} +diff --git a/drivers/net/dpaa2/rte_eth_dpni.c b/drivers/net/dpaa2/rte_eth_dpni.c +new file mode 100644 +index 0000000..c1587dc +--- /dev/null ++++ b/drivers/net/dpaa2/rte_eth_dpni.c +@@ -0,0 +1,2269 @@ ++/*- ++ * BSD LICENSE ++ * ++ * Copyright (c) 2014 Freescale Semiconductor, Inc. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * * Neither the name of Freescale Semiconductor, Inc nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++/* MC header files */ ++#include ++#include ++#include "rte_eth_dpaa2_pvt.h" ++#include "rte_eth_dpni_annot.h" ++#include "dpaa2_logs.h" ++ ++#include ++#include ++ ++#define DPAA2_STASHING ++ ++/* tx fd send batching */ ++#define QBMAN_MULTI_TX ++/* #define DPAA2_CGR_SUPPORT */ ++ ++ ++#define DPAA2_MIN_RX_BUF_SIZE 512 ++#define DPAA2_MAX_RX_PKT_LEN 10240 /*WRIOP support*/ ++ ++#define RTE_ETH_DPAA2_SNAPSHOT_LEN 65535 ++#define RTE_ETH_DPAA2_SNAPLEN 4096 ++#define RTE_ETH_DPAA2_PROMISC 1 ++#define RTE_ETH_DPAA2_TIMEOUT -1 ++#define ETH_DPAA2_RX_IFACE_ARG "rx_iface" ++#define ETH_DPAA2_TX_IFACE_ARG "tx_iface" ++#define ETH_DPAA2_IFACE_ARG "iface" ++ ++static const char *drivername = "DPNI PMD"; ++ ++#define MAX_TCS DPNI_MAX_TC ++#define MAX_RX_QUEUES 64 ++#define MAX_TX_QUEUES 64 ++ ++/*Maximum number of slots available in TX ring*/ ++#define MAX_SLOTS 8 ++ ++/*Threshold for a queue to *Enter* Congestion state. ++ It is set to 128 frames of size 64 bytes.*/ ++#define CONG_ENTER_THRESHOLD (128 * 64) ++ ++/*Threshold for a queue to *Exit* Congestion state. ++ It is set to 98 frames of size 64 bytes*/ ++#define CONG_EXIT_THRESHOLD (98 * 64) ++ ++/*! Maximum number of flow distributions per traffic class */ ++#define MAX_DIST_PER_TC 16 ++ ++/* Size of the input SMMU mapped memory required by MC */ ++#define DIST_PARAM_IOVA_SIZE 256 ++ ++struct dpaa2_queue { ++ void *dev; ++ int32_t eventfd; /*!< Event Fd of this queue */ ++ uint32_t fqid; /*!< Unique ID of this queue */ ++ uint8_t tc_index; /*!< traffic class identifier */ ++ uint16_t flow_id; /*!< To be used by DPAA2 frmework */ ++ uint64_t rx_pkts; ++ uint64_t tx_pkts; ++ uint64_t err_pkts; ++ union { ++ struct queue_storage_info_t *q_storage; ++ struct qbman_result *cscn; ++ }; ++}; ++ ++struct dpaa2_dev_priv { ++ void *hw; ++ int32_t hw_id; ++ int32_t qdid; ++ uint16_t token; ++ uint8_t nb_tx_queues; ++ uint8_t nb_rx_queues; ++ void *rx_vq[MAX_RX_QUEUES]; ++ void *tx_vq[MAX_TX_QUEUES]; ++ ++ struct dpaa2_bp_list *bp_list; /**data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ uint64_t value; ++ ++ dpni_get_counter(dpni, CMD_PRI_LOW, priv->token, DPNI_CNT_ING_FRAME, &value); ++ printf("Rx packets: %ld\n", value); ++ dpni_get_counter(dpni, CMD_PRI_LOW, priv->token, DPNI_CNT_ING_BYTE, &value); ++ printf("Rx bytes: %ld\n", value); ++ dpni_get_counter(dpni, CMD_PRI_LOW, priv->token, DPNI_CNT_ING_MCAST_FRAME, &value); ++ printf("Rx Multicast: %ld\n", value); ++ dpni_get_counter(dpni, CMD_PRI_LOW, priv->token, DPNI_CNT_ING_FRAME_DROP, &value); ++ printf("Rx dropped: %ld\n", value); ++ dpni_get_counter(dpni, CMD_PRI_LOW, priv->token, DPNI_CNT_ING_FRAME_DISCARD, &value); ++ printf("Rx discarded: %ld\n", value); ++ dpni_get_counter(dpni, CMD_PRI_LOW, priv->token, DPNI_CNT_EGR_FRAME, &value); ++ printf("Tx packets: %ld\n", value); ++ dpni_get_counter(dpni, CMD_PRI_LOW, priv->token, DPNI_CNT_EGR_BYTE, &value); ++ printf("Tx bytes: %ld\n", value); ++ dpni_get_counter(dpni, CMD_PRI_LOW, priv->token, DPNI_CNT_EGR_FRAME_DISCARD, &value); ++ printf("Tx dropped: %ld\n", value); ++} ++ ++/** ++ * Atomically reads the link status information from global ++ * structure rte_eth_dev. ++ * ++ * @param dev ++ * - Pointer to the structure rte_eth_dev to read from. ++ * - Pointer to the buffer to be saved with the link status. ++ * ++ * @return ++ * - On success, zero. ++ * - On failure, negative value. ++ */ ++static inline int ++rte_dpni_dev_atomic_read_link_status(struct rte_eth_dev *dev, ++ struct rte_eth_link *link) ++{ ++ struct rte_eth_link *dst = link; ++ struct rte_eth_link *src = &dev->data->dev_link; ++ ++ if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst, ++ *(uint64_t *)src) == 0) ++ return -1; ++ ++ return 0; ++} ++ ++/** ++ * Atomically writes the link status information into global ++ * structure rte_eth_dev. ++ * ++ * @param dev ++ * - Pointer to the structure rte_eth_dev to read from. ++ * - Pointer to the buffer to be saved with the link status. ++ * ++ * @return ++ * - On success, zero. ++ * - On failure, negative value. ++ */ ++static inline int ++rte_dpni_dev_atomic_write_link_status(struct rte_eth_dev *dev, ++ struct rte_eth_link *link) ++{ ++ struct rte_eth_link *dst = &dev->data->dev_link; ++ struct rte_eth_link *src = link; ++ ++ if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst, ++ *(uint64_t *)src) == 0) ++ return -1; ++ ++ return 0; ++} ++ ++static inline void ++dpaa2_eth_parse_packet(struct rte_mbuf *mbuf, uint64_t hw_annot_addr) ++{ ++ uint32_t pkt_type = 0; ++ struct pkt_annotation *annotation = ++ (struct pkt_annotation *)hw_annot_addr; ++ ++ PMD_DRV_LOG(DEBUG, "\n 1 annotation = 0x%lx ", annotation->word4); ++ ++ if (BIT_ISSET_AT_POS(annotation->word3, L2_ETH_MAC_PRESENT)) ++ pkt_type/* mbuf->packet_type */ |= RTE_PTYPE_L2_ETHER; ++ ++ if (BIT_ISSET_AT_POS(annotation->word4, L3_IPV4_1_PRESENT)) ++ pkt_type/* mbuf->packet_type */ |= RTE_PTYPE_L3_IPV4; ++ ++ if (BIT_ISSET_AT_POS(annotation->word4, L3_IPV6_1_PRESENT)) ++ pkt_type /* mbuf->packet_type */ |= RTE_PTYPE_L3_IPV6; ++ ++ if (BIT_ISSET_AT_POS(annotation->word4, L3_IP_1_OPT_PRESENT)) ++ pkt_type/* mbuf->packet_type */ |= RTE_PTYPE_L3_IPV4_EXT; ++ ++ if (BIT_ISSET_AT_POS(annotation->word4, L3_PROTO_UDP_PRESENT)) ++ pkt_type/* mbuf->packet_type */ |= RTE_PTYPE_L4_UDP; ++ ++ if (BIT_ISSET_AT_POS(annotation->word4, L3_PROTO_TCP_PRESENT)) ++ pkt_type/* mbuf->packet_type */ |= RTE_PTYPE_L4_TCP; ++ ++ if (BIT_ISSET_AT_POS(annotation->word4, L3_PROTO_SCTP_PRESENT)) ++ pkt_type/* mbuf->packet_type */ |= RTE_PTYPE_L4_SCTP; ++ ++ if (BIT_ISSET_AT_POS(annotation->word4, L3_PROTO_ICMP_PRESENT)) ++ pkt_type/* mbuf->packet_type */ |= RTE_PTYPE_L4_ICMP; ++ ++ if (BIT_ISSET_AT_POS(annotation->word4, L3_IP_UNKNOWN_PROTOCOL)) ++ pkt_type/* mbuf->packet_type */ |= RTE_PTYPE_UNKNOWN; ++ ++ mbuf->packet_type = pkt_type; ++} ++ ++static inline ++struct rte_mbuf *eth_fd_to_mbuf(const struct qbman_fd *fd) ++{ ++ struct rte_mbuf *mbuf = DPAA2_INLINE_MBUF_FROM_BUF( ++ DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)), ++ bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size); ++ /* need to repopulated some of the fields, ++ as they may have changed in last transmission*/ ++ ++ ++ mbuf->data_off = DPAA2_GET_FD_OFFSET(fd); ++ mbuf->data_len = DPAA2_GET_FD_LEN(fd); ++ mbuf->pkt_len = mbuf->data_len; ++ mbuf->next = NULL; ++ rte_mbuf_refcnt_set(mbuf, 1); ++ ++ PMD_DRV_LOG(DEBUG, "to mbuf - mbuf =%p, mbuf->buf_addr =%p, off = %d," ++ "fd_off=%d fd =%lx, meta = %d bpid =%d, len=%d\n", ++ mbuf, mbuf->buf_addr, mbuf->data_off, ++ DPAA2_GET_FD_OFFSET(fd), DPAA2_GET_FD_ADDR(fd), ++ bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size, ++ DPAA2_GET_FD_BPID(fd), DPAA2_GET_FD_LEN(fd)); ++ ++ /* Parse the packet */ ++ /* parse results are after the private - sw annotation area */ ++ dpaa2_eth_parse_packet(mbuf, ++ (uint64_t)DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd)) ++ + DPAA2_FD_PTA_SIZE); ++ ++ mbuf->nb_segs = 1; ++ mbuf->ol_flags = 0; ++ ++ return mbuf; ++} ++ ++static void __attribute__ ((noinline)) eth_mbuf_to_fd(struct rte_mbuf *mbuf, ++ struct qbman_fd *fd, uint16_t bpid) ++{ ++ /*Resetting the buffer pool id and offset field*/ ++ fd->simple.bpid_offset = 0; ++ ++ DPAA2_SET_FD_ADDR(fd, DPAA2_MBUF_VADDR_TO_IOVA(mbuf)); ++ DPAA2_SET_FD_LEN(fd, mbuf->data_len); ++ DPAA2_SET_FD_BPID(fd, bpid); ++ DPAA2_SET_FD_OFFSET(fd, mbuf->data_off); ++ DPAA2_SET_FD_ASAL(fd, DPAA2_ASAL_VAL); ++ ++ PMD_DRV_LOG(DEBUG, "mbuf =%p, mbuf->buf_addr =%p, off = %d," ++ "fd_off=%d fd =%lx, meta = %d bpid =%d, len=%d\n", ++ mbuf, mbuf->buf_addr, mbuf->data_off, ++ DPAA2_GET_FD_OFFSET(fd), DPAA2_GET_FD_ADDR(fd), ++ bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size, ++ DPAA2_GET_FD_BPID(fd), DPAA2_GET_FD_LEN(fd)); ++ ++ return; ++} ++ ++static int eth_copy_mbuf_to_fd(struct rte_mbuf *mbuf, ++ struct qbman_fd *fd, uint16_t bpid) ++{ ++ struct rte_mbuf *m; ++ void *mb = NULL; ++ ++ if (hw_mbuf_alloc_bulk(bpid_info[bpid].bp_list->buf_pool.mp, &mb, 1)) { ++ PMD_DRV_LOG(WARNING, "Unable to allocated DPAA2 buffer"); ++ rte_pktmbuf_free(mbuf); ++ return -1; ++ } ++ m = (struct rte_mbuf *)mb; ++ memcpy((char *)m->buf_addr + mbuf->data_off, ++ (void *)((char *)mbuf->buf_addr + mbuf->data_off), ++ mbuf->pkt_len); ++ ++ /*Resetting the buffer pool id and offset field*/ ++ fd->simple.bpid_offset = 0; ++ ++ DPAA2_SET_FD_ADDR(fd, DPAA2_MBUF_VADDR_TO_IOVA(m)); ++ DPAA2_SET_FD_LEN(fd, mbuf->data_len); ++ DPAA2_SET_FD_BPID(fd, bpid); ++ DPAA2_SET_FD_OFFSET(fd, mbuf->data_off); ++ DPAA2_SET_FD_ASAL(fd, DPAA2_ASAL_VAL); ++ ++ PMD_DRV_LOG(DEBUG, "\nmbuf %p BMAN buf addr %p", ++ (void *)mbuf, mbuf->buf_addr); ++ ++ PMD_DRV_LOG(DEBUG, "\nfdaddr =%lx bpid =%d meta =%d off =%d, len =%d\n", ++ DPAA2_GET_FD_ADDR(fd), ++ DPAA2_GET_FD_BPID(fd), ++ bpid_info[DPAA2_GET_FD_BPID(fd)].meta_data_size, ++ DPAA2_GET_FD_OFFSET(fd), ++ DPAA2_GET_FD_LEN(fd)); ++ /*free the original packet */ ++ rte_pktmbuf_free(mbuf); ++ ++ return 0; ++} ++ ++static uint16_t ++eth_dpaa2_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) ++{ ++ /* Function is responsible to receive frames for a given device and VQ*/ ++ struct dpaa2_queue *dpaa2_q = (struct dpaa2_queue *)queue; ++ struct qbman_result *dq_storage; ++ uint32_t fqid = dpaa2_q->fqid; ++ int ret, num_rx = 0; ++ uint8_t is_last = 0, status; ++ struct qbman_swp *swp; ++ const struct qbman_fd *fd; ++ struct qbman_pull_desc pulldesc; ++ struct rte_eth_dev *dev = dpaa2_q->dev; ++ ++ if (!thread_io_info.dpio_dev) { ++ ret = dpaa2_affine_qbman_swp(); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Failure in affining portal\n"); ++ return 0; ++ } ++ } ++ swp = thread_io_info.dpio_dev->sw_portal; ++ dq_storage = dpaa2_q->q_storage->dq_storage[0]; ++ ++ qbman_pull_desc_clear(&pulldesc); ++ qbman_pull_desc_set_numframes(&pulldesc, nb_pkts); ++ qbman_pull_desc_set_fq(&pulldesc, fqid); ++ /* todo optimization - we can have dq_storage_phys available*/ ++ qbman_pull_desc_set_storage(&pulldesc, dq_storage, ++ (dma_addr_t)(DPAA2_VADDR_TO_IOVA(dq_storage)), 1); ++ ++ /*Issue a volatile dequeue command. */ ++ while (1) { ++ if (qbman_swp_pull(swp, &pulldesc)) { ++ PMD_DRV_LOG(ERR, "VDQ command is not issued." ++ "QBMAN is busy\n"); ++ /* Portal was busy, try again */ ++ continue; ++ } ++ break; ++ }; ++ ++ /* Receive the packets till Last Dequeue entry is found with ++ respect to the above issues PULL command. ++ */ ++ while (!is_last) { ++ /*Check if the previous issued command is completed. ++ *Also seems like the SWP is shared between the Ethernet Driver ++ *and the SEC driver.*/ ++ while (!qbman_check_command_complete(swp, dq_storage)) ++ ; ++ /* Loop until the dq_storage is updated with ++ * new token by QBMAN */ ++ while (!qbman_result_has_new_result(swp, dq_storage)) ++ ; ++ /* Check whether Last Pull command is Expired and ++ setting Condition for Loop termination */ ++ if (qbman_result_DQ_is_pull_complete(dq_storage)) { ++ is_last = 1; ++ /* Check for valid frame. */ ++ status = (uint8_t)qbman_result_DQ_flags(dq_storage); ++ if (unlikely((status & QBMAN_DQ_STAT_VALIDFRAME) == 0)) { ++ PMD_DRV_LOG(DEBUG, "No frame is delivered\n"); ++ continue; ++ } ++ } ++ ++ fd = qbman_result_DQ_fd(dq_storage); ++ bufs[num_rx] = eth_fd_to_mbuf(fd); ++ bufs[num_rx]->port = dev->data->port_id; ++ ++ num_rx++; ++ dq_storage++; ++ } /* End of Packet Rx loop */ ++ ++ dpaa2_q->rx_pkts += num_rx; ++ ++ PMD_DRV_LOG(INFO, "Ethernet Received %d Packets\n", num_rx); ++ /*Return the total number of packets received to DPAA2 app*/ ++ return num_rx; ++} ++ ++static uint16_t ++eth_dpaa2_prefetch_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) ++{ ++ /* Function is responsible to receive frames for a given device and VQ*/ ++ struct dpaa2_queue *dpaa2_q = (struct dpaa2_queue *)queue; ++ struct qbman_result *dq_storage; ++ uint32_t fqid = dpaa2_q->fqid; ++ int ret, i, num_rx = 0; ++ uint8_t is_last = 0, status; ++ struct qbman_swp *swp; ++ const struct qbman_fd *fd[16]; ++ struct qbman_pull_desc pulldesc; ++ struct queue_storage_info_t *q_storage = dpaa2_q->q_storage; ++ struct rte_eth_dev *dev = dpaa2_q->dev; ++ ++ if (!thread_io_info.dpio_dev) { ++ ret = dpaa2_affine_qbman_swp(); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Failure in affining portal\n"); ++ return 0; ++ } ++ } ++ swp = thread_io_info.dpio_dev->sw_portal; ++ ++ if (!q_storage->active_dqs) { ++ q_storage->toggle = 0; ++ dq_storage = q_storage->dq_storage[q_storage->toggle]; ++ qbman_pull_desc_clear(&pulldesc); ++ qbman_pull_desc_set_numframes(&pulldesc, nb_pkts); ++ qbman_pull_desc_set_fq(&pulldesc, fqid); ++ qbman_pull_desc_set_storage(&pulldesc, dq_storage, ++ (dma_addr_t)(DPAA2_VADDR_TO_IOVA(dq_storage)), 1); ++ if (thread_io_info.global_active_dqs) { ++ while (!qbman_check_command_complete(swp, thread_io_info.global_active_dqs)) ++ ; ++ } ++ while (1) { ++ if (qbman_swp_pull(swp, &pulldesc)) { ++ PMD_DRV_LOG(WARNING, "VDQ command is not issued." ++ "QBMAN is busy\n"); ++ /* Portal was busy, try again */ ++ continue; ++ } ++ break; ++ } ++ q_storage->active_dqs = dq_storage; ++ thread_io_info.global_active_dqs = dq_storage; ++ } ++ if (thread_io_info.global_active_dqs) ++ while (!qbman_check_command_complete(swp, thread_io_info.global_active_dqs)) ++ ; ++ dq_storage = q_storage->active_dqs; ++ while (!is_last) { ++ /* Loop until the dq_storage is updated with ++ * new token by QBMAN */ ++ struct rte_mbuf *mbuf; ++ ++ while (!qbman_result_has_new_result(swp, dq_storage)) ++ ; ++ rte_prefetch0((void *)((uint64_t)(dq_storage + 1))); ++ /* Check whether Last Pull command is Expired and ++ setting Condition for Loop termination */ ++ if (qbman_result_DQ_is_pull_complete(dq_storage)) { ++ is_last = 1; ++ /* Check for valid frame. */ ++ status = (uint8_t)qbman_result_DQ_flags(dq_storage); ++ if (unlikely((status & QBMAN_DQ_STAT_VALIDFRAME) == 0)) { ++ PMD_DRV_LOG2(DEBUG, "No frame is delivered\n"); ++ continue; ++ } ++ } ++ fd[num_rx] = qbman_result_DQ_fd(dq_storage); ++ mbuf = (struct rte_mbuf *)DPAA2_IOVA_TO_VADDR( ++ DPAA2_GET_FD_ADDR(fd[num_rx]) ++ - bpid_info[DPAA2_GET_FD_BPID(fd[num_rx])].meta_data_size); ++ /* Prefeth mbuf */ ++ rte_prefetch0(mbuf); ++ /* Prefetch Annotation address from where we get parse results */ ++ rte_prefetch0((void *)((uint64_t)DPAA2_GET_FD_ADDR(fd[num_rx]) + DPAA2_FD_PTA_SIZE + 16)); ++ /*Prefetch Data buffer*/ ++ /* rte_prefetch0((void *)((uint64_t)DPAA2_GET_FD_ADDR(fd[num_rx]) + DPAA2_GET_FD_OFFSET(fd[num_rx]))); */ ++ dq_storage++; ++ num_rx++; ++ ++ } /* End of Packet Rx loop */ ++ ++ for (i = 0; i < num_rx; i++) { ++ bufs[i] = eth_fd_to_mbuf(fd[i]); ++ bufs[i]->port = dev->data->port_id; ++ } ++ ++ q_storage->toggle ^= 1; ++ dq_storage = q_storage->dq_storage[q_storage->toggle]; ++ qbman_pull_desc_clear(&pulldesc); ++ qbman_pull_desc_set_numframes(&pulldesc, nb_pkts); ++ qbman_pull_desc_set_fq(&pulldesc, fqid); ++ qbman_pull_desc_set_storage(&pulldesc, dq_storage, ++ (dma_addr_t)(DPAA2_VADDR_TO_IOVA(dq_storage)), 1); ++ /*Issue a volatile dequeue command. */ ++ ++ while (1) { ++ if (qbman_swp_pull(swp, &pulldesc)) { ++ PMD_DRV_LOG(WARNING, "VDQ command is not issued." ++ "QBMAN is busy\n"); ++ continue; ++ } ++ break; ++ } ++ q_storage->active_dqs = dq_storage; ++ thread_io_info.global_active_dqs = dq_storage; ++ ++ dpaa2_q->rx_pkts += num_rx; ++ ++ PMD_DRV_LOG2(INFO, "Ethernet Received %d Packets\n", num_rx); ++ /*Return the total number of packets received to DPAA2 app*/ ++ return num_rx; ++} ++ ++/* ++ * Callback to handle sending packets through a real NIC. ++ */ ++static uint16_t ++eth_dpaa2_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) ++{ ++ /* Function to transmit the frames to given device and VQ*/ ++ uint32_t loop; ++ int32_t ret; ++#ifdef QBMAN_MULTI_TX ++ struct qbman_fd fd_arr[8]; ++ uint32_t frames_to_send; ++#else ++ struct qbman_fd fd; ++#endif ++ struct rte_mempool *mp; ++ struct qbman_eq_desc eqdesc; ++ struct dpaa2_queue *dpaa2_q = (struct dpaa2_queue *)queue; ++ struct qbman_swp *swp; ++ uint16_t num_tx = 0; ++ uint16_t bpid; ++ struct rte_eth_dev *dev = dpaa2_q->dev; ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ ++ if (!thread_io_info.dpio_dev) { ++ ret = dpaa2_affine_qbman_swp(); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Failure in affining portal\n"); ++ return 0; ++ } ++ } ++ swp = thread_io_info.dpio_dev->sw_portal; ++ ++ PMD_DRV_LOG(DEBUG, "===> dev =%p, fqid =%d", dev, dpaa2_q->fqid); ++ ++ /*Prepare enqueue descriptor*/ ++ qbman_eq_desc_clear(&eqdesc); ++ qbman_eq_desc_set_no_orp(&eqdesc, DPAA2_EQ_RESP_ERR_FQ); ++ qbman_eq_desc_set_response(&eqdesc, 0, 0); ++ qbman_eq_desc_set_qd(&eqdesc, priv->qdid, ++ dpaa2_q->flow_id, dpaa2_q->tc_index); ++ ++ /*Clear the unused FD fields before sending*/ ++#ifdef QBMAN_MULTI_TX ++ while (nb_pkts) { ++#ifdef DPAA2_CGR_SUPPORT ++ /*Check if the queue is congested*/ ++ if (qbman_result_is_CSCN(dpaa2_q->cscn)) ++ goto skip_tx; ++#endif ++ frames_to_send = (nb_pkts >> 3) ? MAX_SLOTS : nb_pkts; ++ ++ for (loop = 0; loop < frames_to_send; loop++) { ++ fd_arr[loop].simple.frc = 0; ++ DPAA2_RESET_FD_CTRL((&fd_arr[loop])); ++ DPAA2_SET_FD_FLC((&fd_arr[loop]), NULL); ++ mp = (*bufs)->pool; ++ /* Not a hw_pkt pool allocated frame */ ++ if (mp && !(mp->flags & MEMPOOL_F_HW_PKT_POOL)) { ++ printf("\n non hw offload bufffer "); ++ /* alloc should be from the default buffer pool ++ attached to this interface */ ++ if (priv->bp_list) { ++ bpid = priv->bp_list->buf_pool.bpid; ++ } else { ++ printf("\n ??? why no bpool attached"); ++ num_tx = 0; ++ goto skip_tx; ++ } ++ if (eth_copy_mbuf_to_fd(*bufs, &fd_arr[loop], bpid)) { ++ bufs++; ++ continue; ++ } ++ } else { ++ RTE_ASSERT(mp); ++ bpid = mempool_to_bpid(mp); ++ eth_mbuf_to_fd(*bufs, &fd_arr[loop], bpid); ++ } ++ bufs++; ++ } ++ loop = 0; ++ while (loop < frames_to_send) { ++ loop += qbman_swp_send_multiple(swp, &eqdesc, ++ &fd_arr[loop], frames_to_send - loop); ++ } ++ ++ num_tx += frames_to_send; ++ dpaa2_q->tx_pkts += frames_to_send; ++ nb_pkts -= frames_to_send; ++ } ++#else ++#ifdef DPAA2_CGR_SUPPORT ++ /*Check if the queue is congested*/ ++ if(qbman_result_is_CSCN(dpaa2_q->cscn)) ++ goto skip_tx; ++#endif ++ ++ fd.simple.frc = 0; ++ DPAA2_RESET_FD_CTRL((&fd)); ++ DPAA2_SET_FD_FLC((&fd), NULL); ++ loop = 0; ++ ++ while (loop < nb_pkts) { ++ /*Prepare each packet which is to be sent*/ ++ mp = bufs[loop]->pool; ++ /* Not a hw_pkt pool allocated frame */ ++ if (mp && !(mp->flags & MEMPOOL_F_HW_PKT_POOL)) { ++ /* alloc should be from the default buffer pool ++ attached to this interface */ ++ if (priv->bp_list) { ++ bpid = priv->bp_list->buf_pool.bpid; ++ } else { ++ /* Buffer not from offloaded area as well as ++ * lacks buffer pool identifier. Cannot ++ * continue. ++ */ ++ PMD_DRV_LOG(ERR, "No Buffer pool " ++ "attached.\n"); ++ num_tx = 0; ++ goto skip_tx; ++ } ++ ++ if (eth_copy_mbuf_to_fd(bufs[loop], &fd, bpid)) { ++ loop++; ++ continue; ++ } ++ } else { ++ RTE_ASSERT(mp); ++ bpid = mempool_to_bpid(mp); ++ eth_mbuf_to_fd(bufs[loop], &fd, bpid); ++ } ++ /*Enqueue a single packet to the QBMAN*/ ++ do { ++ ret = qbman_swp_enqueue(swp, &eqdesc, &fd); ++ if (ret != 0) { ++ PMD_DRV_LOG(DEBUG, "Error in transmiting the frame\n"); ++ } ++ } while (ret != 0); ++ ++ /* Free the buffer shell */ ++ /* rte_pktmbuf_free(bufs[loop]); */ ++ num_tx++; loop++; ++ } ++ dpaa2_q->tx_pkts += num_tx; ++ dpaa2_q->err_pkts += nb_pkts - num_tx; ++#endif ++skip_tx: ++ return num_tx; ++} ++ ++static int ++dpaa2_vlan_stripping_set(struct rte_eth_dev *dev, int on) ++{ ++ int ret; ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ ++ PMD_INIT_FUNC_TRACE(); ++ ++ if (dpni == NULL) { ++ PMD_DRV_LOG(ERR, "dpni is NULL"); ++ return -1; ++ } ++ ++ ret = dpni_set_vlan_removal(dpni, CMD_PRI_LOW, priv->token, on); ++ if (ret < 0) ++ PMD_DRV_LOG(ERR, "Unable to dpni_set_vlan_removal hwid =%d", ++ priv->hw_id); ++ return ret; ++} ++ ++static int ++dpaa2_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) ++{ ++ int ret; ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ ++ if (dpni == NULL) { ++ PMD_DRV_LOG(ERR, "dpni is NULL"); ++ return -1; ++ } ++ ++ if (on) ++ ret = dpni_add_vlan_id(dpni, CMD_PRI_LOW, priv->token, vlan_id); ++ else ++ ret = dpni_remove_vlan_id(dpni, CMD_PRI_LOW, priv->token, vlan_id); ++ ++ if (ret < 0) ++ PMD_DRV_LOG(ERR, "ret = %d Unable to add/rem vlan %d hwid =%d", ++ ret, vlan_id, priv->hw_id); ++ ++ /*todo this should on global basis */ ++/* ret = dpni_set_vlan_filters(dpni, CMD_PRI_LOW, priv->token, on); ++ if (ret < 0) ++ PMD_DRV_LOG(ERR, "Unable to set vlan filter"); ++*/ return ret; ++} ++ ++static void ++dpaa2_vlan_offload_set(struct rte_eth_dev *dev, int mask) ++{ ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ int ret; ++ ++ if (mask & ETH_VLAN_FILTER_MASK) { ++ if (dev->data->dev_conf.rxmode.hw_vlan_filter) ++ ret = dpni_set_vlan_filters(dpni, CMD_PRI_LOW, priv->token, TRUE); ++ else ++ ret = dpni_set_vlan_filters(dpni, CMD_PRI_LOW, priv->token, FALSE); ++ if (ret < 0) ++ PMD_DRV_LOG(ERR, "ret = %d Unable to set vlan filter", ret); ++ } ++ ++ if (mask & ETH_VLAN_STRIP_MASK) { ++ /* Enable or disable VLAN stripping */ ++ if (dev->data->dev_conf.rxmode.hw_vlan_strip) ++ dpaa2_vlan_stripping_set(dev, TRUE); ++ else ++ dpaa2_vlan_stripping_set(dev, FALSE); ++ } ++ ++ if (mask & ETH_VLAN_EXTEND_MASK) { ++ PMD_INIT_FUNC_TRACE(); ++/* if (dev->data->dev_conf.rxmode.hw_vlan_extend) ++ i40e_vsi_config_double_vlan(vsi, TRUE); ++ else ++ i40e_vsi_config_double_vlan(vsi, FALSE); ++*/ } ++} ++ ++static void ++dpaa2_eth_dev_info(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) ++{ ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ ++ dev_info->driver_name = drivername; ++ dev_info->if_index = priv->hw_id; ++ dev_info->max_mac_addrs = priv->max_unicast_filters; ++ dev_info->max_rx_pktlen = DPAA2_MAX_RX_PKT_LEN; ++ dev_info->max_rx_queues = (uint16_t)priv->nb_rx_queues; ++ dev_info->max_tx_queues = (uint16_t)priv->nb_tx_queues; ++ dev_info->min_rx_bufsize = DPAA2_MIN_RX_BUF_SIZE; ++ dev_info->pci_dev = dev->pci_dev; ++/* dev_info->rx_offload_capa = ++ DEV_RX_OFFLOAD_IPV4_CKSUM | ++ DEV_RX_OFFLOAD_UDP_CKSUM | ++ DEV_RX_OFFLOAD_TCP_CKSUM; ++ dev_info->tx_offload_capa = ++ DEV_TX_OFFLOAD_IPV4_CKSUM | ++ DEV_TX_OFFLOAD_UDP_CKSUM | ++ DEV_TX_OFFLOAD_TCP_CKSUM | ++ DEV_TX_OFFLOAD_SCTP_CKSUM; ++*/ ++} ++ ++static int ++dpaa2_alloc_rx_tx_queues(struct rte_eth_dev *dev) ++{ ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ uint8_t tc_idx; ++ uint16_t dist_idx; ++ uint32_t vq_id; ++ struct dpaa2_queue *mc_q, *mcq; ++ uint32_t tot_queues; ++ int i; ++ struct dpaa2_queue *dpaa2_q; ++ ++ tot_queues = priv->nb_rx_queues + priv->nb_tx_queues; ++ mc_q = rte_malloc(NULL, sizeof(struct dpaa2_queue) * tot_queues, ++ RTE_CACHE_LINE_SIZE); ++ if (!mc_q) { ++ PMD_DRV_LOG(ERR, "malloc failed for rx/tx queues\n"); ++ return -1; ++ } ++ ++ for (i = 0; i < priv->nb_rx_queues; i++) { ++ mc_q->dev = dev; ++ priv->rx_vq[i] = mc_q++; ++ dpaa2_q = (struct dpaa2_queue *)priv->rx_vq[i]; ++ dpaa2_q->q_storage = rte_malloc("dq_storage", ++ sizeof(struct queue_storage_info_t), ++ RTE_CACHE_LINE_SIZE); ++ if (!dpaa2_q->q_storage) ++ goto fail; ++ ++ memset(dpaa2_q->q_storage, 0, sizeof(struct queue_storage_info_t)); ++ } ++ ++ for (i = 0; i < priv->nb_tx_queues; i++) { ++ mc_q->dev = dev; ++ mc_q->flow_id = DPNI_NEW_FLOW_ID; ++ priv->tx_vq[i] = mc_q++; ++ } ++ ++ vq_id = 0; ++ for (tc_idx = 0; tc_idx < priv->num_tc; tc_idx++) { ++ for (dist_idx = 0; dist_idx < priv->num_dist_per_tc[tc_idx]; dist_idx++) { ++ mcq = (struct dpaa2_queue *)priv->rx_vq[vq_id]; ++ mcq->tc_index = tc_idx; ++ mcq->flow_id = dist_idx; ++ vq_id++; ++ } ++ } ++ ++ return 0; ++fail: ++ i -= 1; ++ while (i >= 0) { ++ dpaa2_q = (struct dpaa2_queue *)priv->rx_vq[i]; ++ rte_free(dpaa2_q->q_storage); ++ } ++ return -1; ++} ++ ++static void dpaa2_distset_to_dpkg_profile_cfg( ++ uint32_t req_dist_set, ++ struct dpkg_profile_cfg *kg_cfg) ++{ ++ uint32_t loop = 0, i = 0, dist_field = 0; ++ int l2_configured = 0, l3_configured = 0; ++ int l4_configured = 0, sctp_configured = 0; ++ ++ memset(kg_cfg, 0, sizeof(struct dpkg_profile_cfg)); ++ while (req_dist_set) { ++ if (req_dist_set % 2 != 0) { ++ dist_field = 1U << loop; ++ switch (dist_field) { ++ case ETH_RSS_L2_PAYLOAD: ++ ++ if (l2_configured) ++ break; ++ l2_configured = 1; ++ ++ kg_cfg->extracts[i].extract.from_hdr.prot = ++ NET_PROT_ETH; ++ kg_cfg->extracts[i].extract.from_hdr.field = ++ NH_FLD_ETH_TYPE; ++ kg_cfg->extracts[i].type = DPKG_EXTRACT_FROM_HDR; ++ kg_cfg->extracts[i].extract.from_hdr.type = ++ DPKG_FULL_FIELD; ++ i++; ++ break; ++ ++ case ETH_RSS_IPV4: ++ case ETH_RSS_FRAG_IPV4: ++ case ETH_RSS_NONFRAG_IPV4_OTHER: ++ case ETH_RSS_IPV6: ++ case ETH_RSS_FRAG_IPV6: ++ case ETH_RSS_NONFRAG_IPV6_OTHER: ++ case ETH_RSS_IPV6_EX: ++ ++ if (l3_configured) ++ break; ++ l3_configured = 1; ++ ++ kg_cfg->extracts[i].extract.from_hdr.prot = ++ NET_PROT_IP; ++ kg_cfg->extracts[i].extract.from_hdr.field = ++ NH_FLD_IP_SRC; ++ kg_cfg->extracts[i].type = DPKG_EXTRACT_FROM_HDR; ++ kg_cfg->extracts[i].extract.from_hdr.type = ++ DPKG_FULL_FIELD; ++ i++; ++ ++ kg_cfg->extracts[i].extract.from_hdr.prot = ++ NET_PROT_IP; ++ kg_cfg->extracts[i].extract.from_hdr.field = ++ NH_FLD_IP_DST; ++ kg_cfg->extracts[i].type = DPKG_EXTRACT_FROM_HDR; ++ kg_cfg->extracts[i].extract.from_hdr.type = ++ DPKG_FULL_FIELD; ++ i++; ++ ++ kg_cfg->extracts[i].extract.from_hdr.prot = ++ NET_PROT_IP; ++ kg_cfg->extracts[i].extract.from_hdr.field = ++ NH_FLD_IP_PROTO; ++ kg_cfg->extracts[i].type = DPKG_EXTRACT_FROM_HDR; ++ kg_cfg->extracts[i].extract.from_hdr.type = ++ DPKG_FULL_FIELD; ++ kg_cfg->num_extracts++; ++ i++; ++ break; ++ ++ case ETH_RSS_NONFRAG_IPV4_TCP: ++ case ETH_RSS_NONFRAG_IPV6_TCP: ++ case ETH_RSS_NONFRAG_IPV4_UDP: ++ case ETH_RSS_NONFRAG_IPV6_UDP: ++ ++ if (l4_configured) ++ break; ++ l4_configured = 1; ++ ++ kg_cfg->extracts[i].extract.from_hdr.prot = ++ NET_PROT_TCP; ++ kg_cfg->extracts[i].extract.from_hdr.field = ++ NH_FLD_TCP_PORT_SRC; ++ kg_cfg->extracts[i].type = DPKG_EXTRACT_FROM_HDR; ++ kg_cfg->extracts[i].extract.from_hdr.type = ++ DPKG_FULL_FIELD; ++ i++; ++ ++ kg_cfg->extracts[i].extract.from_hdr.prot = ++ NET_PROT_TCP; ++ kg_cfg->extracts[i].extract.from_hdr.field = ++ NH_FLD_TCP_PORT_SRC; ++ kg_cfg->extracts[i].type = DPKG_EXTRACT_FROM_HDR; ++ kg_cfg->extracts[i].extract.from_hdr.type = ++ DPKG_FULL_FIELD; ++ i++; ++ break; ++ ++ case ETH_RSS_NONFRAG_IPV4_SCTP: ++ case ETH_RSS_NONFRAG_IPV6_SCTP: ++ ++ if (sctp_configured) ++ break; ++ sctp_configured = 1; ++ ++ kg_cfg->extracts[i].extract.from_hdr.prot = ++ NET_PROT_SCTP; ++ kg_cfg->extracts[i].extract.from_hdr.field = ++ NH_FLD_SCTP_PORT_SRC; ++ kg_cfg->extracts[i].type = DPKG_EXTRACT_FROM_HDR; ++ kg_cfg->extracts[i].extract.from_hdr.type = ++ DPKG_FULL_FIELD; ++ i++; ++ ++ kg_cfg->extracts[i].extract.from_hdr.prot = ++ NET_PROT_SCTP; ++ kg_cfg->extracts[i].extract.from_hdr.field = ++ NH_FLD_SCTP_PORT_DST; ++ kg_cfg->extracts[i].type = DPKG_EXTRACT_FROM_HDR; ++ kg_cfg->extracts[i].extract.from_hdr.type = ++ DPKG_FULL_FIELD; ++ i++; ++ break; ++ ++ default: ++ PMD_DRV_LOG(WARNING, "Bad flow distribution option %x\n", dist_field); ++ } ++ } ++ req_dist_set = req_dist_set >> 1; ++ loop++; ++ } ++ kg_cfg->num_extracts = i; ++} ++ ++static int dpaa2_setup_flow_distribution(struct rte_eth_dev *eth_dev, ++ uint32_t req_dist_set) ++{ ++ struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; ++ struct fsl_mc_io *dpni = priv->hw; ++ struct dpni_rx_tc_dist_cfg tc_cfg; ++ struct dpkg_profile_cfg kg_cfg; ++ void *p_params; ++ int ret, tc_index = 0; ++ ++ p_params = rte_malloc( ++ NULL, DIST_PARAM_IOVA_SIZE, RTE_CACHE_LINE_SIZE); ++ if (!p_params) { ++ PMD_DRV_LOG(ERR, "Memory unavaialble\n"); ++ return -ENOMEM; ++ } ++ memset(p_params, 0, DIST_PARAM_IOVA_SIZE); ++ memset(&tc_cfg, 0, sizeof(struct dpni_rx_tc_dist_cfg)); ++ ++ dpaa2_distset_to_dpkg_profile_cfg(req_dist_set, &kg_cfg); ++ tc_cfg.key_cfg_iova = (uint64_t)(DPAA2_VADDR_TO_IOVA(p_params)); ++ tc_cfg.dist_size = eth_dev->data->nb_rx_queues; ++ tc_cfg.dist_mode = DPNI_DIST_MODE_HASH; ++ ++ ret = dpni_prepare_key_cfg(&kg_cfg, p_params); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Unable to prepare extract parameters\n"); ++ rte_free(p_params); ++ return ret; ++ } ++ ++ ret = dpni_set_rx_tc_dist(dpni, CMD_PRI_LOW, priv->token, tc_index, ++ &tc_cfg); ++ rte_free(p_params); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Setting distribution for Rx failed with" ++ "err code: %d\n", ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int ++dpaa2_remove_flow_distribution(struct rte_eth_dev *eth_dev, uint8_t tc_index) ++{ ++ struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; ++ struct fsl_mc_io *dpni = priv->hw; ++ struct dpni_rx_tc_dist_cfg tc_cfg; ++ struct dpkg_profile_cfg kg_cfg; ++ void *p_params; ++ int ret; ++ ++ p_params = rte_malloc( ++ NULL, DIST_PARAM_IOVA_SIZE, RTE_CACHE_LINE_SIZE); ++ if (!p_params) { ++ PMD_DRV_LOG(ERR, "Memory unavaialble\n"); ++ return -ENOMEM; ++ } ++ memset(p_params, 0, DIST_PARAM_IOVA_SIZE); ++ memset(&tc_cfg, 0, sizeof(struct dpni_rx_tc_dist_cfg)); ++ ++ tc_cfg.key_cfg_iova = (uint64_t)(DPAA2_VADDR_TO_IOVA(p_params)); ++ tc_cfg.dist_size = 0; ++ tc_cfg.dist_mode = DPNI_DIST_MODE_NONE; ++ ++ ret = dpni_prepare_key_cfg(&kg_cfg, p_params); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Unable to prepare extract parameters\n"); ++ rte_free(p_params); ++ return ret; ++ } ++ ++ ret = dpni_set_rx_tc_dist(dpni, CMD_PRI_LOW, priv->token, tc_index, ++ &tc_cfg); ++ rte_free(p_params); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Setting distribution for Rx failed with" ++ "err code: %d\n", ret); ++ return ret; ++ } ++ return ret; ++} ++ ++static int ++dpaa2_alloc_dq_storage(struct queue_storage_info_t *q_storage) ++{ ++ int i = 0; ++ ++ for (i = 0; i < NUM_DQS_PER_QUEUE; i++) { ++ q_storage->dq_storage[i] = rte_malloc(NULL, ++ NUM_MAX_RECV_FRAMES * sizeof(struct qbman_result), ++ RTE_CACHE_LINE_SIZE); ++ if (!q_storage->dq_storage[i]) ++ goto fail; ++ /*setting toggle for initial condition*/ ++ q_storage->toggle = -1; ++ } ++ return 0; ++fail: ++ i -= 1; ++ while (i >= 0) ++ rte_free(q_storage->dq_storage[i]); ++ ++ return -1; ++} ++ ++static int ++dpaa2_eth_dev_configure(struct rte_eth_dev *dev) ++{ ++ struct rte_eth_dev_data *data = dev->data; ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct rte_eth_conf *eth_conf = &data->dev_conf; ++ struct dpaa2_queue *dpaa2_q; ++ int i, ret; ++ ++ for (i = 0; i < data->nb_rx_queues; i++) { ++ data->rx_queues[i] = priv->rx_vq[i]; ++ dpaa2_q = (struct dpaa2_queue *)data->rx_queues[i]; ++ if (dpaa2_alloc_dq_storage(dpaa2_q->q_storage)) ++ return -1; ++ } ++ ++ for (i = 0; i < data->nb_tx_queues; i++) { ++ data->tx_queues[i] = priv->tx_vq[i]; ++ dpaa2_q = (struct dpaa2_queue *)data->tx_queues[i]; ++ dpaa2_q->cscn = rte_malloc(NULL, sizeof(struct qbman_result), 16); ++ if (!dpaa2_q->cscn) ++ goto fail_tx_queue; ++ } ++ ++ /* Check for correct configuration */ ++ if (eth_conf->rxmode.mq_mode != ETH_MQ_RX_RSS && ++ data->nb_rx_queues > 1) { ++ PMD_DRV_LOG(ERR, "Distribution is not enabled, " ++ "but Rx queues more than 1\n"); ++ return -1; ++ } ++ ++ if (eth_conf->rxmode.mq_mode == ETH_MQ_RX_RSS) { ++ /* Return in case number of Rx queues is 1 */ ++ if (data->nb_rx_queues == 1) ++ return 0; ++ ret = dpaa2_setup_flow_distribution(dev, ++ eth_conf->rx_adv_conf.rss_conf.rss_hf); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "dpaa2_setup_flow_distribution failed\n"); ++ return ret; ++ } ++ } ++ ++ return 0; ++ fail_tx_queue: ++ i -= 1; ++ while (i >= 0) { ++ dpaa2_q = (struct dpaa2_queue *)data->tx_queues[i]; ++ rte_free(dpaa2_q->cscn); ++ } ++ return -1; ++} ++ ++static int dpaa2_attach_bp_list(struct dpaa2_dev_priv *priv, ++ void *blist) ++{ ++ /* Function to attach a DPNI with a buffer pool list. Buffer pool list ++ * handle is passed in blist. ++ */ ++ int32_t retcode; ++ struct fsl_mc_io *dpni = priv->hw; ++ struct dpni_pools_cfg bpool_cfg; ++ struct dpaa2_bp_list *bp_list = (struct dpaa2_bp_list *)blist; ++ struct dpni_buffer_layout layout; ++ int tot_size; ++ ++ /* ... rx buffer layout . ++ Check alignment for buffer layouts first*/ ++ ++ /* ... rx buffer layout ... */ ++ tot_size = DPAA2_HW_BUF_RESERVE + RTE_PKTMBUF_HEADROOM; ++ tot_size = RTE_ALIGN_CEIL(tot_size, ++ DPAA2_PACKET_LAYOUT_ALIGN); ++ ++ memset(&layout, 0, sizeof(struct dpni_buffer_layout)); ++ layout.options = DPNI_BUF_LAYOUT_OPT_DATA_HEAD_ROOM; ++ ++ layout.data_head_room = tot_size - DPAA2_FD_PTA_SIZE - DPAA2_MBUF_HW_ANNOTATION; ++ retcode = dpni_set_rx_buffer_layout(dpni, CMD_PRI_LOW, priv->token, ++ &layout); ++ if (retcode) { ++ PMD_DRV_LOG(ERR, "Err(%d) in setting rx buffer layout\n", retcode); ++ return retcode; ++ } ++ ++ /*Attach buffer pool to the network interface as described by the user*/ ++ bpool_cfg.num_dpbp = 1; ++ bpool_cfg.pools[0].dpbp_id = bp_list->buf_pool.dpbp_node->dpbp_id; ++ bpool_cfg.pools[0].backup_pool = 0; ++ bpool_cfg.pools[0].buffer_size = ++ RTE_ALIGN_CEIL(bp_list->buf_pool.size, ++ 256 /*DPAA2_PACKET_LAYOUT_ALIGN*/); ++ ++ retcode = dpni_set_pools(dpni, CMD_PRI_LOW, priv->token, &bpool_cfg); ++ if (retcode != 0) { ++ PMD_DRV_LOG(ERR, "Error in attaching the buffer pool list" ++ "bpid = %d Error code = %d\n", ++ bpool_cfg.pools[0].dpbp_id, retcode); ++ return retcode; ++ } ++ ++ priv->bp_list = bp_list; ++ return 0; ++} ++ ++/* Function to setup RX flow information. It contains traffic class ID, ++ * flow ID, destination configuration etc. ++ */ ++static int ++dpaa2_rx_queue_setup(struct rte_eth_dev *dev, ++ uint16_t rx_queue_id, ++ uint16_t nb_rx_desc __rte_unused, ++ unsigned int socket_id __rte_unused, ++ const struct rte_eth_rxconf *rx_conf __rte_unused, ++ struct rte_mempool *mb_pool) ++{ ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ struct dpaa2_queue *dpaa2_q; ++ struct dpni_queue_cfg cfg; ++ uint8_t tc_id, flow_id; ++ uint32_t bpid; ++ int ret; ++ ++ PMD_DRV_LOG(INFO, "dev =%p, queue =%d, pool = %p, conf =%p", ++ dev, rx_queue_id, mb_pool, rx_conf); ++ ++ if (!priv->bp_list || priv->bp_list->mp != mb_pool) { ++ RTE_VERIFY(mb_pool->pool_data); ++ bpid = mempool_to_bpid(mb_pool); ++ ret = dpaa2_attach_bp_list(priv, ++ bpid_info[bpid].bp_list); ++ if (ret) ++ return ret; ++ } ++ dpaa2_q = (struct dpaa2_queue *)dev->data->rx_queues[rx_queue_id]; ++ ++ /*Get the tc id and flow id from given VQ id*/ ++ tc_id = rx_queue_id / MAX_DIST_PER_TC; ++ flow_id = rx_queue_id % MAX_DIST_PER_TC; ++ memset(&cfg, 0, sizeof(struct dpni_queue_cfg)); ++ ++ cfg.options = cfg.options | DPNI_QUEUE_OPT_USER_CTX; ++ ++#ifdef DPAA2_STASHING ++ cfg.options = cfg.options | DPNI_QUEUE_OPT_FLC; ++#endif ++ ++ cfg.user_ctx = (uint64_t)(dpaa2_q); ++#ifdef DPAA2_STASHING ++ cfg.flc_cfg.flc_type = DPNI_FLC_STASH; ++ cfg.flc_cfg.frame_data_size = DPNI_STASH_SIZE_64B; ++ /* Enabling Annotation stashing */ ++ cfg.options |= DPNI_FLC_STASH_FRAME_ANNOTATION; ++ cfg.flc_cfg.options = DPNI_FLC_STASH_FRAME_ANNOTATION; ++#endif ++ ret = dpni_set_rx_flow(dpni, CMD_PRI_LOW, priv->token, ++ tc_id, flow_id, &cfg); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Error in setting the rx flow: = %d\n", ret); ++ return -1; ++ } ++ return 0; ++} ++ ++static int ++dpaa2_tx_queue_setup(struct rte_eth_dev *dev, ++ uint16_t tx_queue_id, ++ uint16_t nb_tx_desc __rte_unused, ++ unsigned int socket_id __rte_unused, ++ const struct rte_eth_txconf *tx_conf __rte_unused) ++{ ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct dpaa2_queue *dpaa2_q = (struct dpaa2_queue *) ++ dev->data->tx_queues[tx_queue_id]; ++ struct fsl_mc_io *dpni = priv->hw; ++ struct dpni_tx_flow_cfg cfg; ++ struct dpni_tx_conf_cfg tx_conf_cfg; ++#ifdef DPAA2_CGR_SUPPORT ++ struct dpni_congestion_notification_cfg cong_notif_cfg; ++#endif ++ uint32_t tc_idx; ++ int ret; ++ ++ PMD_INIT_FUNC_TRACE(); ++ ++ /* Return if queue already configured */ ++ if (dpaa2_q->flow_id != DPNI_NEW_FLOW_ID) ++ return 0; ++ ++ memset(&cfg, 0, sizeof(struct dpni_tx_flow_cfg)); ++ cfg.l3_chksum_gen = 1; ++ cfg.options |= DPNI_TX_FLOW_OPT_L3_CHKSUM_GEN; ++ cfg.l4_chksum_gen = 1; ++ cfg.options = DPNI_TX_FLOW_OPT_L4_CHKSUM_GEN; ++ memset(&tx_conf_cfg, 0, sizeof(struct dpni_tx_conf_cfg)); ++ tx_conf_cfg.errors_only = TRUE; ++ ++ /* ++ if (action & DPAA2BUF_TX_CONF_REQUIRED) { ++ cfg.options = DPNI_TX_FLOW_OPT_TX_CONF_ERROR; ++ cfg.use_common_tx_conf_queue = ++ ((action & DPAA2BUF_TX_CONF_ERR_ON_COMMON_Q) ? ++ TRUE : FALSE); ++ tx_conf_cfg.errors_only = FALSE; ++ }*/ ++ ++ if (priv->num_tc == 1) ++ tc_idx = 0; ++ else ++ tc_idx = tx_queue_id; ++ ++ ret = dpni_set_tx_flow(dpni, CMD_PRI_LOW, priv->token, ++ &(dpaa2_q->flow_id), &cfg); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Error in setting the tx flow:" ++ "ErrorCode = %x\n", ret); ++ return -1; ++ } ++ /*Set tx-conf and error configuration*/ ++ ret = dpni_set_tx_conf(dpni, CMD_PRI_LOW, priv->token, ++ dpaa2_q->flow_id, &tx_conf_cfg); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Error in setting tx conf settings: " ++ "ErrorCode = %x", ret); ++ return -1; ++ } ++ ++ if (tx_queue_id == 0) { ++ /*Set tx-conf and error configuration*/ ++ ret = dpni_set_tx_conf(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_COMMON_TX_CONF, &tx_conf_cfg); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Error in setting tx conf settings: " ++ "ErrorCode = %x", ret); ++ return -1; ++ } ++ } ++ dpaa2_q->tc_index = tc_idx; ++ ++#ifdef DPAA2_CGR_SUPPORT ++ cong_notif_cfg.units = DPNI_CONGESTION_UNIT_BYTES; ++ /*Notify about congestion when the queue size is 128 frames with each \ ++ frame 64 bytes size*/ ++ cong_notif_cfg.threshold_entry = CONG_ENTER_THRESHOLD; ++ /*Notify that the queue is not congested when the number of frames in \ ++ the queue is below this thershold. ++ TODO: Check if this value is the optimum value for better performance*/ ++ cong_notif_cfg.threshold_exit = CONG_EXIT_THRESHOLD; ++ cong_notif_cfg.message_ctx = 0; ++ cong_notif_cfg.message_iova = (uint64_t)dpaa2_q->cscn; ++ cong_notif_cfg.dest_cfg.dest_type = DPNI_DEST_NONE; ++ cong_notif_cfg.options = DPNI_CONG_OPT_WRITE_MEM_ON_ENTER | ++ DPNI_CONG_OPT_WRITE_MEM_ON_EXIT | DPNI_CONG_OPT_COHERENT_WRITE; ++ ++ ret = dpni_set_tx_tc_congestion_notification(dpni, CMD_PRI_LOW, ++ priv->token, ++ tc_idx, &cong_notif_cfg); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Error in setting tx congestion notification " ++ "settings: ErrorCode = %x", ret); ++ return -1; ++ } ++#endif ++ return 0; ++} ++ ++void ++dpaa2_rx_queue_release(void *q) ++{ ++ printf("\n(%s) called for 1=%p\n", __func__, q); ++ return; ++} ++ ++void ++dpaa2_tx_queue_release(void *q) ++{ ++ printf("\n(%s) called for 1=%p\n", __func__, q); ++ return; ++} ++ ++static const uint32_t * ++dpaa2_supported_ptypes_get(struct rte_eth_dev *dev) ++{ ++ static const uint32_t ptypes[] = { ++ /*todo -= add more types */ ++ RTE_PTYPE_L2_ETHER, ++ RTE_PTYPE_L3_IPV4, ++ RTE_PTYPE_L3_IPV4_EXT, ++ RTE_PTYPE_L3_IPV6, ++ RTE_PTYPE_L3_IPV6_EXT, ++ RTE_PTYPE_L4_TCP, ++ RTE_PTYPE_L4_UDP, ++ RTE_PTYPE_L4_SCTP, ++ RTE_PTYPE_L4_ICMP, ++ RTE_PTYPE_UNKNOWN ++ }; ++ ++ if (dev->rx_pkt_burst == eth_dpaa2_prefetch_rx || ++ dev->rx_pkt_burst == eth_dpaa2_rx) ++ return ptypes; ++ return NULL; ++} ++ ++static int ++dpaa2_dev_start(struct rte_eth_dev *dev) ++{ ++ struct rte_eth_dev_data *data = dev->data; ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ struct dpni_queue_attr cfg; ++ uint16_t qdid; ++ struct dpaa2_queue *dpaa2_q; ++ int ret, i, mask = 0; ++ ++ PMD_INIT_FUNC_TRACE(); ++ ++ dev->data->dev_link.link_status = 1; ++ ++ ret = dpni_enable(dpni, CMD_PRI_LOW, priv->token); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Failure %d in enabling dpni %d device\n", ++ ret, priv->hw_id); ++ return ret; ++ } ++ ++ ret = dpni_get_qdid(dpni, CMD_PRI_LOW, priv->token, &qdid); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Error to get qdid:ErrorCode = %d\n", ret); ++ return ret; ++ } ++ priv->qdid = qdid; ++ ++ for (i = 0; i < data->nb_rx_queues; i++) { ++ dpaa2_q = (struct dpaa2_queue *)data->rx_queues[i]; ++ ret = dpni_get_rx_flow(dpni, CMD_PRI_LOW, priv->token, ++ dpaa2_q->tc_index, dpaa2_q->flow_id, &cfg); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Error to get flow " ++ "information Error code = %d\n", ret); ++ return ret; ++ } ++ dpaa2_q->fqid = cfg.fqid; ++ } ++ /* ++ * VLAN Offload Settings ++ */ ++ if (priv->options & DPNI_OPT_VLAN_FILTER) ++ mask = ETH_VLAN_FILTER_MASK; ++ ++ if (priv->options & DPNI_OPT_VLAN_MANIPULATION) ++ mask = ETH_VLAN_STRIP_MASK; ++ ++ if (mask) ++ dpaa2_vlan_offload_set(dev, mask); ++ ++ return 0; ++} ++ ++/********************************************************************* ++ * ++ * This routine disables all traffic on the adapter by issuing a ++ * global reset on the MAC. ++ * ++ **********************************************************************/ ++static void ++dpaa2_dev_stop(struct rte_eth_dev *dev) ++{ ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ int ret; ++ struct rte_eth_link link; ++ ++ dev->data->dev_link.link_status = 0; ++ ++ ret = dpni_disable(dpni, CMD_PRI_LOW, priv->token); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Failure in disabling dpni %d device\n", priv->hw_id); ++ return; ++ } ++ ++ /* clear the recorded link status */ ++ memset(&link, 0, sizeof(link)); ++ rte_dpni_dev_atomic_write_link_status(dev, &link); ++} ++ ++static void ++dpaa2_dev_close(struct rte_eth_dev *dev) ++{ ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ int ret; ++ struct rte_eth_link link; ++ ++ /*Function is reverse of dpaa2_dev_init. ++ * It does the following: ++ * 1. Detach a DPNI from attached resources i.e. buffer pools, dpbp_id. ++ * 2. Close the DPNI device ++ * 3. Free the allocated reqources. ++ */ ++ ++ /* Clean the device first */ ++ ret = dpni_reset(dpni, CMD_PRI_LOW, priv->token); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Failure cleaning dpni device with" ++ "error code %d\n", ret); ++ return; ++ } ++ ++ /*Close the device at underlying layer*/ ++ ret = dpni_close(dpni, CMD_PRI_LOW, priv->token); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Failure closing dpni device with" ++ "error code %d\n", ret); ++ return; ++ } ++ ++ /*Free the allocated memory for ethernet private data and dpni*/ ++ priv->hw = NULL; ++ free(dpni); ++ ++ memset(&link, 0, sizeof(link)); ++ rte_dpni_dev_atomic_write_link_status(dev, &link); ++} ++ ++static void ++dpaa2_dev_promiscuous_enable( ++ struct rte_eth_dev *dev) ++{ ++ int ret; ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ ++ if (dpni == NULL) { ++ PMD_DRV_LOG(ERR, "dpni is NULL"); ++ return; ++ } ++ ++ ret = dpni_set_unicast_promisc(dpni, CMD_PRI_LOW, priv->token, TRUE); ++ if (ret < 0) ++ PMD_DRV_LOG(ERR, "Unable to enable promiscuous mode"); ++ return; ++} ++ ++static void ++dpaa2_dev_promiscuous_disable( ++ struct rte_eth_dev *dev) ++{ ++ int ret; ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ ++ if (dpni == NULL) { ++ PMD_DRV_LOG(ERR, "dpni is NULL"); ++ return; ++ } ++ ++ ret = dpni_set_unicast_promisc(dpni, CMD_PRI_LOW, priv->token, FALSE); ++ if (ret < 0) ++ PMD_DRV_LOG(ERR, "Unable to disable promiscuous mode"); ++ return; ++} ++ ++static void ++dpaa2_dev_allmulticast_enable( ++ struct rte_eth_dev *dev) ++{ ++ int ret; ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ ++ if (dpni == NULL) { ++ PMD_DRV_LOG(ERR, "dpni is NULL"); ++ return; ++ } ++ ++ ret = dpni_set_multicast_promisc(dpni, CMD_PRI_LOW, priv->token, true); ++ if (ret < 0) ++ PMD_DRV_LOG(ERR, "Unable to enable promiscuous mode"); ++ return; ++} ++ ++static void ++dpaa2_dev_allmulticast_disable(struct rte_eth_dev *dev) ++{ ++ int ret; ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ ++ if (dpni == NULL) { ++ PMD_DRV_LOG(ERR, "dpni is NULL"); ++ return; ++ } ++ ++ ret = dpni_set_multicast_promisc(dpni, CMD_PRI_LOW, priv->token, false); ++ if (ret < 0) ++ PMD_DRV_LOG(ERR, "Unable to enable promiscuous mode"); ++ return; ++} ++ ++static int dpaa2_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) ++{ ++ int ret; ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ uint32_t frame_size = mtu + ETHER_HDR_LEN + ETHER_CRC_LEN; ++ ++ if (dpni == NULL) { ++ PMD_DRV_LOG(ERR, "dpni is NULL"); ++ return -EINVAL; ++ } ++ ++ /* check that mtu is within the allowed range */ ++ if ((mtu < ETHER_MIN_MTU) || (frame_size > DPAA2_MAX_RX_PKT_LEN)) ++ return -EINVAL; ++ ++ /* Set the Max Rx frame length as 'mtu' + ++ * Maximum Ethernet header length */ ++ ret = dpni_set_max_frame_length(dpni, CMD_PRI_LOW, priv->token, ++ mtu + ETH_VLAN_HLEN); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "setting the max frame length failed"); ++ return -1; ++ } ++ if (priv->options & DPNI_OPT_IPF) { ++ ret = dpni_set_mtu(dpni, CMD_PRI_LOW, priv->token, mtu); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Setting the MTU failed"); ++ return -1; ++ } ++ } ++ ++ PMD_DRV_LOG(INFO, "MTU is configured %d for the device\n", mtu); ++ return 0; ++} ++ ++static int ++dpaa2_flow_ctrl_set(struct rte_eth_dev *dev __rte_unused, ++ struct rte_eth_fc_conf *fc_conf __rte_unused) ++{ ++ return 0; ++} ++static void ++dpaa2_dev_add_mac_addr(struct rte_eth_dev *dev, ++ struct ether_addr *addr, ++ __rte_unused uint32_t index, ++ __rte_unused uint32_t pool) ++{ ++ int ret; ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ ++ if (dpni == NULL) { ++ PMD_DRV_LOG(ERR, "dpni is NULL"); ++ return; ++ } ++ ++ ret = dpni_add_mac_addr(dpni, CMD_PRI_LOW, ++ priv->token, addr->addr_bytes); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Adding the MAC ADDR failed"); ++ } ++ ++ return; ++} ++ ++static void ++dpaa2_dev_remove_mac_addr(struct rte_eth_dev *dev, ++ uint32_t index) ++{ ++ int ret; ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ struct rte_eth_dev_data *data = dev->data; ++ struct ether_addr *macaddr; ++ ++ macaddr = &data->mac_addrs[index]; ++ ++ if (dpni == NULL) { ++ PMD_DRV_LOG(ERR, "dpni is NULL"); ++ return; ++ } ++ ++ ret = dpni_remove_mac_addr(dpni, CMD_PRI_LOW, ++ priv->token, macaddr->addr_bytes); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Removing the MAC ADDR failed"); ++ } ++ ++ return; ++} ++ ++static void ++dpaa2_dev_set_mac_addr(struct rte_eth_dev *dev, ++ struct ether_addr *addr) ++{ ++ int ret; ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ ++ if (dpni == NULL) { ++ PMD_DRV_LOG(ERR, "dpni is NULL"); ++ return; ++ } ++ ++ ret = dpni_set_primary_mac_addr(dpni, CMD_PRI_LOW, ++ priv->token, addr->addr_bytes); ++ ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Setting the MAC ADDR failed"); ++ } ++ ++ return; ++} ++ ++int dpaa2_dev_get_mac_addr(struct rte_eth_dev *dev, ++ struct ether_addr *addr) ++{ ++ int ret; ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ ++ if (dpni == NULL) { ++ PMD_DRV_LOG(ERR, "dpni is NULL"); ++ return -EINVAL; ++ } ++ ++ ret = dpni_get_primary_mac_addr(dpni, CMD_PRI_LOW, ++ priv->token, addr->addr_bytes); ++ ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Getting the MAC ADDR failed"); ++ } ++ ++ return ret; ++} ++ ++/*int dpni_clear_mac_filters(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int unicast, ++ int multicast) ++ ++int dpni_set_vlan_insertion(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en) ++ ++dpni_set_errors_behavior ++ ++int dpni_get_l3_chksum_validation(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en) ++ ++int dpni_set_l3_chksum_validation(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en) ++ ++int dpni_get_l4_chksum_validation(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int *en) ++ ++int dpni_set_l4_chksum_validation(struct fsl_mc_io *mc_io, ++ uint32_t cmd_flags, ++ uint16_t token, ++ int en) ++ ++*/ ++ ++static int dpaa2_timestamp_enable(struct rte_eth_dev *dev) ++{ ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ ++ struct dpni_buffer_layout layout; ++ int ret; ++ ++ layout.options = DPNI_BUF_LAYOUT_OPT_TIMESTAMP; ++ layout.pass_timestamp = TRUE; ++ ++ ret = dpni_set_rx_buffer_layout(dpni, CMD_PRI_LOW, priv->token, &layout); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Enabling timestamp for Rx failed with" ++ "err code: %d", ret); ++ return ret; ++ } ++ ++ ret = dpni_set_tx_buffer_layout(dpni, CMD_PRI_LOW, priv->token, &layout); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Enabling timestamp failed for Tx with" ++ "err code: %d", ret); ++ return ret; ++ } ++ ++ ret = dpni_set_tx_conf_buffer_layout(dpni, CMD_PRI_LOW, ++ priv->token, &layout); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Enabling timestamp failed for Tx-conf with" ++ "err code: %d", ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int dpaa2_timestamp_disable(struct rte_eth_dev *dev) ++{ ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ struct dpni_buffer_layout layout; ++ int ret; ++ ++ layout.options = DPNI_BUF_LAYOUT_OPT_TIMESTAMP; ++ layout.pass_timestamp = FALSE; ++ ++ ret = dpni_set_rx_buffer_layout(dpni, CMD_PRI_LOW, priv->token, &layout); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Disabling timestamp failed for Rx with" ++ "err code: %d", ret); ++ return ret; ++ } ++ ++ ret = dpni_set_tx_buffer_layout(dpni, CMD_PRI_LOW, priv->token, &layout); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Disabling timestamp failed for Tx with" ++ "err code: %d", ret); ++ return ret; ++ } ++ ++ ret = dpni_set_tx_conf_buffer_layout(dpni, CMD_PRI_LOW, ++ priv->token, &layout); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Disabling timestamp failed for Tx-conf with" ++ "err code: %d", ret); ++ return ret; ++ } ++ ++ return ret; ++} ++ ++/* return 0 means link status changed, -1 means not changed */ ++static int ++dpaa2_dev_get_link_info(struct rte_eth_dev *dev, ++ int wait_to_complete __rte_unused) ++{ ++ int ret; ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ struct rte_eth_link link, old; ++ struct dpni_link_state state = {0}; ++ ++ if (dpni == NULL) { ++ PMD_DRV_LOG(ERR, "dpni is NULL"); ++ return 0; ++ } ++ memset(&old, 0, sizeof(old)); ++ rte_dpni_dev_atomic_read_link_status(dev, &old); ++ ++ ret = dpni_get_link_state(dpni, CMD_PRI_LOW, priv->token, &state); ++ if (ret < 0) { ++ PMD_DRV_LOG(ERR, "dpni_get_link_state"); ++ return 0; ++ } ++ ++ if (state.up == 0) { ++ rte_dpni_dev_atomic_write_link_status(dev, &link); ++ if (state.up == old.link_status) ++ return -1; ++ return 0; ++ } ++ link.link_status = state.up; ++ link.link_speed = state.rate; ++ ++ if (state.options & DPNI_LINK_OPT_HALF_DUPLEX) ++ link.link_duplex = ETH_LINK_HALF_DUPLEX; ++ else ++ link.link_duplex = ETH_LINK_FULL_DUPLEX; ++ ++ rte_dpni_dev_atomic_write_link_status(dev, &link); ++ ++ if (link.link_status == old.link_status) ++ return -1; ++ ++ return 0; ++} ++ ++static ++void dpaa2_dev_stats_get(struct rte_eth_dev *dev, ++ struct rte_eth_stats *stats) ++{ ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ ++ int32_t retcode; ++ uint64_t value; ++ ++ if (dpni == NULL) { ++ PMD_DRV_LOG(ERR, "dpni is NULL"); ++ return; ++ } ++ ++ if (!stats) { ++ PMD_DRV_LOG(ERR, "stats is NULL"); ++ return; ++ } ++ ++ retcode = dpni_get_counter(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_CNT_ING_FRAME, &value); ++ if (retcode) ++ goto error; ++ stats->ipackets = value; ++ retcode = dpni_get_counter(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_CNT_ING_BYTE, &value); ++ if (retcode) ++ goto error; ++ stats->ibytes = value; ++ retcode = dpni_get_counter(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_CNT_ING_FRAME_DROP, &value); ++ if (retcode) ++ goto error; ++ stats->ierrors = value; ++ retcode = dpni_get_counter(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_CNT_ING_FRAME_DISCARD, &value); ++ if (retcode) ++ goto error; ++ stats->ierrors = stats->ierrors + value; ++ retcode = dpni_get_counter(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_CNT_EGR_FRAME, &value); ++ if (retcode) ++ goto error; ++ stats->opackets = value; ++ dpni_get_counter(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_CNT_EGR_BYTE, &value); ++ if (retcode) ++ goto error; ++ stats->obytes = value; ++ retcode = dpni_get_counter(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_CNT_EGR_FRAME_DISCARD, &value); ++ if (retcode) ++ goto error; ++ stats->oerrors = value; ++ ++ return; ++ ++error: ++ PMD_DRV_LOG(ERR, "Operation not completed:Error Code = %d\n", retcode); ++ return; ++}; ++ ++static ++void dpaa2_dev_stats_reset(struct rte_eth_dev *dev) ++{ ++ struct dpaa2_dev_priv *priv = dev->data->dev_private; ++ struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw; ++ ++ int32_t retcode; ++ ++ if (dpni == NULL) { ++ PMD_DRV_LOG(ERR, "dpni is NULL"); ++ return; ++ } ++ ++ retcode = dpni_set_counter(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_CNT_ING_FRAME, 0); ++ if (retcode) ++ goto error; ++ retcode = dpni_set_counter(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_CNT_ING_BYTE, 0); ++ if (retcode) ++ goto error; ++ retcode = dpni_set_counter(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_CNT_ING_BCAST_FRAME, 0); ++ if (retcode) ++ goto error; ++ retcode = dpni_set_counter(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_CNT_ING_BCAST_BYTES, 0); ++ if (retcode) ++ goto error; ++ retcode = dpni_set_counter(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_CNT_ING_MCAST_FRAME, 0); ++ if (retcode) ++ goto error; ++ retcode = dpni_set_counter(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_CNT_ING_MCAST_BYTE, 0); ++ if (retcode) ++ goto error; ++ retcode = dpni_set_counter(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_CNT_ING_FRAME_DROP, 0); ++ if (retcode) ++ goto error; ++ retcode = dpni_set_counter(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_CNT_ING_FRAME_DISCARD, 0); ++ if (retcode) ++ goto error; ++ retcode = dpni_set_counter(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_CNT_EGR_FRAME, 0); ++ if (retcode) ++ goto error; ++ retcode = dpni_set_counter(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_CNT_EGR_BYTE, 0); ++ if (retcode) ++ goto error; ++ retcode = dpni_set_counter(dpni, CMD_PRI_LOW, priv->token, ++ DPNI_CNT_EGR_FRAME_DISCARD, 0); ++ if (retcode) ++ goto error; ++ ++ return; ++ ++error: ++ PMD_DRV_LOG(ERR, "Operation not completed:Error Code = %d\n", retcode); ++ return; ++}; ++ ++static struct eth_dev_ops ops = { ++ .dev_configure = dpaa2_eth_dev_configure, ++ .dev_start = dpaa2_dev_start, ++ .dev_stop = dpaa2_dev_stop, ++ .dev_close = dpaa2_dev_close, ++ .promiscuous_enable = dpaa2_dev_promiscuous_enable, ++ .promiscuous_disable = dpaa2_dev_promiscuous_disable, ++ .allmulticast_enable = dpaa2_dev_allmulticast_enable, ++ .allmulticast_disable = dpaa2_dev_allmulticast_disable, ++ .dev_set_link_up = NULL, ++ .dev_set_link_down = NULL, ++ .link_update = dpaa2_dev_get_link_info, ++ .stats_get = dpaa2_dev_stats_get, ++ .stats_reset = dpaa2_dev_stats_reset, ++ .dev_infos_get = dpaa2_eth_dev_info, ++ .dev_supported_ptypes_get = dpaa2_supported_ptypes_get, ++ .mtu_set = dpaa2_dev_mtu_set, ++ .vlan_filter_set = dpaa2_vlan_filter_set, ++ .vlan_tpid_set = NULL, ++ .vlan_offload_set = dpaa2_vlan_offload_set, ++ .vlan_strip_queue_set = NULL, ++ .vlan_pvid_set = NULL, ++ .rx_queue_setup = dpaa2_rx_queue_setup, ++ .rx_queue_release = dpaa2_rx_queue_release, ++ .tx_queue_setup = dpaa2_tx_queue_setup, ++ .tx_queue_release = dpaa2_tx_queue_release, ++ .dev_led_on = NULL, ++ .dev_led_off = NULL, ++ .set_queue_rate_limit = NULL, ++ .flow_ctrl_get = NULL, ++ .flow_ctrl_set = dpaa2_flow_ctrl_set, ++ .priority_flow_ctrl_set = NULL, ++ .mac_addr_add = dpaa2_dev_add_mac_addr, ++ .mac_addr_remove = dpaa2_dev_remove_mac_addr, ++ .rxq_info_get = NULL, ++ .txq_info_get = NULL, ++ .timesync_enable = dpaa2_timestamp_enable, ++ .timesync_disable = dpaa2_timestamp_disable, ++ .mac_addr_set = dpaa2_dev_set_mac_addr, ++}; ++ ++static int ++dpaa2_dev_init(struct rte_eth_dev *eth_dev) ++{ ++ struct rte_eth_dev_data *data = eth_dev->data; ++ struct fsl_mc_io *dpni_dev; ++ struct dpni_attr attr; ++ struct dpaa2_dev_priv *priv = eth_dev->data->dev_private; ++ struct dpni_buffer_layout layout; ++ int i, ret, hw_id = eth_dev->pci_dev->addr.devid; ++ struct dpni_extended_cfg *ext_cfg = NULL; ++ int tot_size; ++ ++ PMD_INIT_FUNC_TRACE(); ++ ++ dpni_dev = (struct fsl_mc_io *)malloc(sizeof(struct fsl_mc_io)); ++ if (!dpni_dev) { ++ PMD_DRV_LOG(ERR, "malloc failed for dpni device\n"); ++ return -1; ++ } ++ ++ dpni_dev->regs = mcp_ptr_list[0]; ++ ret = dpni_open(dpni_dev, CMD_PRI_LOW, hw_id, &priv->token); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Failure in opening dpni@%d device with" ++ "error code %d\n", hw_id, ret); ++ return -1; ++ } ++ ++ /* Clean the device first */ ++ ret = dpni_reset(dpni_dev, CMD_PRI_LOW, priv->token); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Failure cleaning dpni@%d device with" ++ "error code %d\n", hw_id, ret); ++ return -1; ++ } ++ ++ ext_cfg = (struct dpni_extended_cfg *)rte_malloc(NULL, 256, ++ RTE_CACHE_LINE_SIZE); ++ if (!ext_cfg) { ++ PMD_DRV_LOG(ERR, "No data memory\n"); ++ return -1; ++ } ++ attr.ext_cfg_iova = (uint64_t)(DPAA2_VADDR_TO_IOVA(ext_cfg)); ++ ++ ret = dpni_get_attributes(dpni_dev, CMD_PRI_LOW, priv->token, &attr); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Failure in getting dpni@%d attribute, " ++ "error code %d\n", hw_id, ret); ++ return -1; ++ } ++ ++ priv->num_tc = attr.max_tcs; ++ for (i = 0; i < attr.max_tcs; i++) { ++ priv->num_dist_per_tc[i] = ext_cfg->tc_cfg[i].max_dist; ++ priv->nb_rx_queues += priv->num_dist_per_tc[i]; ++ break; ++ } ++ if (attr.max_tcs == 1) ++ priv->nb_tx_queues = attr.max_senders; ++ else ++ priv->nb_tx_queues = attr.max_tcs; ++ PMD_DRV_LOG(INFO, "num_tc %d", priv->num_tc); ++ PMD_DRV_LOG(INFO, "nb_rx_queues %d", priv->nb_rx_queues); ++ ++ eth_dev->data->nb_rx_queues = priv->nb_rx_queues; ++ eth_dev->data->nb_tx_queues = priv->nb_tx_queues; ++ ++ priv->hw = dpni_dev; ++ priv->hw_id = hw_id; ++ priv->options = attr.options; ++ ++ priv->max_unicast_filters = attr.max_unicast_filters; ++ priv->max_multicast_filters = attr.max_multicast_filters; ++ ++ if (attr.options & DPNI_OPT_VLAN_FILTER) ++ priv->max_vlan_filters = attr.max_vlan_filters; ++ else ++ priv->max_vlan_filters = 0; ++ ++ ret = dpaa2_alloc_rx_tx_queues(eth_dev); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "dpaa2_alloc_rx_tx_queuesFailed\n"); ++ return -1; ++ } ++ ++ data->mac_addrs = (struct ether_addr *)malloc(sizeof(struct ether_addr)); ++ ++ /* Allocate memory for storing MAC addresses */ ++ eth_dev->data->mac_addrs = rte_zmalloc("dpni", ++ ETHER_ADDR_LEN * attr.max_unicast_filters, 0); ++ if (eth_dev->data->mac_addrs == NULL) { ++ PMD_DRV_LOG(ERR, "Failed to allocate %d bytes needed to " ++ "store MAC addresses", ++ ETHER_ADDR_LEN * attr.max_unicast_filters); ++ return -ENOMEM; ++ } ++ ++ ret = dpni_get_primary_mac_addr(dpni_dev, CMD_PRI_LOW, ++ priv->token, ++ (uint8_t *)(data->mac_addrs[0].addr_bytes)); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "DPNI get mac address failed:" ++ " Error Code = %d\n", ret); ++ return -1; ++ } ++ ++ PMD_DRV_LOG(INFO, "Adding Broadcast Address..."); ++ memset(data->mac_addrs[1].addr_bytes, 0xff, ETH_ADDR_LEN); ++ ret = dpni_add_mac_addr(dpni_dev, CMD_PRI_LOW, ++ priv->token, ++ (uint8_t *)(data->mac_addrs[1].addr_bytes)); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "DPNI set broadcast mac address failed:" ++ " Error Code = %0x\n", ret); ++ return -1; ++ } ++ ++ /* ... rx buffer layout ... */ ++ tot_size = DPAA2_HW_BUF_RESERVE + RTE_PKTMBUF_HEADROOM; ++ tot_size = RTE_ALIGN_CEIL(tot_size, ++ DPAA2_PACKET_LAYOUT_ALIGN); ++ ++ memset(&layout, 0, sizeof(struct dpni_buffer_layout)); ++ layout.options = DPNI_BUF_LAYOUT_OPT_FRAME_STATUS | ++ DPNI_BUF_LAYOUT_OPT_TIMESTAMP | ++ DPNI_BUF_LAYOUT_OPT_PARSER_RESULT | ++ DPNI_BUF_LAYOUT_OPT_DATA_HEAD_ROOM | ++ DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE; ++ ++ layout.pass_frame_status = 1; ++ layout.data_head_room = tot_size ++ - DPAA2_FD_PTA_SIZE - DPAA2_MBUF_HW_ANNOTATION; ++ layout.private_data_size = DPAA2_FD_PTA_SIZE; ++ layout.pass_timestamp = 1; ++ layout.pass_parser_result = 1; ++ PMD_DRV_LOG(INFO, "Tot_size = %d, head room = %d, private = %d", ++ tot_size, layout.data_head_room, layout.private_data_size); ++ ret = dpni_set_rx_buffer_layout(dpni_dev, CMD_PRI_LOW, priv->token, ++ &layout); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Err(%d) in setting rx buffer layout\n", ret); ++ return -1; ++ } ++ ++ /* ... tx buffer layout ... */ ++ memset(&layout, 0, sizeof(struct dpni_buffer_layout)); ++ layout.options = DPNI_BUF_LAYOUT_OPT_FRAME_STATUS | ++ DPNI_BUF_LAYOUT_OPT_TIMESTAMP; ++ layout.pass_frame_status = 1; ++ layout.pass_timestamp = 1; ++ ret = dpni_set_tx_buffer_layout(dpni_dev, CMD_PRI_LOW, priv->token, &layout); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Error (%d) in setting tx buffer layout\n", ret); ++ return -1; ++ } ++ ++ /* ... tx-conf and error buffer layout ... */ ++ memset(&layout, 0, sizeof(struct dpni_buffer_layout)); ++ layout.options = DPNI_BUF_LAYOUT_OPT_FRAME_STATUS | ++ DPNI_BUF_LAYOUT_OPT_TIMESTAMP; ++ layout.pass_frame_status = 1; ++ layout.pass_timestamp = 1; ++ ret = dpni_set_tx_conf_buffer_layout(dpni_dev, CMD_PRI_LOW, priv->token, &layout); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Error (%d) in setting tx-conf buffer layout\n", ret); ++ return -1; ++ } ++ ++ /* TODO - Set the MTU if required */ ++ ++ eth_dev->dev_ops = &ops; ++ eth_dev->rx_pkt_burst = eth_dpaa2_prefetch_rx;/*eth_dpaa2_rx;*/ ++ eth_dev->tx_pkt_burst = eth_dpaa2_tx; ++ ++ rte_free(ext_cfg); ++ ++ return 0; ++} ++ ++static struct eth_driver rte_dpaa2_dpni = { ++ { ++ .name = "rte_dpaa2_dpni", ++ .id_table = pci_id_dpaa2_map, ++ }, ++ .eth_dev_init = dpaa2_dev_init, ++ .dev_private_size = sizeof(struct dpaa2_dev_priv), ++}; ++ ++static int ++rte_pmd_dpaa2_devinit( ++ const char *name __rte_unused, ++ const char *params __rte_unused) ++{ ++ PMD_DRV_LOG(INFO, "Initializing dpaa2_pmd for %s\n", name); ++ rte_eth_driver_register(&rte_dpaa2_dpni); ++ ++ return 0; ++} ++ ++static struct rte_driver pmd_dpaa2_drv = { ++ .name = "dpaa2_pmd", ++ .type = PMD_PDEV, ++ .init = rte_pmd_dpaa2_devinit, ++}; ++ ++PMD_REGISTER_DRIVER(pmd_dpaa2_drv, dpaa2); +diff --git a/drivers/net/dpaa2/rte_eth_dpni_annot.h b/drivers/net/dpaa2/rte_eth_dpni_annot.h +new file mode 100644 +index 0000000..0c3ae82 +--- /dev/null ++++ b/drivers/net/dpaa2/rte_eth_dpni_annot.h +@@ -0,0 +1,310 @@ ++/*- ++ * BSD LICENSE ++ * ++ * Copyright (c) 2014 Freescale Semiconductor, Inc. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * * Neither the name of Freescale Semiconductor, Inc nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++/** ++ * @file ++ * ++ * DPNI packet parse results - implementation internal ++ */ ++ ++#ifndef RTE_ETH_DPNI_ANNOT_H_ ++#define RTE_ETH_DPNI_ANNOT_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* Annotation valid bits in FD FRC */ ++#define DPAA2_FD_FRC_FASV 0x8000 ++#define DPAA2_FD_FRC_FAEADV 0x4000 ++#define DPAA2_FD_FRC_FAPRV 0x2000 ++#define DPAA2_FD_FRC_FAIADV 0x1000 ++#define DPAA2_FD_FRC_FASWOV 0x0800 ++#define DPAA2_FD_FRC_FAICFDV 0x0400 ++ ++/* Annotation bits in FD CTRL */ ++#define DPAA2_FD_CTRL_ASAL 0x00020000 /* ASAL = 128 */ ++#define DPAA2_FD_CTRL_PTA 0x00800000 ++#define DPAA2_FD_CTRL_PTV1 0x00400000 ++ ++/* Frame annotation status */ ++struct dpaa2_fas { ++ uint8_t reserved; ++ uint8_t ppid; ++ __le16 ifpid; ++ __le32 status; ++} __packed; ++ ++/** ++ * Internal Packet annotation header ++ */ ++struct pkt_annotation { ++ /**< word1: Frame Annotation Status (8 bytes)*/ ++ uint64_t word1; ++ /**< word2: Time Stamp (8 bytes)*/ ++ uint64_t word2; ++ /**< word3: Next Hdr + FAF Extension + FAF (2 + 2 + 4 bytes)*/ ++ uint64_t word3; ++ /**< word4: Frame Annotation Flags-FAF (8 bytes) */ ++ uint64_t word4; ++ /**< word5: ++ ShimOffset_1 + ShimOffset_2 + IPPIDOffset + EthOffset + ++ LLC+SNAPOffset + VLANTCIOffset_1 + VLANTCIOffset_n + ++ LastETypeOffset (1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 bytes) ++ */ ++ uint64_t word5; ++ /**< word6: ++ PPPoEOffset + MPLSOffset_1 + MPLSOffset_n + ARPorIPOffset_1 ++ + IPOffset_norMInEncapO + GREOffset + L4Offset + ++ GTPorESPorIPSecOffset(1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 bytes) ++ */ ++ uint64_t word6; ++ /**< word7: ++ RoutingHdrOfset1 + RoutingHdrOfset2 + NxtHdrOffset + IPv6FragOffset + ++ GrossRunningSum + RunningSum(1 + 1 + 1 + 1 + 2 + 2 bytes) ++ */ ++ uint64_t word7; ++ /**< word8: ++ ParseErrorcode + Soft Parsing Context (1 + 7 bytes) ++ */ ++ uint64_t word8; /**< Layer 4 length */ ++}; ++ ++/** ++ * Internal Macros to get/set Packet annotation header ++ */ ++ ++/** General Macro to define a particular bit position*/ ++#define BIT_POS(x) ((uint64_t)1 << ((x))) ++/** Set a bit in the variable */ ++#define BIT_SET_AT_POS(var, pos) (var |= pos) ++/** Reset the bit in the variable */ ++#define BIT_RESET_AT_POS(var, pos) (var &= ~(pos)) ++/** Check the bit is set in the variable */ ++#define BIT_ISSET_AT_POS(var, pos) ((var & pos) ? 1 : 0) ++/** ++ * Macrso to define bit position in word3 ++ */ ++#define NEXT_HDR(var) ((uint64_t)var & 0xFFFF000000000000) ++#define FAF_EXTN_IPV6_ROUTE_HDR_PRESENT(var) BIT_POS(16) ++#define FAF_EXTN_RESERVED(var) ((uint64_t)var & 0x00007FFF00000000) ++#define FAF_USER_DEFINED_RESERVED(var) ((uint64_t)var & 0x00000000FF000000) ++#define SHIM_SHELL_SOFT_PARSING_ERRROR BIT_POS(23) ++#define PARSING_ERROR BIT_POS(22) ++#define L2_ETH_MAC_PRESENT BIT_POS(21) ++#define L2_ETH_MAC_UNICAST BIT_POS(20) ++#define L2_ETH_MAC_MULTICAST BIT_POS(19) ++#define L2_ETH_MAC_BROADCAST BIT_POS(18) ++#define L2_ETH_FRAME_IS_BPDU BIT_POS(17) ++#define L2_ETH_FCOE_PRESENT BIT_POS(16) ++#define L2_ETH_FIP_PRESENT BIT_POS(15) ++#define L2_ETH_PARSING_ERROR BIT_POS(14) ++#define L2_LLC_SNAP_PRESENT BIT_POS(13) ++#define L2_UNKNOWN_LLC_OUI BIT_POS(12) ++#define L2_LLC_SNAP_ERROR BIT_POS(11) ++#define L2_VLAN_1_PRESENT BIT_POS(10) ++#define L2_VLAN_N_PRESENT BIT_POS(9) ++#define L2_VLAN_CFI_BIT_PRESENT BIT_POS(8) ++#define L2_VLAN_PARSING_ERROR BIT_POS(7) ++#define L2_PPPOE_PPP_PRESENT BIT_POS(6) ++#define L2_PPPOE_PPP_PARSING_ERROR BIT_POS(5) ++#define L2_MPLS_1_PRESENT BIT_POS(4) ++#define L2_MPLS_N_PRESENT BIT_POS(3) ++#define L2_MPLS_PARSING_ERROR BIT_POS(2) ++#define L2_ARP_PRESENT BIT_POS(1) ++#define L2_ARP_PARSING_ERROR BIT_POS(0) ++/** ++ * Macrso to define bit position in word4 ++ */ ++#define L2_UNKNOWN_PROTOCOL BIT_POS(63) ++#define L2_SOFT_PARSING_ERROR BIT_POS(62) ++#define L3_IPV4_1_PRESENT BIT_POS(61) ++#define L3_IPV4_1_UNICAST BIT_POS(60) ++#define L3_IPV4_1_MULTICAST BIT_POS(59) ++#define L3_IPV4_1_BROADCAST BIT_POS(58) ++#define L3_IPV4_N_PRESENT BIT_POS(57) ++#define L3_IPV4_N_UNICAST BIT_POS(56) ++#define L3_IPV4_N_MULTICAST BIT_POS(55) ++#define L3_IPV4_N_BROADCAST BIT_POS(54) ++#define L3_IPV6_1_PRESENT BIT_POS(53) ++#define L3_IPV6_1_UNICAST BIT_POS(52) ++#define L3_IPV6_1_MULTICAST BIT_POS(51) ++#define L3_IPV6_N_PRESENT BIT_POS(50) ++#define L3_IPV6_N_UNICAST BIT_POS(49) ++#define L3_IPV6_N_MULTICAST BIT_POS(48) ++#define L3_IP_1_OPT_PRESENT BIT_POS(47) ++#define L3_IP_1_UNKNOWN_PROTOCOL BIT_POS(46) ++#define L3_IP_1_MORE_FRAGMENT BIT_POS(45) ++#define L3_IP_1_FIRST_FRAGMENT BIT_POS(44) ++#define L3_IP_1_PARSING_ERROR BIT_POS(43) ++#define L3_IP_N_OPT_PRESENT BIT_POS(42) ++#define L3_IP_N_UNKNOWN_PROTOCOL BIT_POS(41) ++#define L3_IP_N_MORE_FRAGMENT BIT_POS(40) ++#define L3_IP_N_FIRST_FRAGMENT BIT_POS(39) ++#define L3_PROTO_ICMP_PRESENT BIT_POS(38) ++#define L3_PROTO_IGMP_PRESENT BIT_POS(37) ++#define L3_PROTO_ICMPV6_PRESENT BIT_POS(36) ++#define L3_PROTO_UDP_LIGHT_PRESENT BIT_POS(35) ++#define L3_IP_N_PARSING_ERROR BIT_POS(34) ++#define L3_MIN_ENCAP_PRESENT BIT_POS(33) ++#define L3_MIN_ENCAP_SBIT_PRESENT BIT_POS(32) ++#define L3_MIN_ENCAP_PARSING_ERROR BIT_POS(31) ++#define L3_PROTO_GRE_PRESENT BIT_POS(30) ++#define L3_PROTO_GRE_RBIT_PRESENT BIT_POS(29) ++#define L3_PROTO_GRE_PARSING_ERROR BIT_POS(28) ++#define L3_IP_UNKNOWN_PROTOCOL BIT_POS(27) ++#define L3_SOFT_PARSING_ERROR BIT_POS(26) ++#define L3_PROTO_UDP_PRESENT BIT_POS(25) ++#define L3_PROTO_UDP_PARSING_ERROR BIT_POS(24) ++#define L3_PROTO_TCP_PRESENT BIT_POS(23) ++#define L3_PROTO_TCP_OPT_PRESENT BIT_POS(22) ++#define L3_PROTO_TCP_CTRL_BIT_6_TO_11_PRESENT BIT_POS(21) ++#define L3_PROTO_TCP_CTRL_BIT_3_TO_5_PRESENT BIT_POS(20) ++#define L3_PROTO_TCP_PARSING_ERROR BIT_POS(19) ++#define L3_PROTO_IPSEC_PRESENT BIT_POS(18) ++#define L3_PROTO_IPSEC_ESP_PRESENT BIT_POS(17) ++#define L3_PROTO_IPSEC_AH_PRESENT BIT_POS(16) ++#define L3_PROTO_IPSEC_PARSING_ERROR BIT_POS(15) ++#define L3_PROTO_SCTP_PRESENT BIT_POS(14) ++#define L3_PROTO_SCTP_PARSING_ERROR BIT_POS(13) ++#define L3_PROTO_DCCP_PRESENT BIT_POS(12) ++#define L3_PROTO_DCCP_PARSING_ERROR BIT_POS(11) ++#define L4_UNKNOWN_PROTOCOL BIT_POS(10) ++#define L4_SOFT_PARSING_ERROR BIT_POS(9) ++#define L3_PROTO_GTP_PRESENT BIT_POS(8) ++#define L3_PROTO_GTP_PARSING_ERROR BIT_POS(7) ++#define L3_PROTO_ESP_PRESENT BIT_POS(6) ++#define L3_PROTO_ESP_PARSING_ERROR BIT_POS(5) ++#define L3_PROTO_ISCSI_PRESENT BIT_POS(4) ++#define L3_PROTO_CAPWAN__CTRL_PRESENT BIT_POS(3) ++#define L3_PROTO_CAPWAN__DATA_PRESENT BIT_POS(2) ++#define L5_SOFT_PARSING_ERROR BIT_POS(1) ++#define L3_IPV6_ROUTE_HDR_PRESENT BIT_POS(0) ++ ++/** ++ * Macros to get values in word5 ++ */ ++#define SHIM_OFFSET_1(var) ((uint64_t)var & 0xFF00000000000000) ++#define SHIM_OFFSET_2(var) ((uint64_t)var & 0x00FF000000000000) ++#define IP_PID_OFFSET(var) ((uint64_t)var & 0x0000FF0000000000) ++#define ETH_OFFSET(var) ((uint64_t)var & 0x000000FF00000000) ++#define LLC_SNAP_OFFSET(var) ((uint64_t)var & 0x00000000FF000000) ++#define VLAN_TCI_OFFSET_1(var) ((uint64_t)var & 0x0000000000FF0000) ++#define VLAN_TCI_OFFSET_N(var) ((uint64_t)var & 0x000000000000FF00) ++#define LAST_ETYPE_OFFSET(var) ((uint64_t)var & 0x00000000000000FF) ++ ++/** ++ * Macros to get values in word6 ++ */ ++#define PPPOE_OFFSET(var) ((uint64_t)var & 0xFF00000000000000) ++#define MPLS_OFFSET_1(var) ((uint64_t)var & 0x00FF000000000000) ++#define MPLS_OFFSET_N(var) ((uint64_t)var & 0x0000FF0000000000) ++#define ARP_OR_IP_OFFSET_1(var) ((uint64_t)var & 0x000000FF00000000) ++#define IP_N_OR_MIN_ENCAP_OFFSET(var) ((uint64_t)var & 0x00000000FF000000) ++#define GRE_OFFSET(var) ((uint64_t)var & 0x0000000000FF0000) ++#define L4_OFFSET(var) ((uint64_t)var & 0x000000000000FF00) ++#define GTP_OR_ESP_OR_IPSEC_OFFSET(var) ((uint64_t)var & 0x00000000000000FF) ++ ++/** ++ * Macros to get values in word7 ++ */ ++#define IPV6_ROUTING_HDR_OFFSET_1(var) ((uint64_t)var & 0xFF00000000000000) ++#define IPV6_ROUTING_HDR_OFFSET_2(var) ((uint64_t)var & 0x00FF000000000000) ++#define NEXT_HDR_OFFSET(var) ((uint64_t)var & 0x0000FF0000000000) ++#define IPV6_FRAG_OFFSET(var) ((uint64_t)var & 0x000000FF00000000) ++#define GROSS_RUNNING_SUM(var) ((uint64_t)var & 0x00000000FFFF0000) ++#define RUNNING_SUM(var) ((uint64_t)var & 0x000000000000FFFF) ++ ++/** ++ * Macros to get values in word8 ++ */ ++#define PARSE_ERROR_CODE(var) ((uint64_t)var & 0xFF00000000000000) ++#define SOFT_PARSING_CONTEXT(var) ((uint64_t)var & 0x00FFFFFFFFFFFFFF) ++ ++/* Debug frame, otherwise supposed to be discarded */ ++#define DPAA2_ETH_FAS_DISC 0x80000000 ++/* MACSEC frame */ ++#define DPAA2_ETH_FAS_MS 0x40000000 ++#define DPAA2_ETH_FAS_PTP 0x08000000 ++/* Ethernet multicast frame */ ++#define DPAA2_ETH_FAS_MC 0x04000000 ++/* Ethernet broadcast frame */ ++#define DPAA2_ETH_FAS_BC 0x02000000 ++#define DPAA2_ETH_FAS_KSE 0x00040000 ++#define DPAA2_ETH_FAS_EOFHE 0x00020000 ++#define DPAA2_ETH_FAS_MNLE 0x00010000 ++#define DPAA2_ETH_FAS_TIDE 0x00008000 ++#define DPAA2_ETH_FAS_PIEE 0x00004000 ++/* Frame length error */ ++#define DPAA2_ETH_FAS_FLE 0x00002000 ++/* Frame physical error; our favourite pastime */ ++#define DPAA2_ETH_FAS_FPE 0x00001000 ++#define DPAA2_ETH_FAS_PTE 0x00000080 ++#define DPAA2_ETH_FAS_ISP 0x00000040 ++#define DPAA2_ETH_FAS_PHE 0x00000020 ++#define DPAA2_ETH_FAS_BLE 0x00000010 ++/* L3 csum validation performed */ ++#define DPAA2_ETH_FAS_L3CV 0x00000008 ++/* L3 csum error */ ++#define DPAA2_ETH_FAS_L3CE 0x00000004 ++/* L4 csum validation performed */ ++#define DPAA2_ETH_FAS_L4CV 0x00000002 ++/* L4 csum error */ ++#define DPAA2_ETH_FAS_L4CE 0x00000001 ++ ++/* These bits always signal errors */ ++#define DPAA2_ETH_RX_ERR_MASK (DPAA2_ETH_FAS_KSE | \ ++ DPAA2_ETH_FAS_EOFHE | \ ++ DPAA2_ETH_FAS_MNLE | \ ++ DPAA2_ETH_FAS_TIDE | \ ++ DPAA2_ETH_FAS_PIEE | \ ++ DPAA2_ETH_FAS_FLE | \ ++ DPAA2_ETH_FAS_FPE | \ ++ DPAA2_ETH_FAS_PTE | \ ++ DPAA2_ETH_FAS_ISP | \ ++ DPAA2_ETH_FAS_PHE | \ ++ DPAA2_ETH_FAS_BLE | \ ++ DPAA2_ETH_FAS_L3CE | \ ++ DPAA2_ETH_FAS_L4CE) ++/* Unsupported features in the ingress */ ++#define DPAA2_ETH_RX_UNSUPP_MASK DPAA2_ETH_FAS_MS ++/* Tx errors */ ++#define DPAA2_ETH_TXCONF_ERR_MASK (DPAA2_ETH_FAS_KSE | \ ++ DPAA2_ETH_FAS_EOFHE | \ ++ DPAA2_ETH_FAS_MNLE | \ ++ DPAA2_ETH_FAS_TIDE) ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h +index 857dc3e..3dc9544 100644 +--- a/lib/librte_eal/common/eal_private.h ++++ b/lib/librte_eal/common/eal_private.h +@@ -325,4 +325,11 @@ int rte_eal_hugepage_init(void); + */ + int rte_eal_hugepage_attach(void); + ++#ifdef RTE_LIBRTE_DPAA2_PMD ++/** ++ * Initialize any soc init related functions if any before thread creation ++ */ ++int rte_eal_soc_pre_init(void); ++#endif ++ + #endif /* _EAL_PRIVATE_H_ */ +diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile +index 182729c..ed5be74 100644 +--- a/lib/librte_eal/linuxapp/eal/Makefile ++++ b/lib/librte_eal/linuxapp/eal/Makefile +@@ -76,6 +76,10 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_lcore.c + SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_timer.c + SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_interrupts.c + SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_alarm.c ++ifeq ($(CONFIG_RTE_LIBRTE_DPAA2_PMD),y) ++SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_soc.c ++SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_vfio_fsl_mc.c ++endif + ifeq ($(CONFIG_RTE_LIBRTE_IVSHMEM),y) + SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_ivshmem.c + endif +diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c +index 3fb2188..832c252 100644 +--- a/lib/librte_eal/linuxapp/eal/eal.c ++++ b/lib/librte_eal/linuxapp/eal/eal.c +@@ -814,6 +814,11 @@ rte_eal_init(int argc, char **argv) + if (rte_eal_tailqs_init() < 0) + rte_panic("Cannot init tail queues for objects\n"); + ++#ifdef RTE_LIBRTE_DPAA2_PMD ++ if (rte_eal_soc_pre_init() < 0) ++ rte_panic("Cannot pre init soc\n"); ++#endif ++ + #ifdef RTE_LIBRTE_IVSHMEM + if (rte_eal_ivshmem_obj_init() < 0) + rte_panic("Cannot init IVSHMEM objects\n"); +diff --git a/lib/librte_eal/linuxapp/eal/eal_soc.c b/lib/librte_eal/linuxapp/eal/eal_soc.c +new file mode 100644 +index 0000000..1595f68 +--- /dev/null ++++ b/lib/librte_eal/linuxapp/eal/eal_soc.c +@@ -0,0 +1,67 @@ ++/*- ++ * BSD LICENSE ++ * ++ * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * * Neither the name of Freescale Semiconductor, Inc or the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "eal_private.h" ++ ++#ifdef RTE_LIBRTE_DPAA2_PMD ++#include "eal_vfio_fsl_mc.h" ++#endif ++ ++#if (defined RTE_LIBRTE_DPAA_PMD) ++extern int usdpaa_pre_rte_eal_init(void); ++#endif ++ ++/* Initialize any soc init related functions if any before thread creation*/ ++int ++rte_eal_soc_pre_init(void) ++{ ++#ifdef RTE_LIBRTE_DPAA2_PMD ++ if (rte_eal_dpaa2_init() < 0) ++ RTE_LOG(WARNING, EAL, "Cannot init FSL_MC SCAN\n"); ++#endif ++#if (defined RTE_LIBRTE_DPAA_PMD) ++ if (usdpaa_pre_rte_eal_init()) ++ RTE_LOG(WARNING, EAL, "Cannot init FSL_DPAA \n"); ++#endif ++ return 0; ++} +diff --git a/lib/librte_eal/linuxapp/eal/eal_vfio_fsl_mc.c b/lib/librte_eal/linuxapp/eal/eal_vfio_fsl_mc.c +new file mode 100644 +index 0000000..0ddaef9 +--- /dev/null ++++ b/lib/librte_eal/linuxapp/eal/eal_vfio_fsl_mc.c +@@ -0,0 +1,650 @@ ++/*- ++ * BSD LICENSE ++ * ++ * Copyright (c) 2014 Freescale Semiconductor, Inc. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * * Neither the name of Freescale Semiconductor nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "rte_pci.h" ++#include "eal_vfio.h" ++ ++#include ++ ++#include "eal_vfio_fsl_mc.h" ++ ++#include "rte_pci_dev_ids.h" ++#include "eal_filesystem.h" ++#include "eal_private.h" ++ ++#ifndef VFIO_MAX_GROUPS ++#define VFIO_MAX_GROUPS 64 ++#endif ++ ++/* #define DPAA2_STAGE2_STASHING */ ++ ++/** Pathname of FSL-MC devices directory. */ ++#define SYSFS_FSL_MC_DEVICES "/sys/bus/fsl-mc/devices" ++ ++/* Number of VFIO containers & groups with in */ ++static struct fsl_vfio_group vfio_groups[VFIO_MAX_GRP]; ++static struct fsl_vfio_container vfio_containers[VFIO_MAX_CONTAINERS]; ++static char *ls2bus_container; ++static int container_device_fd; ++static uint32_t *msi_intr_vaddr; ++void *(*mcp_ptr_list); ++static uint32_t mcp_id; ++ ++static int vfio_connect_container(struct fsl_vfio_group *vfio_group) ++{ ++ struct fsl_vfio_container *container; ++ int i, fd, ret; ++ ++ /* Try connecting to vfio container already created */ ++ for (i = 0; i < VFIO_MAX_CONTAINERS; i++) { ++ container = &vfio_containers[i]; ++ if (!ioctl(vfio_group->fd, VFIO_GROUP_SET_CONTAINER, &container->fd)) { ++ RTE_LOG(ERR, EAL, "Container pre-exists with FD[0x%x]" ++ " for this group\n", container->fd); ++ vfio_group->container = container; ++ return 0; ++ } ++ } ++ ++ /* Opens main vfio file descriptor which represents the "container" */ ++ fd = open("/dev/vfio/vfio", O_RDWR); ++ if (fd < 0) { ++ RTE_LOG(ERR, EAL, "vfio: failed to open /dev/vfio/vfio\n"); ++ return -errno; ++ } ++ ++ ret = ioctl(fd, VFIO_GET_API_VERSION); ++ if (ret != VFIO_API_VERSION) { ++ RTE_LOG(ERR, EAL, "vfio: supported vfio version: %d, " ++ "reported version: %d", VFIO_API_VERSION, ret); ++ close(fd); ++ return -EINVAL; ++ } ++#ifndef DPAA2_STAGE2_STASHING ++ /* Check whether support for SMMU type IOMMU prresent or not */ ++ if (ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1_IOMMU)) { ++ /* Connect group to container */ ++ ret = ioctl(vfio_group->fd, VFIO_GROUP_SET_CONTAINER, &fd); ++ if (ret) { ++ RTE_LOG(ERR, EAL, "vfio: failed to set group container:\n"); ++ close(fd); ++ return -errno; ++ } ++ ++ ret = ioctl(fd, VFIO_SET_IOMMU, VFIO_TYPE1_IOMMU); ++ if (ret) { ++ RTE_LOG(ERR, EAL, "vfio: failed to set iommu for container:\n"); ++ close(fd); ++ return -errno; ++ } ++ } else { ++ RTE_LOG(ERR, EAL, "vfio error: No supported IOMMU\n"); ++ close(fd); ++ return -EINVAL; ++ } ++#else ++ /* Check whether support for SMMU type IOMMU stage 2 present or not */ ++ if (ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1_NESTING_IOMMU)) { ++ /* Connect group to container */ ++ ret = ioctl(vfio_group->fd, VFIO_GROUP_SET_CONTAINER, &fd); ++ if (ret) { ++ RTE_LOG(ERR, EAL, "vfio: failed to set group container:\n"); ++ close(fd); ++ return -errno; ++ } ++ ++ ret = ioctl(fd, VFIO_SET_IOMMU, VFIO_TYPE1_NESTING_IOMMU); ++ if (ret) { ++ RTE_LOG(ERR, EAL, "vfio: failed to set iommu-2 for container:\n"); ++ close(fd); ++ return -errno; ++ } ++ } else { ++ RTE_LOG(ERR, EAL, "vfio error: No supported IOMMU-2\n"); ++ close(fd); ++ return -EINVAL; ++ } ++#endif ++ container = NULL; ++ for (i = 0; i < VFIO_MAX_CONTAINERS; i++) { ++ if (vfio_containers[i].used) ++ continue; ++ RTE_LOG(ERR, EAL, "DPAA2-Unused container at index %d\n", i); ++ container = &vfio_containers[i]; ++ } ++ if (!container) { ++ RTE_LOG(ERR, EAL, "vfio error: No Free Container Found\n"); ++ close(fd); ++ return -ENOMEM; ++ } ++ ++ container->used = 1; ++ container->fd = fd; ++ container->group_list[container->index] = vfio_group; ++ vfio_group->container = container; ++ container->index++; ++ return 0; ++} ++ ++static int vfio_map_irq_region(struct fsl_vfio_group *group) ++{ ++ int ret; ++ unsigned long *vaddr = NULL; ++ struct vfio_iommu_type1_dma_map map = { ++ .argsz = sizeof(map), ++ .flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE, ++ .vaddr = 0x6030000, ++ .iova = 0x6030000, ++ .size = 0x1000, ++ }; ++ ++ vaddr = (unsigned long *)mmap(NULL, 0x1000, PROT_WRITE | ++ PROT_READ, MAP_SHARED, container_device_fd, 0x6030000); ++ if (vaddr == MAP_FAILED) { ++ RTE_LOG(ERR, EAL, " mapping GITS region (errno = %d)", errno); ++ return -errno; ++ } ++ ++ msi_intr_vaddr = (uint32_t *)((char *)(vaddr) + 64); ++ map.vaddr = (unsigned long)vaddr; ++ ret = ioctl(group->container->fd, VFIO_IOMMU_MAP_DMA, &map); ++ if (ret == 0) ++ return 0; ++ ++ RTE_LOG(ERR, EAL, "vfio_map_irq_region fails (errno = %d)", errno); ++ return -errno; ++} ++ ++int vfio_dmamap_mem_region(uint64_t vaddr, ++ uint64_t iova, ++ uint64_t size) ++{ ++ struct fsl_vfio_group *group; ++ struct vfio_iommu_type1_dma_map dma_map = { ++ .argsz = sizeof(dma_map), ++ .flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE, ++ }; ++ ++ dma_map.vaddr = vaddr; ++ dma_map.size = size; ++ dma_map.iova = iova; ++ ++ /* SET DMA MAP for IOMMU */ ++ group = &vfio_groups[0]; ++ if (ioctl(group->container->fd, VFIO_IOMMU_MAP_DMA, &dma_map)) { ++ RTE_LOG(ERR, EAL, "SWP: VFIO_IOMMU_MAP_DMA API Error %d.\n", errno); ++ return -1; ++ } ++ return 0; ++} ++ ++static int32_t setup_dmamap(void) ++{ ++ int ret; ++ struct fsl_vfio_group *group; ++ struct vfio_iommu_type1_dma_map dma_map = { ++ .argsz = sizeof(struct vfio_iommu_type1_dma_map), ++ .flags = VFIO_DMA_MAP_FLAG_READ | VFIO_DMA_MAP_FLAG_WRITE, ++ }; ++ ++ int i; ++ const struct rte_memseg *memseg; ++ ++ for (i = 0; i < RTE_MAX_MEMSEG; i++) { ++ memseg = rte_eal_get_physmem_layout(); ++ if (memseg == NULL) { ++ RTE_LOG(ERR, EAL, ++ "\nError Cannot get physical layout\n"); ++ return -ENODEV; ++ } ++ ++ if (memseg[i].addr == NULL && memseg[i].len == 0) { ++ break; ++ } ++ ++ dma_map.size = memseg[i].len; ++ dma_map.vaddr = memseg[i].addr_64; ++#ifdef RTE_LIBRTE_DPAA2_USE_PHYS_IOVA ++ dma_map.iova = memseg[i].phys_addr; ++#else ++ dma_map.iova = dma_map.vaddr; ++#endif ++ ++ /* SET DMA MAP for IOMMU */ ++ group = &vfio_groups[0]; ++ ++ printf("-->Initial SHM Virtual ADDR %llX\n", dma_map.vaddr); ++ printf("-----> DMA size 0x%llX\n", dma_map.size); ++ ret = ioctl(group->container->fd, VFIO_IOMMU_MAP_DMA, &dma_map); ++ if (ret) { ++ RTE_LOG(ERR, EAL, ++ "\nErr: VFIO_IOMMU_MAP_DMA API Error %d.\n", ++ errno); ++ return ret; ++ } ++ printf("-----> dma_map.vaddr = 0x%llX\n", dma_map.vaddr); ++ } ++ ++ /* TODO - This is a W.A. as VFIO currently does not add the mapping of ++ the interrupt region to SMMU. This should be removed once the ++ support is added in the Kernel. ++ */ ++ vfio_map_irq_region(group); ++ ++ return 0; ++} ++ ++static int vfio_set_group(struct fsl_vfio_group *group, int groupid) ++{ ++ char path[PATH_MAX]; ++ struct vfio_group_status status = { .argsz = sizeof(status) }; ++ ++ /* Open the VFIO file corresponding to the IOMMU group */ ++ snprintf(path, sizeof(path), "/dev/vfio/%d", groupid); ++ ++ group->fd = open(path, O_RDWR); ++ if (group->fd < 0) { ++ RTE_LOG(ERR, EAL, "vfio: error opening %s\n", path); ++ return -1; ++ } ++ ++ /* Test & Verify that group is VIABLE & AVAILABLE */ ++ if (ioctl(group->fd, VFIO_GROUP_GET_STATUS, &status)) { ++ RTE_LOG(ERR, EAL, "vfio: error getting group status\n"); ++ close(group->fd); ++ return -1; ++ } ++ if (!(status.flags & VFIO_GROUP_FLAGS_VIABLE)) { ++ RTE_LOG(ERR, EAL, "vfio: group not viable\n"); ++ close(group->fd); ++ return -1; ++ } ++ /* Since Group is VIABLE, Store the groupid */ ++ group->groupid = groupid; ++ ++ /* Now connect this IOMMU group to given container */ ++ if (vfio_connect_container(group)) { ++ RTE_LOG(ERR, EAL, ++ "vfio: error sonnecting container with group %d\n", ++ groupid); ++ close(group->fd); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int32_t setup_vfio_grp(char *vfio_container) ++{ ++ char path[PATH_MAX]; ++ char iommu_group_path[PATH_MAX], *group_name; ++ struct fsl_vfio_group *group = NULL; ++ struct stat st; ++ int groupid; ++ int ret, len, i; ++ ++ printf("\tProcessing Container = %s\n", vfio_container); ++ sprintf(path, "/sys/bus/fsl-mc/devices/%s", vfio_container); ++ /* Check whether ls-container exists or not */ ++ printf("\tcontainer device path = %s\n", path); ++ if (stat(path, &st) < 0) { ++ RTE_LOG(ERR, EAL, "vfio: Error (%d) getting FSL-MC device (%s)\n", ++ errno, path); ++ return -errno; ++ } ++ ++ /* DPRC container exists. NOw checkout the IOMMU Group */ ++ strncat(path, "/iommu_group", sizeof(path) - strlen(path) - 1); ++ ++ len = readlink(path, iommu_group_path, PATH_MAX); ++ if (len == -1) { ++ RTE_LOG(ERR, EAL, "\tvfio: error no iommu_group for device\n"); ++ RTE_LOG(ERR, EAL, "\t%s: len = %d, errno = %d\n", ++ path, len, errno); ++ return -errno; ++ } ++ ++ iommu_group_path[len] = 0; ++ group_name = basename(iommu_group_path); ++ if (sscanf(group_name, "%d", &groupid) != 1) { ++ RTE_LOG(ERR, EAL, "\tvfio: error reading %s: %m\n", path); ++ return -errno; ++ } ++ ++ RTE_LOG(INFO, EAL, "\tvfio: iommu group id = %d\n", groupid); ++ ++ /* Check if group already exists */ ++ for (i = 0; i < VFIO_MAX_GRP; i++) { ++ group = &vfio_groups[i]; ++ if (group->groupid == groupid) { ++ RTE_LOG(ERR, EAL, "groupid already exists %d\n", groupid); ++ return 0; ++ } ++ } ++ ++ if (vfio_set_group(group, groupid)) { ++ RTE_LOG(ERR, EAL, "group setup failure - %d\n", groupid); ++ return -ENODEV; ++ } ++ ++ /* Get Device information */ ++ ret = ioctl(group->fd, VFIO_GROUP_GET_DEVICE_FD, vfio_container); ++ if (ret < 0) { ++ RTE_LOG(ERR, EAL, "\tvfio: error getting device %s fd from group %d\n", ++ vfio_container, group->groupid); ++ return ret; ++ } ++ container_device_fd = ret; ++ RTE_LOG(INFO, EAL, "vfio: Container FD is [0x%X]\n", container_device_fd); ++ /* Set up SMMU */ ++ ret = setup_dmamap(); ++ if (ret) { ++ RTE_LOG(ERR, EAL, ": Setting dma map\n"); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int64_t vfio_map_mcp_obj(struct fsl_vfio_group *group, char *mcp_obj) ++{ ++ int64_t v_addr = (int64_t)MAP_FAILED; ++ int32_t ret, mc_fd; ++ ++ struct vfio_device_info d_info = { .argsz = sizeof(d_info) }; ++ struct vfio_region_info reg_info = { .argsz = sizeof(reg_info) }; ++ ++ /* getting the mcp object's fd*/ ++ mc_fd = ioctl(group->fd, VFIO_GROUP_GET_DEVICE_FD, mcp_obj); ++ if (mc_fd < 0) { ++ RTE_LOG(ERR, EAL, "vfio: error getting device %s fd from group %d\n", ++ mcp_obj, group->fd); ++ return v_addr; ++ } ++ ++ /* getting device info*/ ++ ret = ioctl(mc_fd, VFIO_DEVICE_GET_INFO, &d_info); ++ if (ret < 0) { ++ RTE_LOG(ERR, EAL, "vfio: error getting DEVICE_INFO\n"); ++ goto MC_FAILURE; ++ } ++ ++ /* getting device region info*/ ++ ret = ioctl(mc_fd, VFIO_DEVICE_GET_REGION_INFO, ®_info); ++ if (ret < 0) { ++ RTE_LOG(ERR, EAL, "vfio: error getting REGION_INFO\n"); ++ goto MC_FAILURE; ++ } ++ ++ RTE_LOG(INFO, EAL, "region offset = %llx , region size = %llx\n", ++ reg_info.offset, reg_info.size); ++ ++ v_addr = (uint64_t)mmap(NULL, reg_info.size, ++ PROT_WRITE | PROT_READ, MAP_SHARED, ++ mc_fd, reg_info.offset); ++ ++MC_FAILURE: ++ close(mc_fd); ++ ++ return v_addr; ++} ++ ++/* Following function shall fetch total available list of MC devices ++ * from VFIO container & populate private list of devices and other ++ * data structures ++ */ ++static int vfio_process_group_devices(void) ++{ ++ struct fsl_vfio_device *vdev; ++ struct vfio_device_info device_info = { .argsz = sizeof(device_info) }; ++ char *temp_obj, *object_type, *mcp_obj, *dev_name; ++ int32_t object_id, i, dev_fd, ret; ++ DIR *d; ++ struct dirent *dir; ++ char path[PATH_MAX]; ++ int64_t v_addr; ++ int ndev_count; ++ struct fsl_vfio_group *group = &vfio_groups[0]; ++ ++ sprintf(path, "/sys/kernel/iommu_groups/%d/devices", group->groupid); ++ ++ d = opendir(path); ++ if (!d) { ++ RTE_LOG(ERR, EAL, "Unable to open directory %s\n", path); ++ return -1; ++ } ++ ++ /*Counting the number of devices in a group and getting the mcp ID*/ ++ ndev_count = 0; ++ mcp_obj = NULL; ++ while ((dir = readdir(d)) != NULL) { ++ if (dir->d_type == DT_LNK) { ++ ndev_count++; ++ if (!strncmp("dpmcp", dir->d_name, 5)) { ++ if (mcp_obj) ++ free(mcp_obj); ++ mcp_obj = malloc(sizeof(dir->d_name)); ++ if (!mcp_obj) { ++ RTE_LOG(ERR, EAL, ++ "Unable to allocate memory\n"); ++ return -ENOMEM; ++ } ++ strcpy(mcp_obj, dir->d_name); ++ temp_obj = strtok(dir->d_name, "."); ++ temp_obj = strtok(NULL, "."); ++ sscanf(temp_obj, "%d", &mcp_id); ++ } ++ } ++ } ++ closedir(d); ++ ++ if (!mcp_obj) { ++ RTE_LOG(ERR, EAL, "MCP Object not Found\n"); ++ return -ENODEV; ++ } ++ RTE_LOG(INFO, EAL, "Total devices in conatiner = %d, MCP ID = %d\n", ++ ndev_count, mcp_id); ++ ++ /* Allocate the memory depends upon number of objects in a group*/ ++ group->vfio_device = (struct fsl_vfio_device *)malloc(ndev_count * sizeof(struct fsl_vfio_device)); ++ if (!(group->vfio_device)) { ++ RTE_LOG(ERR, EAL, "Unable to allocate memory\n"); ++ free(mcp_obj); ++ return -ENOMEM; ++ } ++ ++ /* Allocate memory for MC Portal list */ ++ mcp_ptr_list = malloc(sizeof(void *) * 1); ++ if (!mcp_ptr_list) { ++ RTE_LOG(ERR, EAL, "NO Memory!\n"); ++ free(mcp_obj); ++ goto FAILURE; ++ } ++ ++ v_addr = vfio_map_mcp_obj(group, mcp_obj); ++ free(mcp_obj); ++ if (v_addr == (int64_t)MAP_FAILED) { ++ RTE_LOG(ERR, EAL, "mapping region (errno = %d)\n", errno); ++ goto FAILURE; ++ } ++ ++ RTE_LOG(INFO, EAL, "MC has VIR_ADD = 0x%ld\n", v_addr); ++ ++ mcp_ptr_list[0] = (void *)v_addr; ++ ++ d = opendir(path); ++ if (!d) { ++ RTE_LOG(ERR, EAL, "Directory %s not able to open\n", path); ++ goto FAILURE; ++ } ++ ++ i = 0; ++ printf("\nDPAA2 - Parsing MC Device Objects:\n"); ++ /* Parsing each object and initiating them*/ ++ while ((dir = readdir(d)) != NULL) { ++ if (dir->d_type != DT_LNK) ++ continue; ++ if (!strncmp("dprc", dir->d_name, 4) || !strncmp("dpmcp", dir->d_name, 5)) ++ continue; ++ dev_name = malloc(sizeof(dir->d_name)); ++ if (!dev_name) { ++ RTE_LOG(ERR, EAL, "Unable to allocate memory\n"); ++ goto FAILURE; ++ } ++ strcpy(dev_name, dir->d_name); ++ object_type = strtok(dir->d_name, "."); ++ temp_obj = strtok(NULL, "."); ++ sscanf(temp_obj, "%d", &object_id); ++ RTE_LOG(INFO, EAL, "%s ", dev_name); ++ ++ /* getting the device fd*/ ++ dev_fd = ioctl(group->fd, VFIO_GROUP_GET_DEVICE_FD, dev_name); ++ if (dev_fd < 0) { ++ RTE_LOG(ERR, EAL, "vfio getting device %s fd from group %d\n", ++ dev_name, group->fd); ++ free(dev_name); ++ goto FAILURE; ++ } ++ ++ free(dev_name); ++ vdev = &group->vfio_device[group->object_index++]; ++ vdev->fd = dev_fd; ++ vdev->index = i; ++ i++; ++ /* Get Device inofrmation */ ++ if (ioctl(vdev->fd, VFIO_DEVICE_GET_INFO, &device_info)) { ++ RTE_LOG(ERR, EAL, "VFIO_DEVICE_FSL_MC_GET_INFO failed\n"); ++ goto FAILURE; ++ } ++ ++ if (!strcmp(object_type, "dpni") || ++ !strcmp(object_type, "dpseci")) { ++ struct rte_pci_device *dev; ++ ++ dev = malloc(sizeof(struct rte_pci_device)); ++ if (dev == NULL) { ++ return -1; ++ } ++ memset(dev, 0, sizeof(*dev)); ++ /* store hw_id of dpni/dpseci device */ ++ dev->addr.devid = object_id; ++ dev->id.vendor_id = FSL_VENDOR_ID; ++ dev->id.device_id = (strcmp(object_type, "dpseci")) ? ++ FSL_MC_DPNI_DEVID : FSL_MC_DPSECI_DEVID; ++ ++ TAILQ_INSERT_TAIL(&pci_device_list, dev, next); ++ } ++ ++ if (!strcmp(object_type, "dpio")) { ++ dpaa2_create_dpio_device(vdev, &device_info, object_id); ++ } ++ ++ if (!strcmp(object_type, "dpbp")) { ++ dpaa2_create_dpbp_device(object_id); ++ } ++ } ++ closedir(d); ++ ++ ret = dpaa2_affine_qbman_swp(); ++ if (ret) ++ RTE_LOG(ERR, EAL, "%s(): Err in affining qbman swp\n", __func__); ++ ++ return 0; ++ ++FAILURE: ++ free(group->vfio_device); ++ group->vfio_device = NULL; ++ return -1; ++} ++ ++/* ++ * Scan the content of the PCI bus, and the devices in the devices ++ * list ++ */ ++static int ++fsl_mc_scan(void) ++{ ++ char path[PATH_MAX]; ++ struct stat st; ++ ++ ls2bus_container = getenv("DPRC"); ++ ++ if (ls2bus_container == NULL) { ++ RTE_LOG(WARNING, EAL, "vfio container not set in env DPRC\n"); ++ return -1; ++ } ++ ++ snprintf(path, sizeof(path), "%s/%s", SYSFS_FSL_MC_DEVICES, ++ ls2bus_container); ++ /* Check whether LS-Container exists or not */ ++ RTE_LOG(INFO, EAL, "\tcontainer device path = %s\n", path); ++ if (stat(path, &st) < 0) { ++ RTE_LOG(ERR, EAL, "vfio:fsl-mc device does not exists\n"); ++ return -1; ++ } ++ return 0; ++} ++ ++/* Init the FSL-MC- LS2 EAL subsystem */ ++int ++rte_eal_dpaa2_init(void) ++{ ++ if (fsl_mc_scan() < 0) ++ return -1; ++ ++#ifdef VFIO_PRESENT ++ if (setup_vfio_grp(ls2bus_container)) { ++ RTE_LOG(ERR, EAL, "setup_vfio_grp\n"); ++ return -1; ++ } ++ if (vfio_process_group_devices()) { ++ RTE_LOG(ERR, EAL, "vfio_process_group_devices\n"); ++ return -1; ++ } ++#endif ++ return 0; ++} +diff --git a/lib/librte_eal/linuxapp/eal/eal_vfio_fsl_mc.h b/lib/librte_eal/linuxapp/eal/eal_vfio_fsl_mc.h +new file mode 100644 +index 0000000..cf2bd38 +--- /dev/null ++++ b/lib/librte_eal/linuxapp/eal/eal_vfio_fsl_mc.h +@@ -0,0 +1,98 @@ ++/*- ++ * BSD LICENSE ++ * ++ * Copyright (c) 2014 Freescale Semiconductor, Inc. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * * Neither the name of Freescale Semiconductor nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#ifndef _EAL_VFIO_FSL_MC_H_ ++#define _EAL_VFIO_FSL_MC_H_ ++ ++#include ++#include ++#include "eal_vfio.h" ++ ++#define FSL_VENDOR_ID 0x1957 ++#define FSL_MC_DPNI_DEVID 7 ++#define FSL_MC_DPSECI_DEVID 3 ++ ++#define VFIO_MAX_GRP 1 ++#define VFIO_MAX_CONTAINERS 1 ++ ++#define DPAA2_MBUF_HW_ANNOTATION 64 ++#define DPAA2_FD_PTA_SIZE 64 ++ ++#if (DPAA2_MBUF_HW_ANNOTATION + DPAA2_FD_PTA_SIZE) > RTE_PKTMBUF_HEADROOM ++#error "Annotation requirement is more than RTE_PKTMBUF_HEADROOM" ++#endif ++ ++/* we will re-use the HEADROOM for annotation in RX */ ++#define DPAA2_HW_BUF_RESERVE 0 ++#define DPAA2_PACKET_LAYOUT_ALIGN 64 /*changing from 256 */ ++ ++typedef struct fsl_vfio_device { ++ int fd; /* fsl_mc root container device ?? */ ++ int index; /*index of child object */ ++ struct fsl_vfio_device *child; /* Child object */ ++} fsl_vfio_device; ++ ++typedef struct fsl_vfio_group { ++ int fd; /* /dev/vfio/"groupid" */ ++ int groupid; ++ struct fsl_vfio_container *container; ++ int object_index; ++ struct fsl_vfio_device *vfio_device; ++} fsl_vfio_group; ++ ++typedef struct fsl_vfio_container { ++ int fd; /* /dev/vfio/vfio */ ++ int used; ++ int index; /* index in group list */ ++ struct fsl_vfio_group *group_list[VFIO_MAX_GRP]; ++} fsl_vfio_container; ++ ++int vfio_dmamap_mem_region( ++ uint64_t vaddr, ++ uint64_t iova, ++ uint64_t size); ++ ++/* initialize the NXP/FSL dpaa2 accelerators */ ++int rte_eal_dpaa2_init(void); ++ ++int dpaa2_create_dpio_device(struct fsl_vfio_device *vdev, ++ struct vfio_device_info *obj_info, ++ int object_id); ++ ++int dpaa2_create_dpbp_device(int dpbp_id); ++ ++int dpaa2_affine_qbman_swp(void); ++ ++int dpaa2_affine_qbman_swp_sec(void); ++ ++#endif ++ +diff --git a/lib/librte_mempool/rte_mempool.h b/lib/librte_mempool/rte_mempool.h +index 059ad9e..d620ad1 100644 +--- a/lib/librte_mempool/rte_mempool.h ++++ b/lib/librte_mempool/rte_mempool.h +@@ -262,6 +262,14 @@ struct rte_mempool { + #define MEMPOOL_F_POOL_CREATED 0x0010 /**< Internal: pool is created. */ + #define MEMPOOL_F_NO_PHYS_CONTIG 0x0020 /**< Don't need physically contiguous objs. */ + ++#ifdef RTE_LIBRTE_DPAA2_PMD ++/* TODO: This should be removed once mempool integration is complete. Primary ++ * reason for this is identification of DPAA1/2 memory pool for forwarding ++ * case ++ */ ++#define MEMPOOL_F_HW_PKT_POOL 0x0080 ++#endif ++ + /** + * @internal When debug is enabled, store some statistics. + * +diff --git a/mk/rte.app.mk b/mk/rte.app.mk +index eb28e11..11ae122 100644 +--- a/mk/rte.app.mk ++++ b/mk/rte.app.mk +@@ -101,6 +101,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE) += -lrte_cfgfile + + _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += -lrte_pmd_bond + _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += -lrte_pmd_xenvirt -lxenstore ++_LDLIBS-$(CONFIG_RTE_LIBRTE_DPAA2_PMD) += -lrte_pmd_dpaa2 + + ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),n) + # plugins (link only if static libraries) +-- +2.5.0 + -- cgit 1.2.3-korg From a9a951f8e5ed6e172fbfbdbb6cb690c67fa2f715 Mon Sep 17 00:00:00 2001 From: Damjan Marion Date: Mon, 16 Jan 2017 22:06:10 +0100 Subject: Add --without-libssl configure parameter This replaces --without-ipsec and --without-ipv6sr and allows other parts of the code to be disabled if libssl is not available. Change-Id: Id97ff3685a7924d7f86622952e0405d94ceb5957 Signed-off-by: Damjan Marion --- build-data/platforms/arm32.mk | 4 ++-- build-data/platforms/dpaa2.mk | 8 ++++---- build-data/platforms/qppc.mk | 4 ++-- build-data/platforms/thunder.mk | 4 ++-- src/configure.ac | 6 ++---- src/vnet.am | 6 +++--- src/vnet/ipsec/ipsec_api.c | 24 ++++++++++++------------ src/vnet/ipsec/ipsec_output.c | 2 +- src/vpp/api/api.c | 2 +- 9 files changed, 29 insertions(+), 31 deletions(-) (limited to 'build-data/platforms/dpaa2.mk') diff --git a/build-data/platforms/arm32.mk b/build-data/platforms/arm32.mk index 7b80061b..47d4ad5a 100644 --- a/build-data/platforms/arm32.mk +++ b/build-data/platforms/arm32.mk @@ -22,8 +22,8 @@ arm32_root_packages = vpp vlib vlib-api vnet svm vpp-api-test \ jvpp gmod vlib_configure_args_arm32 = --with-pre-data=128 -vnet_configure_args_arm32 = --with-dpdk --without-ipsec --without-ipv6sr -vpp_configure_args_arm32 = --with-dpdk --without-ipsec --without-ipv6sr +vnet_configure_args_arm32 = --with-dpdk --without-libssl +vpp_configure_args_arm32 = --with-dpdk --without-libssl arm32_dpdk_arch = "armv7a" arm32_dpdk_target = "arm-armv7a-linuxapp-gcc" diff --git a/build-data/platforms/dpaa2.mk b/build-data/platforms/dpaa2.mk index 0ec627a4..2d4745ac 100644 --- a/build-data/platforms/dpaa2.mk +++ b/build-data/platforms/dpaa2.mk @@ -42,10 +42,10 @@ dpaa2_dpdk_make_extra_args = "CROSS=$(dpaa2_target)- DPDK_PKTMBUF_HEADROOM=256" endif endif -vpp_configure_args_dpaa2 = --with-dpdk --without-ipsec \ - --without-ipv6sr --with-sysroot=$(SYSROOT) -vnet_configure_args_dpaa2 = --with-dpdk --without-ipsec \ - --without-ipv6sr --with-sysroot=$(SYSROOT) +vpp_configure_args_dpaa2 = --with-dpdk --without-libssl \ + --with-sysroot=$(SYSROOT) +vnet_configure_args_dpaa2 = --with-dpdk --without-libssl \ + --with-sysroot=$(SYSROOT) # Set these parameters carefully. The vlib_buffer_t is 256 bytes, i.e. vlib_configure_args_dpaa2 = --with-pre-data=256 diff --git a/build-data/platforms/qppc.mk b/build-data/platforms/qppc.mk index 244747e7..983684fc 100644 --- a/build-data/platforms/qppc.mk +++ b/build-data/platforms/qppc.mk @@ -11,10 +11,10 @@ qppc_root_packages = vppinfra vlib vlib-api vnet svm \ vpp vpp-api-test vnet_configure_args_qppc = \ - --without-ipsec --without-ipv6sr + --without-libssl vpp_configure_args_qppc = \ - --without-ipsec --without-ipv6sr + --without-libssl vlib_configure_args_qppc = --with-pre-data=128 diff --git a/build-data/platforms/thunder.mk b/build-data/platforms/thunder.mk index f891f4a1..31b6a510 100644 --- a/build-data/platforms/thunder.mk +++ b/build-data/platforms/thunder.mk @@ -15,10 +15,10 @@ thunder_root_packages = vppinfra vlib-cavium-dpdk vnet-cavium-dpdk cavium-dpdk \ vpp-cavium-dpdk vpp-api-test-cavium-dpdk vnet-cavium-dpdk_configure_args_thunder = \ - --with-dpdk --without-ipsec --without-ipv6sr + --with-dpdk --without-libssl vpp-cavium-dpdk_configure_args_thunder = \ - --with-dpdk --without-ipsec --without-ipv6sr + --with-dpdk --without-libssl cavium-dpdk_configure_args_thunder = --with-headroom=256 diff --git a/src/configure.ac b/src/configure.ac index eb380d8b..b2234448 100644 --- a/src/configure.ac +++ b/src/configure.ac @@ -101,8 +101,7 @@ WITH_ARG(dpdk_crypto, [Use DPDK cryptodev]) WITH_ARG(dpdk_mlx5_pmd, [Use DPDK with mlx5 PMD]) # --without-X -WITHOUT_ARG(ipsec, [Disable IPSec]) -WITHOUT_ARG(ipv6sr, [Disable IPv6 SR]) +WITHOUT_ARG(libssl, [Disable libssl]) WITHOUT_ARG(apicli, [Disable binary api CLI]) AC_ARG_WITH(unix, @@ -133,8 +132,7 @@ AC_SUBST(APICLI, [-DVPP_API_TEST_BUILTIN=${n_with_apicli}]) AC_DEFINE_UNQUOTED(DPDK, [${n_with_dpdk}]) AC_DEFINE_UNQUOTED(DPDK_SHARED_LIB, [${n_enable_dpdk_shared}]) AC_DEFINE_UNQUOTED(DPDK_CRYPTO, [${n_with_dpdk_crypto}]) -AC_DEFINE_UNQUOTED(IPSEC, [${n_with_ipsec}]) -AC_DEFINE_UNQUOTED(IPV6SR, [${n_with_ipv6sr}]) +AC_DEFINE_UNQUOTED(WITH_LIBSSL, [${n_with_libssl}]) # Silence following noise: diff --git a/src/vnet.am b/src/vnet.am index 3b2a25e8..93dd1e6c 100644 --- a/src/vnet.am +++ b/src/vnet.am @@ -26,7 +26,7 @@ libvnet_la_DEPENDENCIES = \ libvnet_la_LIBADD = $(libvnet_la_DEPENDENCIES) -lm -lpthread -ldl -lrt $(DPDK_LD_ADD) libvnet_la_LDFLAGS = $(DPDK_LD_FLAGS) -if WITH_IPV6SR +if WITH_LIBSSL libvnet_la_LIBADD += -lcrypto endif @@ -372,7 +372,7 @@ API_FILES += vnet/bfd/bfd.api ######################################## # Layer 3 protocol: IPSec ######################################## -if WITH_IPSEC +if WITH_LIBSSL libvnet_la_SOURCES += \ vnet/ipsec/ipsec.c \ vnet/ipsec/ipsec_cli.c \ @@ -673,7 +673,7 @@ nobase_include_HEADERS += \ # ipv6 segment routing ######################################## -if WITH_IPV6SR +if WITH_LIBSSL libvnet_la_SOURCES += \ vnet/sr/sr.c \ vnet/sr/sr_replicate.c \ diff --git a/src/vnet/ipsec/ipsec_api.c b/src/vnet/ipsec/ipsec_api.c index 30cc5bd2..9bcf63b4 100644 --- a/src/vnet/ipsec/ipsec_api.c +++ b/src/vnet/ipsec/ipsec_api.c @@ -26,7 +26,7 @@ #include -#if IPSEC > 0 +#if WITH_LIBSSL > 0 #include #include #endif /* IPSEC */ @@ -63,7 +63,7 @@ _(IKEV2_SET_LOCAL_KEY, ikev2_set_local_key) static void vl_api_ipsec_spd_add_del_t_handler (vl_api_ipsec_spd_add_del_t * mp) { -#if IPSEC == 0 +#if WITH_LIBSSL == 0 clib_warning ("unimplemented"); #else @@ -95,7 +95,7 @@ static void vl_api_ipsec_interface_add_del_spd_t_handler VALIDATE_SW_IF_INDEX (mp); -#if IPSEC > 0 +#if WITH_LIBSSL > 0 rv = ipsec_set_interface_spd (vm, sw_if_index, spd_id, mp->is_add); #else rv = VNET_API_ERROR_UNIMPLEMENTED; @@ -113,7 +113,7 @@ static void vl_api_ipsec_spd_add_del_entry_t_handler vl_api_ipsec_spd_add_del_entry_reply_t *rmp; int rv; -#if IPSEC > 0 +#if WITH_LIBSSL > 0 ipsec_policy_t p; memset (&p, 0, sizeof (p)); @@ -176,7 +176,7 @@ static void vl_api_ipsec_sad_add_del_entry_t_handler vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main (); vl_api_ipsec_sad_add_del_entry_reply_t *rmp; int rv; -#if IPSEC > 0 +#if WITH_LIBSSL > 0 ipsec_sa_t sa; memset (&sa, 0, sizeof (sa)); @@ -324,7 +324,7 @@ vl_api_ipsec_spd_dump_t_handler (vl_api_ipsec_spd_dump_t * mp) ipsec_spd_t *spd; uword *p; u32 spd_index; -#if IPSEC > 0 +#if WITH_LIBSSL > 0 q = vl_api_client_index_to_input_queue (mp->client_index); if (q == 0) return; @@ -355,7 +355,7 @@ vl_api_ipsec_sa_set_key_t_handler (vl_api_ipsec_sa_set_key_t * mp) vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main (); vl_api_ipsec_sa_set_key_reply_t *rmp; int rv; -#if IPSEC > 0 +#if WITH_LIBSSL > 0 ipsec_sa_t sa; sa.id = ntohl (mp->sa_id); sa.crypto_key_len = mp->crypto_key_length; @@ -377,7 +377,7 @@ vl_api_ikev2_profile_add_del_t_handler (vl_api_ikev2_profile_add_del_t * mp) vl_api_ikev2_profile_add_del_reply_t *rmp; int rv = 0; -#if IPSEC > 0 +#if WITH_LIBSSL > 0 vlib_main_t *vm = vlib_get_main (); clib_error_t *error; u8 *tmp = format (0, "%s", mp->name); @@ -399,7 +399,7 @@ static void vl_api_ikev2_profile_set_auth_reply_t *rmp; int rv = 0; -#if IPSEC > 0 +#if WITH_LIBSSL > 0 vlib_main_t *vm = vlib_get_main (); clib_error_t *error; u8 *tmp = format (0, "%s", mp->name); @@ -423,7 +423,7 @@ vl_api_ikev2_profile_set_id_t_handler (vl_api_ikev2_profile_set_id_t * mp) vl_api_ikev2_profile_add_del_reply_t *rmp; int rv = 0; -#if IPSEC > 0 +#if WITH_LIBSSL > 0 vlib_main_t *vm = vlib_get_main (); clib_error_t *error; u8 *tmp = format (0, "%s", mp->name); @@ -447,7 +447,7 @@ vl_api_ikev2_profile_set_ts_t_handler (vl_api_ikev2_profile_set_ts_t * mp) vl_api_ikev2_profile_set_ts_reply_t *rmp; int rv = 0; -#if IPSEC > 0 +#if WITH_LIBSSL > 0 vlib_main_t *vm = vlib_get_main (); clib_error_t *error; u8 *tmp = format (0, "%s", mp->name); @@ -470,7 +470,7 @@ vl_api_ikev2_set_local_key_t_handler (vl_api_ikev2_set_local_key_t * mp) vl_api_ikev2_profile_set_ts_reply_t *rmp; int rv = 0; -#if IPSEC > 0 +#if WITH_LIBSSL > 0 vlib_main_t *vm = vlib_get_main (); clib_error_t *error; diff --git a/src/vnet/ipsec/ipsec_output.c b/src/vnet/ipsec/ipsec_output.c index 97977899..df93b5e4 100644 --- a/src/vnet/ipsec/ipsec_output.c +++ b/src/vnet/ipsec/ipsec_output.c @@ -27,7 +27,7 @@ #define ESP_NODE "esp-encrypt" #endif -#if IPSEC > 0 +#if WITH_LIBSSL > 0 #define foreach_ipsec_output_next \ _(DROP, "error-drop") \ diff --git a/src/vpp/api/api.c b/src/vpp/api/api.c index 3d6905dd..3afc3383 100644 --- a/src/vpp/api/api.c +++ b/src/vpp/api/api.c @@ -54,7 +54,7 @@ #include #include #include -#if IPV6SR > 0 +#if WITH_LIBSSL > 0 #include #endif #include -- cgit 1.2.3-korg