aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.clang-format1
-rw-r--r--.gitignore1
-rw-r--r--MAINTAINERS7
-rw-r--r--Makefile32
-rw-r--r--build/external/packages/dpdk.mk16
-rw-r--r--build/external/packages/octeon-roc.mk4
-rw-r--r--docs/aboutvpp/releasenotes/index.rst2
-rw-r--r--docs/aboutvpp/releasenotes/past.rst2
l---------docs/developer/corefeatures/sr/sr_mpls.rst2
-rw-r--r--docs/gettingstarted/progressivevpp/index.rst2
-rw-r--r--docs/gettingstarted/progressivevpp/settingupenvironment.rst21
-rw-r--r--docs/spelling_wordlist.txt1
-rw-r--r--extras/hs-test/Makefile44
-rw-r--r--extras/hs-test/container.go16
-rw-r--r--extras/hs-test/cpu.go30
-rw-r--r--extras/hs-test/docker/Dockerfile.vpp2
-rw-r--r--extras/hs-test/echo_test.go4
-rw-r--r--extras/hs-test/framework_test.go9
-rw-r--r--extras/hs-test/go.mod2
-rw-r--r--extras/hs-test/hst_suite.go86
-rw-r--r--extras/hs-test/http_test.go122
-rw-r--r--extras/hs-test/mirroring_test.go5
-rw-r--r--extras/hs-test/raw_session_test.go5
-rwxr-xr-xextras/hs-test/script/build_hst.sh4
-rw-r--r--extras/hs-test/script/compress.sh33
-rw-r--r--extras/hs-test/suite_nginx_test.go17
-rw-r--r--extras/hs-test/suite_no_topo_test.go16
-rw-r--r--extras/hs-test/suite_ns_test.go16
-rw-r--r--extras/hs-test/suite_tap_test.go12
-rw-r--r--extras/hs-test/suite_veth_test.go19
-rw-r--r--[-rwxr-xr-x]extras/hs-test/test7
-rw-r--r--extras/hs-test/utils.go16
-rw-r--r--extras/hs-test/vppinstance.go150
-rw-r--r--src/cmake/platform/octeon9.cmake4
-rw-r--r--src/plugins/acl/acl_test.c35
-rw-r--r--src/plugins/builtinurl/builtinurl.api1
-rw-r--r--src/plugins/dev_iavf/port.c43
-rw-r--r--src/plugins/dev_octeon/CMakeLists.txt6
-rw-r--r--src/plugins/dev_octeon/init.c4
-rw-r--r--src/plugins/dev_octeon/octeon.h4
-rw-r--r--src/plugins/dev_octeon/port.c44
-rw-r--r--src/plugins/dev_octeon/roc_helper.c7
-rw-r--r--src/plugins/dev_octeon/rx_node.c33
-rw-r--r--src/plugins/dev_octeon/tx_node.c82
-rw-r--r--src/plugins/dpdk/device/cli.c9
-rw-r--r--src/plugins/dpdk/device/init.c12
-rw-r--r--src/plugins/hs_apps/http_cli.c7
-rw-r--r--src/plugins/hs_apps/http_client_cli.c24
-rw-r--r--src/plugins/http/http.c67
-rw-r--r--src/plugins/http/http.h68
-rw-r--r--src/plugins/http_static/static_server.c11
-rw-r--r--src/plugins/ikev2/ikev2_api.c14
-rw-r--r--src/plugins/ikev2/ikev2_test.c12
-rw-r--r--src/plugins/marvell/pp2/cli.c2
-rw-r--r--src/plugins/nat/nat44-ed/nat44_ed_api.c3
-rw-r--r--src/plugins/nat/nat44-ei/nat44_ei_api.c3
-rw-r--r--src/plugins/nat/nat44-ei/nat44_ei_in2out.c2
-rw-r--r--src/plugins/nat/pnat/pnat_api.c5
-rw-r--r--src/plugins/netmap/CMakeLists.txt32
-rw-r--r--src/plugins/netmap/FEATURE.yaml (renamed from extras/deprecated/netmap/FEATURE.yaml)6
-rw-r--r--src/plugins/netmap/cli.c (renamed from extras/deprecated/netmap/cli.c)4
-rw-r--r--src/plugins/netmap/device.c (renamed from extras/deprecated/netmap/device.c)4
-rw-r--r--src/plugins/netmap/net_netmap.h (renamed from extras/deprecated/netmap/net_netmap.h)6
-rw-r--r--src/plugins/netmap/netmap.api (renamed from extras/deprecated/netmap/netmap.api)0
-rw-r--r--src/plugins/netmap/netmap.c (renamed from extras/deprecated/netmap/netmap.c)93
-rw-r--r--src/plugins/netmap/netmap.h (renamed from extras/deprecated/netmap/netmap.h)0
-rw-r--r--src/plugins/netmap/netmap_api.c (renamed from extras/deprecated/netmap/netmap_api.c)54
-rw-r--r--src/plugins/netmap/node.c (renamed from extras/deprecated/netmap/node.c)20
-rw-r--r--src/plugins/netmap/plugin.c16
-rw-r--r--src/plugins/srmpls/CMakeLists.txt30
-rw-r--r--src/plugins/srmpls/FEATURE.yaml (renamed from src/vnet/srmpls/FEATURE.yaml)0
-rw-r--r--src/plugins/srmpls/dir.dox (renamed from src/vnet/srmpls/dir.dox)0
-rw-r--r--src/plugins/srmpls/plugin.c (renamed from extras/deprecated/netmap/dir.dox)21
-rw-r--r--src/plugins/srmpls/sr_doc.rst (renamed from src/vnet/srmpls/sr_doc.rst)0
-rw-r--r--src/plugins/srmpls/sr_mpls.api (renamed from src/vnet/srmpls/sr_mpls.api)0
-rw-r--r--src/plugins/srmpls/sr_mpls.h (renamed from src/vnet/srmpls/sr_mpls.h)0
-rw-r--r--src/plugins/srmpls/sr_mpls_api.c (renamed from src/vnet/srmpls/sr_mpls_api.c)17
-rw-r--r--src/plugins/srmpls/sr_mpls_policy.c (renamed from src/vnet/srmpls/sr_mpls_policy.c)2
-rw-r--r--src/plugins/srmpls/sr_mpls_steering.c (renamed from src/vnet/srmpls/sr_mpls_steering.c)2
-rw-r--r--src/plugins/srmpls/sr_mpls_test.c (renamed from src/vnet/srmpls/sr_mpls_test.c)8
-rw-r--r--src/plugins/unittest/policer_test.c2
-rw-r--r--src/plugins/urpf/CMakeLists.txt4
-rw-r--r--src/plugins/urpf/urpf.c27
-rw-r--r--src/plugins/urpf/urpf.h14
-rw-r--r--src/plugins/urpf/urpf_dp.h335
-rw-r--r--src/plugins/wireguard/wireguard_chachapoly.c8
-rw-r--r--src/plugins/wireguard/wireguard_noise.c4
-rwxr-xr-xsrc/tools/vppapigen/vppapigen_c.py76
-rw-r--r--src/vat2/vat2_helpers.h2
-rw-r--r--src/vlib/CMakeLists.txt6
-rw-r--r--src/vlib/linux/pci.c15
-rw-r--r--src/vlib/pci/pci.c8
-rw-r--r--src/vlib/threads.c92
-rw-r--r--src/vlib/threads.h5
-rw-r--r--src/vlib/unix/main.c114
-rw-r--r--src/vlib/unix/plugin.c4
-rw-r--r--src/vlibapi/api_common.h4
-rw-r--r--src/vlibapi/api_helper_macros.h4
-rw-r--r--src/vlibapi/api_shared.c4
-rw-r--r--src/vlibmemory/memclnt_api.c1
-rw-r--r--src/vlibmemory/memory_api.c4
-rw-r--r--src/vlibmemory/vlib_api_cli.c6
-rw-r--r--src/vnet/CMakeLists.txt20
-rw-r--r--src/vnet/dev/format.c2
-rw-r--r--src/vnet/devices/virtio/node.c10
-rw-r--r--src/vnet/devices/virtio/virtio_inline.h1
-rw-r--r--src/vnet/ethernet/node.c36
-rw-r--r--src/vnet/ip-neighbor/ip_neighbor.c32
-rw-r--r--src/vnet/ip-neighbor/ip_neighbor_types.c15
-rw-r--r--src/vnet/ip/icmp6.c2
-rw-r--r--src/vnet/session/session_lookup.c1
-rw-r--r--src/vnet/udp/udp.c35
-rw-r--r--src/vnet/udp/udp_inlines.h4
-rw-r--r--src/vpp/vnet/main.c4
-rw-r--r--src/vppinfra/CMakeLists.txt45
-rw-r--r--src/vppinfra/asm_mips.h351
-rw-r--r--src/vppinfra/asm_x86.c1947
-rw-r--r--src/vppinfra/asm_x86.h125
-rw-r--r--src/vppinfra/backtrace.c260
-rw-r--r--src/vppinfra/cJSON.c185
-rw-r--r--src/vppinfra/cJSON.h23
-rw-r--r--src/vppinfra/clib.h4
-rw-r--r--src/vppinfra/format_ansi.h48
-rw-r--r--src/vppinfra/heap.c1
-rw-r--r--src/vppinfra/mem_dlmalloc.c25
-rw-r--r--src/vppinfra/mhash.c52
-rw-r--r--src/vppinfra/mhash.h5
-rw-r--r--src/vppinfra/stack.c75
-rw-r--r--src/vppinfra/stack.h26
-rw-r--r--src/vppinfra/test_mhash.c403
-rw-r--r--src/vppinfra/unix-misc.c48
-rw-r--r--src/vppinfra/unix.h3
-rw-r--r--test/Makefile15
-rwxr-xr-xtest/scripts/core_pinning.sh328
-rw-r--r--test/test_abf.py8
-rw-r--r--test/test_flowprobe.py2
-rw-r--r--test/test_gso.py36
-rw-r--r--test/test_gtpu.py4
-rw-r--r--test/test_ip6.py2
-rw-r--r--test/test_ip6_nd_mirror_proxy.py2
-rw-r--r--test/test_ipip.py6
-rw-r--r--test/test_l3xc.py2
-rw-r--r--test/test_linux_cp.py2
-rw-r--r--test/test_map.py2
-rw-r--r--test/test_map_br.py4
-rw-r--r--test/test_mpls.py2
-rw-r--r--test/test_nat44_ed_output.py2
-rw-r--r--test/test_neighbor.py1
-rw-r--r--test/test_pcap.py2
-rw-r--r--test/test_reassembly.py24
-rw-r--r--test/test_srv6_mobile.py8
-rw-r--r--test/test_trace_filter.py2
-rw-r--r--test/test_vxlan.py1
153 files changed, 2540 insertions, 3965 deletions
diff --git a/.clang-format b/.clang-format
index 617c5db417f..798a8c39a35 100644
--- a/.clang-format
+++ b/.clang-format
@@ -27,6 +27,7 @@ ForEachMacros:
- 'foreach_vlib_frame_bitmap_set_bit_index'
- 'FOREACH_ARRAY_ELT'
- 'RTE_ETH_FOREACH_DEV'
+ - 'foreach_clib_stack_frame'
- 'foreach_vnet_dev_rx_queue_runtime'
- 'foreach_vnet_dev_counter'
- 'foreach_vnet_dev_port_rx_queue'
diff --git a/.gitignore b/.gitignore
index 5c707a8364a..5537f0dd791 100644
--- a/.gitignore
+++ b/.gitignore
@@ -123,6 +123,7 @@ compile_commands.json
/extras/hs-test/hs-test
/extras/hs-test/http_server
/extras/hs-test/.build.ok
+/extras/hs-test/summary/
# ./configure
/CMakeFiles
diff --git a/MAINTAINERS b/MAINTAINERS
index c310e728227..fd456c04a6c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -192,7 +192,7 @@ I: sr
M: Pablo Camarillo <pcamaril@cisco.com>
M: Ahmed Abdelsalam <ahabdels@cisco.com>
F: src/vnet/srv6/
-F: src/vnet/srmpls/
+F: src/plugin/srmpls/
F: src/examples/srv6-sample-localsid/
VNET IPSec
@@ -892,3 +892,8 @@ M: vpp-dev Mailing List <vpp-dev@fd.io>
C: Missing Maintainer
F: *
F: */
+
+Netmap
+I: netmap
+M: Tom Jones <thj@freebsd.org>
+F: src/plugins/netmap/
diff --git a/Makefile b/Makefile
index edd632e42d5..1ab387e94d4 100644
--- a/Makefile
+++ b/Makefile
@@ -72,7 +72,7 @@ DEB_DEPENDS += debhelper dkms git libtool libapr1-dev dh-python
DEB_DEPENDS += libconfuse-dev git-review exuberant-ctags cscope pkg-config
DEB_DEPENDS += gcovr lcov chrpath autoconf libnuma-dev
DEB_DEPENDS += python3-all python3-setuptools check
-DEB_DEPENDS += libffi-dev python3-ply
+DEB_DEPENDS += libffi-dev python3-ply libunwind-dev
DEB_DEPENDS += cmake ninja-build python3-jsonschema python3-yaml
DEB_DEPENDS += python3-venv # ensurepip
DEB_DEPENDS += python3-dev python3-pip
@@ -86,6 +86,7 @@ DEB_DEPENDS += nasm
DEB_DEPENDS += iperf ethtool # for 'make test TEST=vm_vpp_interfaces'
DEB_DEPENDS += libpcap-dev
DEB_DEPENDS += tshark
+DEB_DEPENDS += jq # for extracting test summary from .json report (hs-test)
LIBFFI=libffi6 # works on all but 20.04 and debian-testing
@@ -244,6 +245,7 @@ help:
@echo " build - build debug binaries"
@echo " build-release - build release binaries"
@echo " build-coverity - build coverity artifacts"
+ @echo " build-vpp-gcov - build gcov vpp only"
@echo " rebuild - wipe and build debug binaries"
@echo " rebuild-release - wipe and build release binaries"
@echo " run - run debug binary"
@@ -251,6 +253,8 @@ help:
@echo " debug - run debug binary with debugger"
@echo " debug-release - run release binary with debugger"
@echo " test - build and run tests"
+ @echo " test-cov-hs - build and run host stack tests with coverage"
+ @echo " test-cov-both - build and run python and host stack tests, merge coverage data"
@echo " test-help - show help on test framework"
@echo " run-vat - run vpp-api-test tool"
@echo " pkg-deb - build DEB packages"
@@ -439,6 +443,10 @@ rebuild: wipe build
build-release: $(BR)/.deps.ok
$(call make,$(PLATFORM),$(addsuffix -install,$(TARGETS)))
+.PHONY: build-vpp-gcov
+build-vpp-gcov:
+ $(call test,vpp_gcov)
+
.PHONY: wipe-release
wipe-release: test-wipe $(BR)/.deps.ok
$(call make,$(PLATFORM),$(addsuffix -wipe,$(TARGETS)))
@@ -485,6 +493,20 @@ test-cov:
$(eval TEST_GCOV=1)
$(call test,vpp_gcov,cov)
+.PHONY: test-cov-hs
+test-cov-hs:
+ @make -C extras/hs-test build-cov
+ @make -C extras/hs-test test-cov
+
+.PHONY: test-cov-both
+test-cov-both:
+ @echo "Running Python, Golang tests and merging coverage reports."
+ find $(BR) -name '*.gcda' -delete
+ @make test-cov
+ find $(BR) -name '*.gcda' -delete
+ @make test-cov-hs
+ @make cov-merge
+
.PHONY: test-cov-build
test-cov-build:
$(eval CC=gcc)
@@ -501,6 +523,14 @@ test-cov-post:
$(eval CC=gcc)
$(call test,vpp_gcov,cov-post)
+.PHONY: cov-merge
+cov-merge:
+ @lcov --add-tracefile $(BR)/test-coverage-merged/coverage-filtered.info \
+ -a $(BR)/test-coverage-merged/coverage-filtered1.info -o $(BR)/test-coverage-merged/coverage-merged.info
+ @genhtml $(BR)/test-coverage-merged/coverage-merged.info \
+ --output-directory $(BR)/test-coverage-merged/html
+ @echo "Code coverage report is in $(BR)/test-coverage-merged/html/index.html"
+
.PHONY: test-all
test-all:
$(eval EXTENDED_TESTS=1)
diff --git a/build/external/packages/dpdk.mk b/build/external/packages/dpdk.mk
index e0a3ef2559b..c03d1a14703 100644
--- a/build/external/packages/dpdk.mk
+++ b/build/external/packages/dpdk.mk
@@ -33,8 +33,11 @@ dpdk_tarball_md5sum_21.11 := 58660bbbe9e95abce86e47692b196555
dpdk_tarball_md5sum := $(dpdk_tarball_md5sum_$(dpdk_version))
dpdk_url := $(dpdk_base_url)/$(dpdk_tarball)
dpdk_tarball_strip_dirs := 1
+ifeq ($(shell uname), FreeBSD)
+dpdk_depends := $(if $(ARCH_X86_64), ipsec-mb)
+else
dpdk_depends := rdma-core $(if $(ARCH_X86_64), ipsec-mb)
-
+endif
DPDK_MLX_DEFAULT := $(shell if grep -q "rdma=$(rdma-core_version) dpdk=$(dpdk_version)" mlx_rdma_dpdk_matrix.txt; then echo 'y'; else echo 'n'; fi)
DPDK_MLX4_PMD ?= $(DPDK_MLX_DEFAULT)
DPDK_MLX5_PMD ?= $(DPDK_MLX_DEFAULT)
@@ -134,14 +137,19 @@ endif
DPDK_DRIVERS_DISABLED := $(shell echo $(DPDK_DRIVERS_DISABLED) | tr -d '\\\t ')
DPDK_LIBS_DISABLED := $(shell echo $(DPDK_LIBS_DISABLED) | tr -d '\\\t ')
+SED=sed
+ifeq ($shell(uname), FreeBSD)
+SED=gsed
+endif
+
HASH := \#
# post-meson-setup snippet to alter rte_build_config.h
define dpdk_config
if grep -q RTE_$(1) $(dpdk_src_dir)/config/rte_config.h ; then \
-sed -i -e 's/$(HASH)define RTE_$(1).*/$(HASH)define RTE_$(1) $(DPDK_$(1))/' \
+$(SED) -i -e 's/$(HASH)define RTE_$(1).*/$(HASH)define RTE_$(1) $(DPDK_$(1))/' \
$(dpdk_src_dir)/config/rte_config.h; \
elif grep -q RTE_$(1) $(dpdk_build_dir)/rte_build_config.h ; then \
-sed -i -e 's/$(HASH)define RTE_$(1).*/$(HASH)define RTE_$(1) $(DPDK_$(1))/' \
+$(SED) -i -e 's/$(HASH)define RTE_$(1).*/$(HASH)define RTE_$(1) $(DPDK_$(1))/' \
$(dpdk_build_dir)/rte_build_config.h; \
else \
echo '$(HASH)define RTE_$(1) $(DPDK_$(1))' \
@@ -157,7 +165,7 @@ if [[ "$(DPDK_$(1))" == "y" ]]; then \
>> $(dpdk_build_dir)/rte_build_config.h ; \
fi; \
elif [[ "$(DPDK_$(1))" == "n" ]]; then \
- sed -i '/$(HASH)define RTE_$(1) .*/d' $(dpdk_build_dir)/rte_build_config.h \
+ $(SED) -i '/$(HASH)define RTE_$(1) .*/d' $(dpdk_build_dir)/rte_build_config.h \
$(dpdk_src_dir)/config/rte_config.h ; \
fi
endef
diff --git a/build/external/packages/octeon-roc.mk b/build/external/packages/octeon-roc.mk
index 62f5d823bdf..f96cd4c6e3d 100644
--- a/build/external/packages/octeon-roc.mk
+++ b/build/external/packages/octeon-roc.mk
@@ -2,9 +2,9 @@
# SPDX-License-Identifier: Apache-2.0
# https://spdx.org/licenses/Apache-2.0.html
-octeon-roc_version := 0.3
+octeon-roc_version := 0.4
octeon-roc_tarball := octeon-roc-v$(octeon-roc_version).tar.gz
-octeon-roc_tarball_md5sum := e4a16beb76a6c63af1600dd4d1d752b8
+octeon-roc_tarball_md5sum := f3772f6e05d71cf2709c00ff1a1929ca
octeon-roc_tarball_strip_dirs := 1
octeon-roc_url := https://github.com/MarvellEmbeddedProcessors/marvell-vpp/archive/refs/tags/$(octeon-roc_tarball)
diff --git a/docs/aboutvpp/releasenotes/index.rst b/docs/aboutvpp/releasenotes/index.rst
index adbe8401d27..6fda5152a58 100644
--- a/docs/aboutvpp/releasenotes/index.rst
+++ b/docs/aboutvpp/releasenotes/index.rst
@@ -9,6 +9,4 @@ Release notes
v24.02
v23.10
v23.06
- v23.02
- v22.10.1
past
diff --git a/docs/aboutvpp/releasenotes/past.rst b/docs/aboutvpp/releasenotes/past.rst
index 87285828eef..8f15bd4da3e 100644
--- a/docs/aboutvpp/releasenotes/past.rst
+++ b/docs/aboutvpp/releasenotes/past.rst
@@ -6,6 +6,8 @@ Past releases
.. toctree::
:maxdepth: 1
+ v23.02
+ v22.10.1
v22.10
v22.06.1
v22.06
diff --git a/docs/developer/corefeatures/sr/sr_mpls.rst b/docs/developer/corefeatures/sr/sr_mpls.rst
index d2fe4025326..9e676db4f07 120000
--- a/docs/developer/corefeatures/sr/sr_mpls.rst
+++ b/docs/developer/corefeatures/sr/sr_mpls.rst
@@ -1 +1 @@
-../../../../src/vnet/srmpls/sr_doc.rst \ No newline at end of file
+../../../../src/plugins/srmpls/sr_doc.rst \ No newline at end of file
diff --git a/docs/gettingstarted/progressivevpp/index.rst b/docs/gettingstarted/progressivevpp/index.rst
index 7d1a2e2b237..efe31b12db5 100644
--- a/docs/gettingstarted/progressivevpp/index.rst
+++ b/docs/gettingstarted/progressivevpp/index.rst
@@ -6,7 +6,7 @@
Progressive VPP Tutorial
########################
-Learn to run FD.io VPP on a single Ubuntu 16.04 VM using Vagrant with this walkthrough
+Learn to run FD.io VPP on a single Ubuntu VM using Vagrant with this walkthrough
covering basic FD.io VPP scenarios. Useful FD.io VPP commands will be used, and
will discuss basic operations, and the state of a running FD.io VPP on a system.
diff --git a/docs/gettingstarted/progressivevpp/settingupenvironment.rst b/docs/gettingstarted/progressivevpp/settingupenvironment.rst
index 8c67c79b188..a8fe16aa4ce 100644
--- a/docs/gettingstarted/progressivevpp/settingupenvironment.rst
+++ b/docs/gettingstarted/progressivevpp/settingupenvironment.rst
@@ -3,15 +3,15 @@
Setting up your environment
===========================
-All of these exercises are designed to be performed on an Ubuntu 16.04 (Xenial) box.
+All of these exercises are designed to be performed on an Ubuntu 22.04 (Jammy) box.
-* If you have an Ubuntu 18.04 box on which you have sudo or root access, you can feel free to use that.
-* If you do not, a Vagrantfile is provided to setup a basic Ubuntu 18.04 box for you in the the steps below.
+* If you have an Ubuntu 22.04 box on which you have sudo or root access, you can feel free to use that.
+* If you do not, a Vagrantfile is provided to setup a basic Ubuntu 22.04 box for you in the the steps below.
-Install Virtual Box and Vagrant
+Install Libvirt and Vagrant
-------------------------------
-You will need to install Virtual Box and Vagrant.
+You will need to install Libvirt and Vagrant.
Create a Vagrant Directory
---------------------------
@@ -32,21 +32,16 @@ Create a file called **Vagrantfile** with the following contents:
Vagrant.configure(2) do |config|
- config.vm.box = "bento/ubuntu-18.04"
- config.vm.box_check_update = false
+ config.vm.box = "generic/ubuntu2204"
vmcpu=(ENV['VPP_VAGRANT_VMCPU'] || 2)
vmram=(ENV['VPP_VAGRANT_VMRAM'] || 4096)
config.ssh.forward_agent = true
- config.vm.provider "virtualbox" do |vb|
- vb.customize ["modifyvm", :id, "--ioapic", "on"]
+ config.vm.provider "libvirt" do |vb|
vb.memory = "#{vmram}"
vb.cpus = "#{vmcpu}"
- #support for the SSE4.x instruction is required in some versions of VB.
- vb.customize ["setextradata", :id, "VBoxInternal/CPUM/SSE4.1", "1"]
- vb.customize ["setextradata", :id, "VBoxInternal/CPUM/SSE4.2", "1"]
end
end
@@ -97,7 +92,7 @@ We write this file with the following contents:
.. code-block:: console
$ sudo bash
- # echo "deb [trusted=yes] https://packagecloud.io/fdio/release/ubuntu bionic main" > /etc/apt/sources.list.d/99fd.io.list
+ # echo "deb https://packagecloud.io/fdio/release/ubuntu jammy main" > /etc/apt/sources.list.d/99fd.io.list
#
Get the key.
diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt
index 2348c8dc391..f90ffa89216 100644
--- a/docs/spelling_wordlist.txt
+++ b/docs/spelling_wordlist.txt
@@ -1047,6 +1047,7 @@ srcIP
srcPortDefinition
srcUP
srh
+srmpls
Srmpls
srtp
SRTP
diff --git a/extras/hs-test/Makefile b/extras/hs-test/Makefile
index d4e699940d1..b809b170e00 100644
--- a/extras/hs-test/Makefile
+++ b/extras/hs-test/Makefile
@@ -1,3 +1,4 @@
+export HS_ROOT=$(CURDIR)
ifeq ($(VERBOSE),)
VERBOSE=false
@@ -15,6 +16,10 @@ ifeq ($(TEST),)
TEST=all
endif
+ifeq ($(TEST-HS),)
+TEST-HS=all
+endif
+
ifeq ($(DEBUG),)
DEBUG=false
endif
@@ -50,7 +55,9 @@ list_tests = @go run github.com/onsi/ginkgo/v2/ginkgo --dry-run -v --no-color --
help:
@echo "Make targets:"
@echo " test - run tests"
+ @echo " test-debug - run tests (vpp debug image)"
@echo " build - build test infra"
+ @echo " build-cov - coverage build of VPP and Docker images"
@echo " build-debug - build test infra (vpp debug image)"
@echo " build-go - just build golang files"
@echo " fixstyle - format .go source files"
@@ -66,7 +73,7 @@ help:
@echo " UNCONFIGURE=[true|false] - unconfigure selected test"
@echo " DEBUG=[true|false] - attach VPP to GDB"
@echo " TEST=[test-name] - specific test to run"
- @echo " CPUS=[n-cpus] - number of cpus to run with vpp"
+ @echo " CPUS=[n-cpus] - number of cpus to allocate to VPP and containers"
@echo " VPPSRC=[path-to-vpp-src] - path to vpp source files (for gdb)"
@echo " PARALLEL=[n-cpus] - number of test processes to spawn to run in parallel"
@echo " REPEAT=[n] - repeat tests up to N times or until a failure occurs"
@@ -86,14 +93,41 @@ build-vpp-release:
build-vpp-debug:
@make -C ../.. build
+.PHONY: build-vpp-gcov
+build-vpp-gcov:
+ @make -C ../.. build-vpp-gcov
+
.build.ok: build
@touch .build.ok
+.build_debug.ok: build-debug
+ @touch .build.ok
+
.PHONY: test
test: .deps.ok .build.ok
- @bash ./test --persist=$(PERSIST) --verbose=$(VERBOSE) \
+ # '-' ignores the exit status, it is set in compress.sh
+ # necessary so gmake won't skip executing the bash script
+ -bash ./test --persist=$(PERSIST) --verbose=$(VERBOSE) \
--unconfigure=$(UNCONFIGURE) --debug=$(DEBUG) --test=$(TEST) --cpus=$(CPUS) \
--vppsrc=$(VPPSRC) --parallel=$(PARALLEL) --repeat=$(REPEAT)
+ @bash ./script/compress.sh
+
+.PHONY: test-debug
+test-debug: .deps.ok .build_debug.ok
+ # '-' ignores the exit status, it is set in compress.sh
+ # necessary so gmake won't skip executing the bash script
+ -bash ./test --persist=$(PERSIST) --verbose=$(VERBOSE) \
+ --unconfigure=$(UNCONFIGURE) --debug=$(DEBUG) --test=$(TEST) --cpus=$(CPUS) \
+ --vppsrc=$(VPPSRC) --parallel=$(PARALLEL) --repeat=$(REPEAT)
+ @bash ./script/compress.sh
+
+.PHONY: test-cov
+test-cov: .deps.ok .build.ok
+ -bash ./test --persist=$(PERSIST) --verbose=$(VERBOSE) \
+ --unconfigure=$(UNCONFIGURE) --debug=$(DEBUG) --test=$(TEST-HS) --cpus=$(CPUS) \
+ --vppsrc=$(VPPSRC)
+ @make -C ../.. test-cov-post HS_TEST=1
+ @bash ./script/compress.sh
.PHONY: build-go
build-go:
@@ -105,6 +139,12 @@ build: .deps.ok build-vpp-release build-go
bash ./script/build_hst.sh release
@touch .build.ok
+.PHONY: build-cov
+build-cov: .deps.ok build-vpp-gcov build-go
+ @rm -f .build.vpp
+ bash ./script/build_hst.sh gcov
+ @touch .build.vpp
+
.PHONY: build-debug
build-debug: .deps.ok build-vpp-debug build-go
@rm -f .build.ok
diff --git a/extras/hs-test/container.go b/extras/hs-test/container.go
index c82f1fc03a7..44d84d5fe65 100644
--- a/extras/hs-test/container.go
+++ b/extras/hs-test/container.go
@@ -37,6 +37,7 @@ type Container struct {
volumes map[string]Volume
envVars map[string]string
vppInstance *VppInstance
+ allocatedCpus []int
}
func newContainer(suite *HstSuite, yamlInput ContainerConfig) (*Container, error) {
@@ -77,7 +78,7 @@ func newContainer(suite *HstSuite, yamlInput ContainerConfig) (*Container, error
}
if _, ok := yamlInput["volumes"]; ok {
- workingVolumeDir := logDir + CurrentSpecReport().LeafNodeText + container.suite.pid + volumeDir
+ workingVolumeDir := logDir + CurrentSpecReport().LeafNodeText + volumeDir
workDirReplacer := strings.NewReplacer("$HST_DIR", workDir)
volDirReplacer := strings.NewReplacer("$HST_VOLUME_DIR", workingVolumeDir)
for _, volu := range yamlInput["volumes"].([]interface{}) {
@@ -160,6 +161,12 @@ func (c *Container) create() error {
return exechelper.Run(cmd)
}
+func (c *Container) allocateCpus() {
+ c.suite.startedContainers = append(c.suite.startedContainers, c)
+ c.allocatedCpus = c.suite.AllocateCpus()
+ c.suite.log("Allocated CPUs " + fmt.Sprint(c.allocatedCpus) + " to container " + c.name)
+}
+
func (c *Container) start() error {
cmd := "docker start " + c.name
c.suite.log(cmd)
@@ -175,6 +182,9 @@ func (c *Container) prepareCommand() (string, error) {
if c.runDetached {
cmd += " -d"
}
+
+ c.allocateCpus()
+ cmd += fmt.Sprintf(" --cpuset-cpus=\"%d-%d\"", c.allocatedCpus[0], c.allocatedCpus[len(c.allocatedCpus)-1])
cmd += " " + c.getContainerArguments()
c.suite.log(cmd)
@@ -286,7 +296,7 @@ func (c *Container) exec(command string, arguments ...any) string {
GinkgoHelper()
c.suite.log(containerExecCommand)
byteOutput, err := exechelper.CombinedOutput(containerExecCommand)
- c.suite.assertNil(err, err)
+ c.suite.assertNil(err, fmt.Sprint(err))
return string(byteOutput)
}
@@ -340,7 +350,7 @@ func (c *Container) log(maxLines int) (string, error) {
}
func (c *Container) stop() error {
- if c.vppInstance != nil && c.vppInstance.apiChannel != nil {
+ if c.vppInstance != nil && c.vppInstance.apiStream != nil {
c.vppInstance.saveLogs()
c.vppInstance.disconnect()
}
diff --git a/extras/hs-test/cpu.go b/extras/hs-test/cpu.go
index a976f47d8a5..49a7dfb02f8 100644
--- a/extras/hs-test/cpu.go
+++ b/extras/hs-test/cpu.go
@@ -4,6 +4,7 @@ import (
"bufio"
"errors"
"fmt"
+ . "github.com/onsi/ginkgo/v2"
"os"
"os/exec"
"strings"
@@ -16,26 +17,35 @@ type CpuContext struct {
cpus []int
}
-func (c *CpuContext) Release() {
- c.cpuAllocator.cpus = append(c.cpuAllocator.cpus, c.cpus...)
- c.cpus = c.cpus[:0] // empty the list
-}
-
type CpuAllocatorT struct {
cpus []int
}
var cpuAllocator *CpuAllocatorT = nil
-func (c *CpuAllocatorT) Allocate(nCpus int) (*CpuContext, error) {
+func (c *CpuAllocatorT) Allocate(containerCount int, nCpus int) (*CpuContext, error) {
var cpuCtx CpuContext
- if len(c.cpus) < nCpus {
- return nil, fmt.Errorf("could not allocate %d CPUs; available: %d", nCpus, len(c.cpus))
+ // splitting cpus into equal parts; this will over-allocate cores but it's good enough for now
+ maxContainerCount := 4
+ // skip CPU 0
+ minCpu := ((GinkgoParallelProcess() - 1) * maxContainerCount * nCpus) + 1
+ maxCpu := (GinkgoParallelProcess() * maxContainerCount * nCpus)
+
+ if len(c.cpus)-1 < maxCpu {
+ err := fmt.Errorf("could not allocate %d CPUs; available: %d; attempted to allocate cores %d-%d",
+ nCpus*containerCount, len(c.cpus)-1, minCpu, maxCpu)
+ return nil, err
}
- cpuCtx.cpus = c.cpus[0:nCpus]
+ if containerCount == 1 {
+ cpuCtx.cpus = c.cpus[minCpu : minCpu+nCpus]
+ } else if containerCount > 1 && containerCount <= maxContainerCount {
+ cpuCtx.cpus = c.cpus[minCpu+(nCpus*(containerCount-1)) : minCpu+(nCpus*containerCount)]
+ } else {
+ return nil, fmt.Errorf("too many containers; CPU allocation for >%d containers is not implemented", maxContainerCount)
+ }
+
cpuCtx.cpuAllocator = c
- c.cpus = c.cpus[nCpus:]
return &cpuCtx, nil
}
diff --git a/extras/hs-test/docker/Dockerfile.vpp b/extras/hs-test/docker/Dockerfile.vpp
index ace83c593c6..9d900e86772 100644
--- a/extras/hs-test/docker/Dockerfile.vpp
+++ b/extras/hs-test/docker/Dockerfile.vpp
@@ -5,7 +5,7 @@ FROM ubuntu:${UBUNTU_VERSION}
RUN apt-get update \
&& apt-get install -y openssl libapr1 libnuma1 libsubunit0 \
iproute2 libnl-3-dev libnl-route-3-dev python3 iputils-ping \
- vim gdb \
+ vim gdb libunwind-dev \
&& rm -rf /var/lib/apt/lists/*
ENV DIR=vpp-data/lib/vpp_plugins
diff --git a/extras/hs-test/echo_test.go b/extras/hs-test/echo_test.go
index 0515b5e0411..ce852bea3e0 100644
--- a/extras/hs-test/echo_test.go
+++ b/extras/hs-test/echo_test.go
@@ -21,7 +21,9 @@ func EchoBuiltinTest(s *VethsSuite) {
s.assertNotContains(o, "failed:")
}
+// unstable with multiple workers
func TcpWithLossTest(s *VethsSuite) {
+ s.SkipIfMultiWorker()
serverVpp := s.getContainerByName("server-vpp").vppInstance
serverVeth := s.getInterfaceByName(serverInterfaceName)
@@ -45,5 +47,5 @@ func TcpWithLossTest(s *VethsSuite) {
serverVeth.ip4AddressString())
s.log(output)
s.assertNotEqual(len(output), 0)
- s.assertNotContains(output, "failed: timeout", output)
+ s.assertNotContains(output, "failed", output)
}
diff --git a/extras/hs-test/framework_test.go b/extras/hs-test/framework_test.go
index 8773fa2417d..8cbf936f026 100644
--- a/extras/hs-test/framework_test.go
+++ b/extras/hs-test/framework_test.go
@@ -2,12 +2,21 @@ package main
import (
"testing"
+ "time"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
+var suiteTimeout time.Duration
+
func TestHst(t *testing.T) {
+ if *isVppDebug {
+ // 30 minute timeout so that the framework won't timeout while debugging
+ suiteTimeout = time.Minute * 30
+ } else {
+ suiteTimeout = time.Minute * 5
+ }
RegisterFailHandler(Fail)
RunSpecs(t, "HST")
}
diff --git a/extras/hs-test/go.mod b/extras/hs-test/go.mod
index 0f3854d2148..3be9ba20a86 100644
--- a/extras/hs-test/go.mod
+++ b/extras/hs-test/go.mod
@@ -26,7 +26,7 @@ require (
github.com/onsi/ginkgo/v2 v2.16.0
github.com/onsi/gomega v1.32.0
github.com/pkg/errors v0.9.1 // indirect
- github.com/sirupsen/logrus v1.9.3 // indirect
+ github.com/sirupsen/logrus v1.9.3
github.com/vishvananda/netns v0.0.4 // indirect
golang.org/x/sys v0.16.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
diff --git a/extras/hs-test/hst_suite.go b/extras/hs-test/hst_suite.go
index bb499246bf9..26dcf4e5a2b 100644
--- a/extras/hs-test/hst_suite.go
+++ b/extras/hs-test/hst_suite.go
@@ -5,7 +5,8 @@ import (
"errors"
"flag"
"fmt"
- "log/slog"
+ "io"
+ "log"
"os"
"os/exec"
"strings"
@@ -29,19 +30,28 @@ var nConfiguredCpus = flag.Int("cpus", 1, "number of CPUs assigned to vpp")
var vppSourceFileDir = flag.String("vppsrc", "", "vpp source file directory")
type HstSuite struct {
- containers map[string]*Container
- volumes []string
- netConfigs []NetConfig
- netInterfaces map[string]*NetInterface
- ip4AddrAllocator *Ip4AddressAllocator
- testIds map[string]string
- cpuAllocator *CpuAllocatorT
- cpuContexts []*CpuContext
- cpuPerVpp int
- pid string
+ containers map[string]*Container
+ startedContainers []*Container
+ volumes []string
+ netConfigs []NetConfig
+ netInterfaces map[string]*NetInterface
+ ip4AddrAllocator *Ip4AddressAllocator
+ testIds map[string]string
+ cpuAllocator *CpuAllocatorT
+ cpuContexts []*CpuContext
+ cpuPerVpp int
+ pid string
+ logger *log.Logger
+ logFile *os.File
}
func (s *HstSuite) SetupSuite() {
+ s.createLogger()
+ s.log("Suite Setup")
+ RegisterFailHandler(func(message string, callerSkip ...int) {
+ s.hstFail()
+ Fail(message, callerSkip...)
+ })
var err error
s.pid = fmt.Sprint(os.Getpid())
s.cpuAllocator, err = CpuAllocator()
@@ -52,7 +62,7 @@ func (s *HstSuite) SetupSuite() {
}
func (s *HstSuite) AllocateCpus() []int {
- cpuCtx, err := s.cpuAllocator.Allocate(s.cpuPerVpp)
+ cpuCtx, err := s.cpuAllocator.Allocate(len(s.startedContainers), s.cpuPerVpp)
s.assertNil(err)
s.AddCpuContext(cpuCtx)
return cpuCtx.cpus
@@ -63,16 +73,16 @@ func (s *HstSuite) AddCpuContext(cpuCtx *CpuContext) {
}
func (s *HstSuite) TearDownSuite() {
+ defer s.logFile.Close()
+ s.log("Suite Teardown")
s.unconfigureNetworkTopology()
}
func (s *HstSuite) TearDownTest() {
+ s.log("Test Teardown")
if *isPersistent {
return
}
- for _, c := range s.cpuContexts {
- c.Release()
- }
s.resetContainers()
s.removeVolumes()
s.ip4AddrAllocator.deleteIpAddresses()
@@ -85,10 +95,8 @@ func (s *HstSuite) skipIfUnconfiguring() {
}
func (s *HstSuite) SetupTest() {
- RegisterFailHandler(func(message string, callerSkip ...int) {
- s.hstFail()
- Fail(message, callerSkip...)
- })
+ s.log("Test Setup")
+ s.startedContainers = s.startedContainers[:0]
s.skipIfUnconfiguring()
s.setupVolumes()
s.setupContainers()
@@ -110,7 +118,7 @@ func (s *HstSuite) setupContainers() {
}
}
-func logVppInstance(container *Container, maxLines int) {
+func (s *HstSuite) logVppInstance(container *Container, maxLines int) {
if container.vppInstance == nil {
return
}
@@ -136,26 +144,26 @@ func logVppInstance(container *Container, maxLines int) {
}
}
- fmt.Println("vvvvvvvvvvvvvvv " + container.name + " [VPP instance]:")
+ s.log("vvvvvvvvvvvvvvv " + container.name + " [VPP instance]:")
for _, line := range lines {
- fmt.Println(line)
+ s.log(line)
}
- fmt.Printf("^^^^^^^^^^^^^^^\n\n")
+ s.log("^^^^^^^^^^^^^^^\n\n")
}
func (s *HstSuite) hstFail() {
- fmt.Println("Containers: " + fmt.Sprint(s.containers))
- for _, container := range s.containers {
+ for _, container := range s.startedContainers {
out, err := container.log(20)
if err != nil {
- fmt.Printf("An error occured while obtaining '%s' container logs: %s\n", container.name, fmt.Sprint(err))
+ s.log("An error occured while obtaining '" + container.name + "' container logs: " + fmt.Sprint(err))
+ s.log("The container might not be running - check logs in " + container.getLogDirPath())
continue
}
- fmt.Printf("\nvvvvvvvvvvvvvvv " +
+ s.log("\nvvvvvvvvvvvvvvv " +
container.name + ":\n" +
out +
"^^^^^^^^^^^^^^^\n\n")
- logVppInstance(container, 20)
+ s.logVppInstance(container, 20)
}
}
@@ -187,9 +195,25 @@ func (s *HstSuite) assertNotEmpty(object interface{}, msgAndArgs ...interface{})
Expect(object).ToNot(BeEmpty(), msgAndArgs...)
}
+func (s *HstSuite) createLogger() {
+ suiteName := CurrentSpecReport().ContainerHierarchyTexts[0]
+ var err error
+ s.logFile, err = os.Create("summary/" + suiteName + ".log")
+ if err != nil {
+ Fail("Unable to create log file.")
+ }
+ s.logger = log.New(io.Writer(s.logFile), "", log.LstdFlags)
+}
+
+// Logs to files by default, logs to stdout when VERBOSE=true with GinkgoWriter
+// to keep console tidy
func (s *HstSuite) log(arg any) {
+ logs := strings.Split(fmt.Sprint(arg), "\n")
+ for _, line := range logs {
+ s.logger.Println(line)
+ }
if *isVerbose {
- slog.Info(fmt.Sprint(arg))
+ GinkgoWriter.Println(arg)
}
}
@@ -266,7 +290,7 @@ func (s *HstSuite) loadContainerTopology(topologyName string) {
for _, elem := range yamlTopo.Volumes {
volumeMap := elem["volume"].(VolumeConfig)
hostDir := volumeMap["host-dir"].(string)
- workingVolumeDir := logDir + CurrentSpecReport().LeafNodeText + s.pid + volumeDir
+ workingVolumeDir := logDir + CurrentSpecReport().LeafNodeText + volumeDir
volDirReplacer := strings.NewReplacer("$HST_VOLUME_DIR", workingVolumeDir)
hostDir = volDirReplacer.Replace(hostDir)
s.volumes = append(s.volumes, hostDir)
@@ -450,7 +474,7 @@ func (s *HstSuite) startHttpServer(running chan struct{}, done chan struct{}, ad
err := cmd.Start()
s.log(cmd)
if err != nil {
- fmt.Println("Failed to start http server: " + fmt.Sprint(err))
+ s.log("Failed to start http server: " + fmt.Sprint(err))
return
}
running <- struct{}{}
diff --git a/extras/hs-test/http_test.go b/extras/hs-test/http_test.go
index fe12f5a2f65..0bb6a43e851 100644
--- a/extras/hs-test/http_test.go
+++ b/extras/hs-test/http_test.go
@@ -2,6 +2,7 @@ package main
import (
"fmt"
+ "net/http"
"os"
"strings"
"time"
@@ -11,12 +12,16 @@ import (
func init() {
registerNsTests(HttpTpsTest)
- registerVethTests(HttpCliTest)
+ registerVethTests(HttpCliTest, HttpCliConnectErrorTest)
registerNoTopoTests(NginxHttp3Test, NginxAsServerTest,
- NginxPerfCpsTest, NginxPerfRpsTest, NginxPerfWrkTest, HeaderServerTest)
+ NginxPerfCpsTest, NginxPerfRpsTest, NginxPerfWrkTest, HeaderServerTest,
+ HttpStaticMovedTest, HttpStaticNotFoundTest, HttpCliMethodNotAllowedTest,
+ HttpCliBadRequestTest, HttpStaticPathTraversalTest)
registerNoTopoSoloTests(HttpStaticPromTest)
}
+const wwwRootPath = "/tmp/www_root"
+
func HttpTpsTest(s *NsSuite) {
iface := s.getInterfaceByName(clientInterface)
client_ip := iface.ip4AddressString()
@@ -55,6 +60,20 @@ func HttpCliTest(s *VethsSuite) {
s.assertContains(o, "<html>", "<html> not found in the result!")
}
+func HttpCliConnectErrorTest(s *VethsSuite) {
+ clientContainer := s.getContainerByName("client-vpp")
+
+ serverVeth := s.getInterfaceByName(serverInterfaceName)
+
+ uri := "http://" + serverVeth.ip4AddressString() + "/80"
+
+ o := clientContainer.vppInstance.vppctl("http cli client" +
+ " uri " + uri + " query /show/vlib/graph")
+
+ s.log(o)
+ s.assertContains(o, "failed to connect")
+}
+
func NginxHttp3Test(s *NoTopoSuite) {
s.SkipUnlessExtendedTestsBuilt()
@@ -91,22 +110,101 @@ func HttpStaticPromTest(s *NoTopoSuite) {
s.assertNil(err)
}
+func HttpStaticPathTraversalTest(s *NoTopoSuite) {
+ vpp := s.getContainerByName("vpp").vppInstance
+ vpp.container.exec("mkdir -p " + wwwRootPath)
+ vpp.container.exec("mkdir -p " + "/tmp/secret_folder")
+ vpp.container.createFile("/tmp/secret_folder/secret_file.txt", "secret")
+ serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
+ s.log(vpp.vppctl("http static server www-root " + wwwRootPath + " uri tcp://" + serverAddress + "/80 debug"))
+
+ client := newHttpClient()
+ req, err := http.NewRequest("GET", "http://"+serverAddress+":80/../secret_folder/secret_file.txt", nil)
+ s.assertNil(err, fmt.Sprint(err))
+ resp, err := client.Do(req)
+ s.assertNil(err, fmt.Sprint(err))
+ defer resp.Body.Close()
+ s.assertEqual(404, resp.StatusCode)
+}
+
+func HttpStaticMovedTest(s *NoTopoSuite) {
+ vpp := s.getContainerByName("vpp").vppInstance
+ vpp.container.exec("mkdir -p " + wwwRootPath + "/tmp.aaa")
+ vpp.container.createFile(wwwRootPath+"/tmp.aaa/index.html", "<http><body><p>Hello</p></body></http>")
+ serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
+ s.log(vpp.vppctl("http static server www-root " + wwwRootPath + " uri tcp://" + serverAddress + "/80 debug"))
+
+ client := newHttpClient()
+ req, err := http.NewRequest("GET", "http://"+serverAddress+":80/tmp.aaa", nil)
+ s.assertNil(err, fmt.Sprint(err))
+ resp, err := client.Do(req)
+ s.assertNil(err, fmt.Sprint(err))
+ defer resp.Body.Close()
+ s.assertEqual(301, resp.StatusCode)
+ s.assertNotEqual("", resp.Header.Get("Location"))
+}
+
+func HttpStaticNotFoundTest(s *NoTopoSuite) {
+ vpp := s.getContainerByName("vpp").vppInstance
+ vpp.container.exec("mkdir -p " + wwwRootPath)
+ serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
+ s.log(vpp.vppctl("http static server www-root " + wwwRootPath + " uri tcp://" + serverAddress + "/80 debug"))
+
+ client := newHttpClient()
+ req, err := http.NewRequest("GET", "http://"+serverAddress+":80/notfound.html", nil)
+ s.assertNil(err, fmt.Sprint(err))
+ resp, err := client.Do(req)
+ s.assertNil(err, fmt.Sprint(err))
+ defer resp.Body.Close()
+ s.assertEqual(404, resp.StatusCode)
+}
+
+func HttpCliMethodNotAllowedTest(s *NoTopoSuite) {
+ vpp := s.getContainerByName("vpp").vppInstance
+ serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
+ vpp.vppctl("http cli server")
+
+ client := newHttpClient()
+ req, err := http.NewRequest("POST", "http://"+serverAddress+":80/test", nil)
+ s.assertNil(err, fmt.Sprint(err))
+ resp, err := client.Do(req)
+ s.assertNil(err, fmt.Sprint(err))
+ defer resp.Body.Close()
+ s.assertEqual(405, resp.StatusCode)
+ // TODO: need to be fixed in http code
+ //s.assertNotEqual("", resp.Header.Get("Allow"))
+}
+
+func HttpCliBadRequestTest(s *NoTopoSuite) {
+ vpp := s.getContainerByName("vpp").vppInstance
+ serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
+ vpp.vppctl("http cli server")
+
+ client := newHttpClient()
+ req, err := http.NewRequest("GET", "http://"+serverAddress+":80", nil)
+ s.assertNil(err, fmt.Sprint(err))
+ resp, err := client.Do(req)
+ s.assertNil(err, fmt.Sprint(err))
+ defer resp.Body.Close()
+ s.assertEqual(400, resp.StatusCode)
+}
+
func HeaderServerTest(s *NoTopoSuite) {
- query := "show/version"
vpp := s.getContainerByName("vpp").vppInstance
serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
vpp.vppctl("http cli server")
- curlCont := s.getContainerByName("curl")
- args := fmt.Sprintf("curl -i -s http://%s:80/%s", serverAddress, query)
- curlCont.extraRunningArgs = args
- o, err := curlCont.combinedOutput()
+ client := newHttpClient()
+ req, err := http.NewRequest("GET", "http://"+serverAddress+":80/show/version", nil)
s.assertNil(err, fmt.Sprint(err))
- s.log(o)
- s.assertContains(o, "Server: http_cli_server")
+ resp, err := client.Do(req)
+ s.assertNil(err, fmt.Sprint(err))
+ defer resp.Body.Close()
+ s.assertEqual("http_cli_server", resp.Header.Get("Server"))
}
func NginxAsServerTest(s *NoTopoSuite) {
+ s.skip("Broken in the CI")
query := "return_ok"
finished := make(chan error, 1)
@@ -160,7 +258,6 @@ func runNginxPerf(s *NoTopoSuite, mode, ab_or_wrk string) error {
args += " -r"
args += " http://" + serverAddress + ":80/64B.json"
abCont.extraRunningArgs = args
- time.Sleep(time.Second * 10)
o, err := abCont.combinedOutput()
rps := parseString(o, "Requests per second:")
s.log(rps)
@@ -180,14 +277,19 @@ func runNginxPerf(s *NoTopoSuite, mode, ab_or_wrk string) error {
return nil
}
+// unstable with multiple workers
func NginxPerfCpsTest(s *NoTopoSuite) {
+ s.skip("Broken in the CI")
+ s.SkipIfMultiWorker()
s.assertNil(runNginxPerf(s, "cps", "ab"))
}
func NginxPerfRpsTest(s *NoTopoSuite) {
+ s.skip("Broken in the CI")
s.assertNil(runNginxPerf(s, "rps", "ab"))
}
func NginxPerfWrkTest(s *NoTopoSuite) {
+ s.skip("Broken in the CI")
s.assertNil(runNginxPerf(s, "", "wrk"))
}
diff --git a/extras/hs-test/mirroring_test.go b/extras/hs-test/mirroring_test.go
index 6c5a860b01c..daf3fc913e0 100644
--- a/extras/hs-test/mirroring_test.go
+++ b/extras/hs-test/mirroring_test.go
@@ -5,10 +5,13 @@ import (
)
func init() {
- registerNginxTests(MirroringTest)
+ // registerNginxTests(MirroringTest)
}
+// broken when CPUS > 1
func MirroringTest(s *NginxSuite) {
+ s.skip("Broken in the CI")
+ s.SkipIfMultiWorker()
proxyAddress := s.getInterfaceByName(mirroringClientInterfaceName).peer.ip4AddressString()
path := "/64B.json"
diff --git a/extras/hs-test/raw_session_test.go b/extras/hs-test/raw_session_test.go
index cf74c62cd3e..5c66df0b1ce 100644
--- a/extras/hs-test/raw_session_test.go
+++ b/extras/hs-test/raw_session_test.go
@@ -1,16 +1,15 @@
package main
func init() {
- registerVethTests(VppEchoQuicTest, VppEchoTcpTest, VppEchoUdpTest)
+ registerVethTests(VppEchoQuicTest, VppEchoTcpTest)
}
func VppEchoQuicTest(s *VethsSuite) {
s.testVppEcho("quic")
}
-// udp echo currently broken in vpp, skipping
+// TODO: udp echo currently broken in vpp
func VppEchoUdpTest(s *VethsSuite) {
- s.skip("Broken")
s.testVppEcho("udp")
}
diff --git a/extras/hs-test/script/build_hst.sh b/extras/hs-test/script/build_hst.sh
index 33a8393b8b5..3b4bc28e275 100755
--- a/extras/hs-test/script/build_hst.sh
+++ b/extras/hs-test/script/build_hst.sh
@@ -21,6 +21,8 @@ export VPP_WS=../..
if [ "$1" == "debug" ]; then
VPP_BUILD_ROOT=${VPP_WS}/build-root/build-vpp_debug-native/vpp
+elif [ "$1" == "gcov" ]; then
+ VPP_BUILD_ROOT=${VPP_WS}/build-root/build-vpp_gcov-native/vpp
else
VPP_BUILD_ROOT=${VPP_WS}/build-root/build-vpp-native/vpp
fi
@@ -67,9 +69,9 @@ docker_build hs-test/vpp vpp
docker_build hs-test/nginx-ldp nginx
docker_build hs-test/nginx-server nginx-server
docker_build hs-test/build build
-docker_build hs-test/curl curl
if [ "$HST_EXTENDED_TESTS" = true ] ; then
docker_build hs-test/nginx-http3 nginx-http3
+ docker_build hs-test/curl curl
fi
# cleanup detached images
diff --git a/extras/hs-test/script/compress.sh b/extras/hs-test/script/compress.sh
new file mode 100644
index 00000000000..1f0205c1efb
--- /dev/null
+++ b/extras/hs-test/script/compress.sh
@@ -0,0 +1,33 @@
+#!/usr/bin/env bash
+
+# if failed-summary.log is not empty, exit status = 1
+if [ -s "${HS_ROOT}/summary/failed-summary.log" ]
+then
+ if [ -n "${WORKSPACE}" ]
+ then
+ echo -n "Copying docker logs..."
+ dirs=$(jq -r '.[0] | .SpecReports[] | select(.State == "failed") | .LeafNodeText' ${HS_ROOT}/summary/report.json)
+ for dirName in $dirs; do
+ logDir=/tmp/hs-test/$dirName
+ if [ -d "$logDir" ]; then
+ mkdir -p ${WORKSPACE}/archives/summary
+ cp -r $logDir ${WORKSPACE}/archives/summary/
+ fi
+ done
+ echo "Done."
+
+ echo -n "Copying failed test logs into build log archive directory (${WORKSPACE}/archives)... "
+ mkdir -p ${WORKSPACE}/archives/summary
+ cp -a ${HS_ROOT}/summary/* ${WORKSPACE}/archives/summary
+ echo "Done."
+
+ echo -n "Compressing files in ${WORKSPACE}/archives from test runs... "
+ cd ${WORKSPACE}/archives
+ find . -type f \( -name "*.json" -o -name "*.log" \) -exec gzip {} \;
+ echo "Done."
+
+ else
+ echo "Not compressing files in temporary directories from test runs."
+ fi
+ exit 1
+fi
diff --git a/extras/hs-test/suite_nginx_test.go b/extras/hs-test/suite_nginx_test.go
index 2d1caf152f4..4c6e9dbb309 100644
--- a/extras/hs-test/suite_nginx_test.go
+++ b/extras/hs-test/suite_nginx_test.go
@@ -4,7 +4,6 @@ import (
"reflect"
"runtime"
"strings"
- "time"
. "github.com/onsi/ginkgo/v2"
)
@@ -48,10 +47,9 @@ func (s *NginxSuite) SetupTest() {
append("enable").
append("use-app-socket-api").close()
- cpus := s.AllocateCpus()
// ... for proxy
vppProxyContainer := s.getContainerByName(vppProxyContainerName)
- proxyVpp, _ := vppProxyContainer.newVppInstance(cpus, sessionConfig)
+ proxyVpp, _ := vppProxyContainer.newVppInstance(vppProxyContainer.allocatedCpus, sessionConfig)
s.assertNil(proxyVpp.start())
clientInterface := s.getInterfaceByName(mirroringClientInterfaceName)
@@ -98,9 +96,11 @@ var _ = Describe("NginxSuite", Ordered, ContinueOnFailure, func() {
test := test
pc := reflect.ValueOf(test).Pointer()
funcValue := runtime.FuncForPC(pc)
- It(strings.Split(funcValue.Name(), ".")[2], func(ctx SpecContext) {
+ testName := strings.Split(funcValue.Name(), ".")[2]
+ It(testName, func(ctx SpecContext) {
+ s.log(testName + ": BEGIN")
test(&s)
- }, SpecTimeout(time.Minute*5))
+ }, SpecTimeout(suiteTimeout))
}
})
@@ -118,12 +118,15 @@ var _ = Describe("NginxSuiteSolo", Ordered, ContinueOnFailure, Serial, func() {
AfterEach(func() {
s.TearDownTest()
})
+
for _, test := range nginxSoloTests {
test := test
pc := reflect.ValueOf(test).Pointer()
funcValue := runtime.FuncForPC(pc)
- It(strings.Split(funcValue.Name(), ".")[2], Label("SOLO"), func(ctx SpecContext) {
+ testName := strings.Split(funcValue.Name(), ".")[2]
+ It(testName, Label("SOLO"), func(ctx SpecContext) {
+ s.log(testName + ": BEGIN")
test(&s)
- }, SpecTimeout(time.Minute*5))
+ }, SpecTimeout(suiteTimeout))
}
})
diff --git a/extras/hs-test/suite_no_topo_test.go b/extras/hs-test/suite_no_topo_test.go
index 6df06c7e60e..260fc1d681d 100644
--- a/extras/hs-test/suite_no_topo_test.go
+++ b/extras/hs-test/suite_no_topo_test.go
@@ -4,7 +4,6 @@ import (
"reflect"
"runtime"
"strings"
- "time"
. "github.com/onsi/ginkgo/v2"
)
@@ -45,9 +44,8 @@ func (s *NoTopoSuite) SetupTest() {
append("enable").
append("use-app-socket-api").close()
- cpus := s.AllocateCpus()
container := s.getContainerByName(singleTopoContainerVpp)
- vpp, _ := container.newVppInstance(cpus, sessionConfig)
+ vpp, _ := container.newVppInstance(container.allocatedCpus, sessionConfig)
s.assertNil(vpp.start())
tapInterface := s.getInterfaceByName(tapInterfaceName)
@@ -74,9 +72,11 @@ var _ = Describe("NoTopoSuite", Ordered, ContinueOnFailure, func() {
test := test
pc := reflect.ValueOf(test).Pointer()
funcValue := runtime.FuncForPC(pc)
- It(strings.Split(funcValue.Name(), ".")[2], func(ctx SpecContext) {
+ testName := strings.Split(funcValue.Name(), ".")[2]
+ It(testName, func(ctx SpecContext) {
+ s.log(testName + ": BEGIN")
test(&s)
- }, SpecTimeout(time.Minute*5))
+ }, SpecTimeout(suiteTimeout))
}
})
@@ -99,8 +99,10 @@ var _ = Describe("NoTopoSuiteSolo", Ordered, ContinueOnFailure, Serial, func() {
test := test
pc := reflect.ValueOf(test).Pointer()
funcValue := runtime.FuncForPC(pc)
- It(strings.Split(funcValue.Name(), ".")[2], Label("SOLO"), func(ctx SpecContext) {
+ testName := strings.Split(funcValue.Name(), ".")[2]
+ It(testName, Label("SOLO"), func(ctx SpecContext) {
+ s.log(testName + ": BEGIN")
test(&s)
- }, SpecTimeout(time.Minute*5))
+ }, SpecTimeout(suiteTimeout))
}
})
diff --git a/extras/hs-test/suite_ns_test.go b/extras/hs-test/suite_ns_test.go
index 86d9b78a010..7bdb90b42ae 100644
--- a/extras/hs-test/suite_ns_test.go
+++ b/extras/hs-test/suite_ns_test.go
@@ -5,7 +5,6 @@ import (
"reflect"
"runtime"
"strings"
- "time"
. "github.com/onsi/ginkgo/v2"
)
@@ -48,9 +47,8 @@ func (s *NsSuite) SetupTest() {
append("evt_qs_memfd_seg").
append("event-queue-length 100000").close()
- cpus := s.AllocateCpus()
container := s.getContainerByName("vpp")
- vpp, _ := container.newVppInstance(cpus, sessionConfig)
+ vpp, _ := container.newVppInstance(container.allocatedCpus, sessionConfig)
s.assertNil(vpp.start())
idx, err := vpp.createAfPacket(s.getInterfaceByName(serverInterface))
@@ -83,9 +81,11 @@ var _ = Describe("NsSuite", Ordered, ContinueOnFailure, func() {
test := test
pc := reflect.ValueOf(test).Pointer()
funcValue := runtime.FuncForPC(pc)
- It(strings.Split(funcValue.Name(), ".")[2], func(ctx SpecContext) {
+ testName := strings.Split(funcValue.Name(), ".")[2]
+ It(testName, func(ctx SpecContext) {
+ s.log(testName + ": BEGIN")
test(&s)
- }, SpecTimeout(time.Minute*5))
+ }, SpecTimeout(suiteTimeout))
}
})
@@ -108,8 +108,10 @@ var _ = Describe("NsSuiteSolo", Ordered, ContinueOnFailure, Serial, func() {
test := test
pc := reflect.ValueOf(test).Pointer()
funcValue := runtime.FuncForPC(pc)
- It(strings.Split(funcValue.Name(), ".")[2], Label("SOLO"), func(ctx SpecContext) {
+ testName := strings.Split(funcValue.Name(), ".")[2]
+ It(testName, Label("SOLO"), func(ctx SpecContext) {
+ s.log(testName + ": BEGIN")
test(&s)
- }, SpecTimeout(time.Minute*5))
+ }, SpecTimeout(suiteTimeout))
}
})
diff --git a/extras/hs-test/suite_tap_test.go b/extras/hs-test/suite_tap_test.go
index 25c1e25a215..cb0653304c3 100644
--- a/extras/hs-test/suite_tap_test.go
+++ b/extras/hs-test/suite_tap_test.go
@@ -48,9 +48,11 @@ var _ = Describe("TapSuite", Ordered, ContinueOnFailure, func() {
test := test
pc := reflect.ValueOf(test).Pointer()
funcValue := runtime.FuncForPC(pc)
- It(strings.Split(funcValue.Name(), ".")[2], func(ctx SpecContext) {
+ testName := strings.Split(funcValue.Name(), ".")[2]
+ It(testName, func(ctx SpecContext) {
+ s.log(testName + ": BEGIN")
test(&s)
- }, SpecTimeout(time.Minute*5))
+ }, SpecTimeout(suiteTimeout))
}
})
@@ -73,8 +75,10 @@ var _ = Describe("TapSuiteSolo", Ordered, ContinueOnFailure, Serial, func() {
test := test
pc := reflect.ValueOf(test).Pointer()
funcValue := runtime.FuncForPC(pc)
- It(strings.Split(funcValue.Name(), ".")[2], Label("SOLO"), func(ctx SpecContext) {
+ testName := strings.Split(funcValue.Name(), ".")[2]
+ It(testName, Label("SOLO"), func(ctx SpecContext) {
+ s.log(testName + ": BEGIN")
test(&s)
- }, SpecTimeout(time.Minute*5))
+ }, SpecTimeout(suiteTimeout))
}
})
diff --git a/extras/hs-test/suite_veth_test.go b/extras/hs-test/suite_veth_test.go
index f4c3684f031..13ef5ef268d 100644
--- a/extras/hs-test/suite_veth_test.go
+++ b/extras/hs-test/suite_veth_test.go
@@ -50,8 +50,7 @@ func (s *VethsSuite) SetupTest() {
// ... For server
serverContainer := s.getContainerByName("server-vpp")
- cpus := s.AllocateCpus()
- serverVpp, err := serverContainer.newVppInstance(cpus, sessionConfig)
+ serverVpp, err := serverContainer.newVppInstance(serverContainer.allocatedCpus, sessionConfig)
s.assertNotNil(serverVpp, fmt.Sprint(err))
s.setupServerVpp()
@@ -59,8 +58,7 @@ func (s *VethsSuite) SetupTest() {
// ... For client
clientContainer := s.getContainerByName("client-vpp")
- cpus = s.AllocateCpus()
- clientVpp, err := clientContainer.newVppInstance(cpus, sessionConfig)
+ clientVpp, err := clientContainer.newVppInstance(clientContainer.allocatedCpus, sessionConfig)
s.assertNotNil(clientVpp, fmt.Sprint(err))
s.setupClientVpp()
@@ -107,9 +105,11 @@ var _ = Describe("VethsSuite", Ordered, ContinueOnFailure, func() {
test := test
pc := reflect.ValueOf(test).Pointer()
funcValue := runtime.FuncForPC(pc)
- It(strings.Split(funcValue.Name(), ".")[2], func(ctx SpecContext) {
+ testName := strings.Split(funcValue.Name(), ".")[2]
+ It(testName, func(ctx SpecContext) {
+ s.log(testName + ": BEGIN")
test(&s)
- }, SpecTimeout(time.Minute*5))
+ }, SpecTimeout(suiteTimeout))
}
})
@@ -123,7 +123,6 @@ var _ = Describe("VethsSuiteSolo", Ordered, ContinueOnFailure, Serial, func() {
})
AfterAll(func() {
s.TearDownSuite()
-
})
AfterEach(func() {
s.TearDownTest()
@@ -134,8 +133,10 @@ var _ = Describe("VethsSuiteSolo", Ordered, ContinueOnFailure, Serial, func() {
test := test
pc := reflect.ValueOf(test).Pointer()
funcValue := runtime.FuncForPC(pc)
- It(strings.Split(funcValue.Name(), ".")[2], Label("SOLO"), func(ctx SpecContext) {
+ testName := strings.Split(funcValue.Name(), ".")[2]
+ It(testName, Label("SOLO"), func(ctx SpecContext) {
+ s.log(testName + ": BEGIN")
test(&s)
- }, SpecTimeout(time.Minute*5))
+ }, SpecTimeout(suiteTimeout))
}
})
diff --git a/extras/hs-test/test b/extras/hs-test/test
index 94162b87759..398e2b39edb 100755..100644
--- a/extras/hs-test/test
+++ b/extras/hs-test/test
@@ -86,4 +86,9 @@ if [ $single_test -eq 0 ] && [ $debug_set -eq 1 ]; then
exit 1
fi
-sudo -E go run github.com/onsi/ginkgo/v2/ginkgo --no-color --trace $ginkgo_args -- $args
+mkdir -p summary
+
+sudo -E go run github.com/onsi/ginkgo/v2/ginkgo --no-color --trace --json-report=summary/report.json $ginkgo_args -- $args
+
+jq -r '.[0] | .SpecReports[] | select((.State == "failed") or (.State == "timedout") or (.State == "panicked")) | select(.Failure != null) | "TestName: \(.LeafNodeText)\nSuite:\n\(.Failure.Location.FileName)\nMessage:\n\(.Failure.Message)\n Full Stack Trace:\n\(.Failure.Location.FullStackTrace)\n"' summary/report.json > summary/failed-summary.log \
+ && echo "Summary generated -> summary/failed-summary.log" \ No newline at end of file
diff --git a/extras/hs-test/utils.go b/extras/hs-test/utils.go
index 304dd4c241b..d250dc64519 100644
--- a/extras/hs-test/utils.go
+++ b/extras/hs-test/utils.go
@@ -3,8 +3,10 @@ package main
import (
"fmt"
"io"
+ "net/http"
"os"
"strings"
+ "time"
)
const networkTopologyDir string = "topo-network/"
@@ -78,3 +80,17 @@ func (s *Stanza) saveToFile(fileName string) error {
_, err = io.Copy(fo, strings.NewReader(s.content))
return err
}
+
+// newHttpClient creates [http.Client] with disabled proxy and redirects, it also sets timeout to 30seconds.
+func newHttpClient() *http.Client {
+ transport := http.DefaultTransport
+ transport.(*http.Transport).Proxy = nil
+ transport.(*http.Transport).DisableKeepAlives = true
+ client := &http.Client{
+ Transport: transport,
+ Timeout: time.Second * 30,
+ CheckRedirect: func(req *http.Request, via []*http.Request) error {
+ return http.ErrUseLastResponse
+ }}
+ return client
+}
diff --git a/extras/hs-test/vppinstance.go b/extras/hs-test/vppinstance.go
index 7ddec7e0ed4..8a92776894c 100644
--- a/extras/hs-test/vppinstance.go
+++ b/extras/hs-test/vppinstance.go
@@ -1,7 +1,9 @@
package main
import (
+ "context"
"fmt"
+ "io"
"os"
"os/exec"
"os/signal"
@@ -12,6 +14,7 @@ import (
"github.com/edwarnicke/exechelper"
. "github.com/onsi/ginkgo/v2"
+ "github.com/sirupsen/logrus"
"go.fd.io/govpp"
"go.fd.io/govpp/api"
@@ -20,7 +23,6 @@ import (
"go.fd.io/govpp/binapi/interface_types"
"go.fd.io/govpp/binapi/session"
"go.fd.io/govpp/binapi/tapv2"
- "go.fd.io/govpp/binapi/vpe"
"go.fd.io/govpp/core"
)
@@ -81,7 +83,7 @@ type VppInstance struct {
container *Container
additionalConfig []Stanza
connection *core.Connection
- apiChannel api.Channel
+ apiStream api.Stream
cpus []int
}
@@ -106,6 +108,11 @@ func (vpp *VppInstance) getEtcDir() string {
}
func (vpp *VppInstance) start() error {
+ maxReconnectAttempts := 3
+ // Replace default logger in govpp with our own
+ govppLogger := logrus.New()
+ govppLogger.SetOutput(io.MultiWriter(vpp.getSuite().logger.Writer(), GinkgoWriter))
+ core.SetLogger(govppLogger)
// Create folders
containerWorkDir := vpp.container.getContainerWorkDir()
@@ -136,6 +143,8 @@ func (vpp *VppInstance) start() error {
vpp.getSuite().log("starting vpp")
if *isVppDebug {
+ // default = 3; VPP will timeout while debugging if there are not enough attempts
+ maxReconnectAttempts = 5000
sig := make(chan os.Signal, 1)
signal.Notify(sig, syscall.SIGQUIT)
cont := make(chan bool, 1)
@@ -160,10 +169,10 @@ func (vpp *VppInstance) start() error {
sockAddress := vpp.container.getHostWorkDir() + defaultApiSocketFilePath
conn, connEv, err := govpp.AsyncConnect(
sockAddress,
- core.DefaultMaxReconnectAttempts,
+ maxReconnectAttempts,
core.DefaultReconnectInterval)
if err != nil {
- fmt.Println("async connect error: ", err)
+ vpp.getSuite().log("async connect error: " + fmt.Sprint(err))
return err
}
vpp.connection = conn
@@ -171,24 +180,19 @@ func (vpp *VppInstance) start() error {
// ... wait for Connected event
e := <-connEv
if e.State != core.Connected {
- fmt.Println("connecting to VPP failed: ", e.Error)
+ vpp.getSuite().log("connecting to VPP failed: " + fmt.Sprint(e.Error))
}
- // ... check compatibility of used messages
- ch, err := conn.NewAPIChannel()
+ ch, err := conn.NewStream(
+ context.Background(),
+ core.WithRequestSize(50),
+ core.WithReplySize(50),
+ core.WithReplyTimeout(time.Second*5))
if err != nil {
- fmt.Println("creating channel failed: ", err)
+ vpp.getSuite().log("creating stream failed: " + fmt.Sprint(err))
return err
}
- if err := ch.CheckCompatiblity(vpe.AllMessages()...); err != nil {
- fmt.Println("compatibility error: ", err)
- return err
- }
- if err := ch.CheckCompatiblity(interfaces.AllMessages()...); err != nil {
- fmt.Println("compatibility error: ", err)
- return err
- }
- vpp.apiChannel = ch
+ vpp.apiStream = ch
return nil
}
@@ -236,31 +240,50 @@ func (vpp *VppInstance) waitForApp(appName string, timeout int) {
func (vpp *VppInstance) createAfPacket(
veth *NetInterface,
) (interface_types.InterfaceIndex, error) {
- createReq := &af_packet.AfPacketCreateV2{
+ createReq := &af_packet.AfPacketCreateV3{
+ Mode: 1,
UseRandomHwAddr: true,
HostIfName: veth.Name(),
+ Flags: af_packet.AfPacketFlags(11),
}
if veth.hwAddress != (MacAddress{}) {
createReq.UseRandomHwAddr = false
createReq.HwAddr = veth.hwAddress
}
- createReply := &af_packet.AfPacketCreateV2Reply{}
vpp.getSuite().log("create af-packet interface " + veth.Name())
- if err := vpp.apiChannel.SendRequest(createReq).ReceiveReply(createReply); err != nil {
+ if err := vpp.apiStream.SendMsg(createReq); err != nil {
+ vpp.getSuite().hstFail()
+ return 0, err
+ }
+ replymsg, err := vpp.apiStream.RecvMsg()
+ if err != nil {
+ return 0, err
+ }
+ reply := replymsg.(*af_packet.AfPacketCreateV3Reply)
+ err = api.RetvalToVPPApiError(reply.Retval)
+ if err != nil {
return 0, err
}
- veth.index = createReply.SwIfIndex
+
+ veth.index = reply.SwIfIndex
// Set to up
upReq := &interfaces.SwInterfaceSetFlags{
SwIfIndex: veth.index,
Flags: interface_types.IF_STATUS_API_FLAG_ADMIN_UP,
}
- upReply := &interfaces.SwInterfaceSetFlagsReply{}
vpp.getSuite().log("set af-packet interface " + veth.Name() + " up")
- if err := vpp.apiChannel.SendRequest(upReq).ReceiveReply(upReply); err != nil {
+ if err := vpp.apiStream.SendMsg(upReq); err != nil {
+ return 0, err
+ }
+ replymsg, err = vpp.apiStream.RecvMsg()
+ if err != nil {
+ return 0, err
+ }
+ reply2 := replymsg.(*interfaces.SwInterfaceSetFlagsReply)
+ if err = api.RetvalToVPPApiError(reply2.Retval); err != nil {
return 0, err
}
@@ -279,10 +302,18 @@ func (vpp *VppInstance) createAfPacket(
SwIfIndex: veth.index,
Prefix: veth.addressWithPrefix(),
}
- addressReply := &interfaces.SwInterfaceAddDelAddressReply{}
vpp.getSuite().log("af-packet interface " + veth.Name() + " add address " + veth.ip4Address)
- if err := vpp.apiChannel.SendRequest(addressReq).ReceiveReply(addressReply); err != nil {
+ if err := vpp.apiStream.SendMsg(addressReq); err != nil {
+ return 0, err
+ }
+ replymsg, err = vpp.apiStream.RecvMsg()
+ if err != nil {
+ return 0, err
+ }
+ reply3 := replymsg.(*interfaces.SwInterfaceAddDelAddressReply)
+ err = api.RetvalToVPPApiError(reply3.Retval)
+ if err != nil {
return 0, err
}
@@ -294,25 +325,41 @@ func (vpp *VppInstance) addAppNamespace(
ifx interface_types.InterfaceIndex,
namespaceId string,
) error {
- req := &session.AppNamespaceAddDelV2{
+ req := &session.AppNamespaceAddDelV4{
+ IsAdd: true,
Secret: secret,
SwIfIndex: ifx,
NamespaceID: namespaceId,
+ SockName: defaultApiSocketFilePath,
}
- reply := &session.AppNamespaceAddDelV2Reply{}
vpp.getSuite().log("add app namespace " + namespaceId)
- if err := vpp.apiChannel.SendRequest(req).ReceiveReply(reply); err != nil {
+ if err := vpp.apiStream.SendMsg(req); err != nil {
+ return err
+ }
+ replymsg, err := vpp.apiStream.RecvMsg()
+ if err != nil {
+ return err
+ }
+ reply := replymsg.(*session.AppNamespaceAddDelV4Reply)
+ if err = api.RetvalToVPPApiError(reply.Retval); err != nil {
return err
}
sessionReq := &session.SessionEnableDisable{
IsEnable: true,
}
- sessionReply := &session.SessionEnableDisableReply{}
vpp.getSuite().log("enable app namespace " + namespaceId)
- if err := vpp.apiChannel.SendRequest(sessionReq).ReceiveReply(sessionReply); err != nil {
+ if err := vpp.apiStream.SendMsg(sessionReq); err != nil {
+ return err
+ }
+ replymsg, err = vpp.apiStream.RecvMsg()
+ if err != nil {
+ return err
+ }
+ reply2 := replymsg.(*session.SessionEnableDisableReply)
+ if err = api.RetvalToVPPApiError(reply2.Retval); err != nil {
return err
}
@@ -327,43 +374,64 @@ func (vpp *VppInstance) createTap(
if len(tapId) > 0 {
id = tapId[0]
}
- createTapReq := &tapv2.TapCreateV2{
+ createTapReq := &tapv2.TapCreateV3{
ID: id,
HostIfNameSet: true,
HostIfName: tap.Name(),
HostIP4PrefixSet: true,
HostIP4Prefix: tap.ip4AddressWithPrefix(),
}
- createTapReply := &tapv2.TapCreateV2Reply{}
vpp.getSuite().log("create tap interface " + tap.Name())
// Create tap interface
- if err := vpp.apiChannel.SendRequest(createTapReq).ReceiveReply(createTapReply); err != nil {
+ if err := vpp.apiStream.SendMsg(createTapReq); err != nil {
+ return err
+ }
+ replymsg, err := vpp.apiStream.RecvMsg()
+ if err != nil {
+ return err
+ }
+ reply := replymsg.(*tapv2.TapCreateV3Reply)
+ if err = api.RetvalToVPPApiError(reply.Retval); err != nil {
return err
}
// Add address
addAddressReq := &interfaces.SwInterfaceAddDelAddress{
IsAdd: true,
- SwIfIndex: createTapReply.SwIfIndex,
+ SwIfIndex: reply.SwIfIndex,
Prefix: tap.peer.addressWithPrefix(),
}
- addAddressReply := &interfaces.SwInterfaceAddDelAddressReply{}
vpp.getSuite().log("tap interface " + tap.Name() + " add address " + tap.peer.ip4Address)
- if err := vpp.apiChannel.SendRequest(addAddressReq).ReceiveReply(addAddressReply); err != nil {
+ if err := vpp.apiStream.SendMsg(addAddressReq); err != nil {
+ return err
+ }
+ replymsg, err = vpp.apiStream.RecvMsg()
+ if err != nil {
+ return err
+ }
+ reply2 := replymsg.(*interfaces.SwInterfaceAddDelAddressReply)
+ if err = api.RetvalToVPPApiError(reply2.Retval); err != nil {
return err
}
// Set interface to up
upReq := &interfaces.SwInterfaceSetFlags{
- SwIfIndex: createTapReply.SwIfIndex,
+ SwIfIndex: reply.SwIfIndex,
Flags: interface_types.IF_STATUS_API_FLAG_ADMIN_UP,
}
- upReply := &interfaces.SwInterfaceSetFlagsReply{}
vpp.getSuite().log("set tap interface " + tap.Name() + " up")
- if err := vpp.apiChannel.SendRequest(upReq).ReceiveReply(upReply); err != nil {
+ if err := vpp.apiStream.SendMsg(upReq); err != nil {
+ return err
+ }
+ replymsg, err = vpp.apiStream.RecvMsg()
+ if err != nil {
+ return err
+ }
+ reply3 := replymsg.(*interfaces.SwInterfaceSetFlagsReply)
+ if err = api.RetvalToVPPApiError(reply3.Retval); err != nil {
return err
}
@@ -380,7 +448,7 @@ func (vpp *VppInstance) saveLogs() {
func (vpp *VppInstance) disconnect() {
vpp.connection.Disconnect()
- vpp.apiChannel.Close()
+ vpp.apiStream.Close()
}
func (vpp *VppInstance) generateCpuConfig() string {
@@ -391,6 +459,7 @@ func (vpp *VppInstance) generateCpuConfig() string {
}
c.newStanza("cpu").
append(fmt.Sprintf("main-core %d", vpp.cpus[0]))
+ vpp.getSuite().log(fmt.Sprintf("main-core %d", vpp.cpus[0]))
workers := vpp.cpus[1:]
if len(workers) > 0 {
@@ -401,6 +470,7 @@ func (vpp *VppInstance) generateCpuConfig() string {
s = s + fmt.Sprintf("%d", workers[i])
}
c.append(fmt.Sprintf("corelist-workers %s", s))
+ vpp.getSuite().log("corelist-workers " + s)
}
return c.close().toString()
}
diff --git a/src/cmake/platform/octeon9.cmake b/src/cmake/platform/octeon9.cmake
new file mode 100644
index 00000000000..46ca7dfa64a
--- /dev/null
+++ b/src/cmake/platform/octeon9.cmake
@@ -0,0 +1,4 @@
+
+set(VPP_PLATFORM_CACHE_LINE_SIZE 128)
+set(VPP_PLATFORM_MARCH_FLAGS -march=armv8.2-a+crc+crypto)
+set(VPP_PLATFORM_BUFFER_ALIGN 128)
diff --git a/src/plugins/acl/acl_test.c b/src/plugins/acl/acl_test.c
index 8404689dc06..98803a916cb 100644
--- a/src/plugins/acl/acl_test.c
+++ b/src/plugins/acl/acl_test.c
@@ -114,7 +114,7 @@ static void vl_api_acl_interface_list_details_t_handler
int i;
vat_main_t * vam = acl_test_main.vat_main;
u8 *out = 0;
- vl_api_acl_interface_list_details_t_endian(mp);
+ vl_api_acl_interface_list_details_t_endian (mp, 0 /* from network */);
out = format(out, "sw_if_index: %d, count: %d, n_input: %d\n", mp->sw_if_index, mp->count, mp->n_input);
out = format(out, " input ");
for(i=0; i<mp->count; i++) {
@@ -141,7 +141,8 @@ static void vl_api_acl_interface_etype_whitelist_details_t_handler
int i;
vat_main_t * vam = acl_test_main.vat_main;
u8 *out = 0;
- vl_api_acl_interface_etype_whitelist_details_t_endian(mp);
+ vl_api_acl_interface_etype_whitelist_details_t_endian (
+ mp, 0 /* from network */);
out = format(out, "sw_if_index: %d, count: %d, n_input: %d\n", mp->sw_if_index, mp->count, mp->n_input);
out = format(out, " input ");
for(i=0; i<mp->count; i++) {
@@ -173,15 +174,15 @@ vl_api_acl_rule_t_pretty_format (u8 *out, vl_api_acl_rule_t * a)
inet_ntop(af, &a->src_prefix.address.un, (void *)src, sizeof(src));
inet_ntop(af, &a->dst_prefix.address.un, (void *)dst, sizeof(dst));
- out = format(out, "%s action %d src %s/%d dst %s/%d proto %d sport %d-%d dport %d-%d tcpflags %d mask %d",
- a->src_prefix.address.af ? "ipv6" : "ipv4", a->is_permit,
- src, a->src_prefix.len,
- dst, a->dst_prefix.len,
- a->proto,
- a->srcport_or_icmptype_first, a->srcport_or_icmptype_last,
- a->dstport_or_icmpcode_first, a->dstport_or_icmpcode_last,
- a->tcp_flags_value, a->tcp_flags_mask);
- return(out);
+ out = format (out,
+ "%s action %d src %s/%d dst %s/%d proto %d sport %d-%d dport "
+ "%d-%d tcpflags %d mask %d",
+ a->src_prefix.address.af ? "ipv6" : "ipv4", a->is_permit, src,
+ a->src_prefix.len, dst, a->dst_prefix.len, a->proto,
+ a->srcport_or_icmptype_first, a->srcport_or_icmptype_last,
+ a->dstport_or_icmpcode_first, a->dstport_or_icmpcode_last,
+ a->tcp_flags_value, a->tcp_flags_mask);
+ return (out);
}
@@ -191,9 +192,10 @@ static void vl_api_acl_details_t_handler
{
int i;
vat_main_t * vam = acl_test_main.vat_main;
- vl_api_acl_details_t_endian(mp);
- u8 *out = 0;
- out = format(0, "acl_index: %d, count: %d\n tag {%s}\n", mp->acl_index, mp->count, mp->tag);
+ vl_api_acl_details_t_endian (mp, 0 /* from network */);
+ u8 *out = 0;
+ out = format (0, "acl_index: %d, count: %d\n tag {%s}\n",
+ mp->acl_index, mp->count, mp->tag);
for(i=0; i<mp->count; i++) {
out = format(out, " ");
out = vl_api_acl_rule_t_pretty_format(out, &mp->r[i]);
@@ -225,8 +227,9 @@ static void vl_api_macip_acl_details_t_handler
{
int i;
vat_main_t * vam = acl_test_main.vat_main;
- vl_api_macip_acl_details_t_endian(mp);
- u8 *out = format(0,"MACIP acl_index: %d, count: %d\n tag {%s}\n", mp->acl_index, mp->count, mp->tag);
+ vl_api_macip_acl_details_t_endian (mp, 0 /* from network */);
+ u8 *out = format (0, "MACIP acl_index: %d, count: %d\n tag {%s}\n",
+ mp->acl_index, mp->count, mp->tag);
for(i=0; i<mp->count; i++) {
out = format(out, " ");
out = vl_api_macip_acl_rule_t_pretty_format(out, &mp->r[i]);
diff --git a/src/plugins/builtinurl/builtinurl.api b/src/plugins/builtinurl/builtinurl.api
index f292fd77a8e..80efa73c725 100644
--- a/src/plugins/builtinurl/builtinurl.api
+++ b/src/plugins/builtinurl/builtinurl.api
@@ -35,6 +35,7 @@ option version = "1.0.0";
*/
autoreply define builtinurl_enable {
+ option deprecated="incorporated in http_static plugin";
/* Client identifier, set from api_main.my_client_index */
u32 client_index;
diff --git a/src/plugins/dev_iavf/port.c b/src/plugins/dev_iavf/port.c
index 982436d9b45..90e81e960c4 100644
--- a/src/plugins/dev_iavf/port.c
+++ b/src/plugins/dev_iavf/port.c
@@ -42,29 +42,35 @@ iavf_port_vlan_strip_disable (vlib_main_t *vm, vnet_dev_port_t *port)
vnet_dev_t *dev = port->dev;
iavf_port_t *ap = vnet_dev_get_port_data (port);
virtchnl_vlan_caps_t vc;
- vnet_dev_rv_t rv;
+ vnet_dev_rv_t rv = VNET_DEV_ERR_NOT_SUPPORTED;
u32 outer, inner;
const u32 mask = VIRTCHNL_VLAN_ETHERTYPE_8100;
- if ((ap->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN_V2) == 0)
- return iavf_vc_op_disable_vlan_stripping (vm, dev);
+ if (ap->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN_V2)
+ {
+ if ((rv = iavf_vc_op_get_offload_vlan_v2_caps (vm, dev, &vc)))
+ return rv;
- if ((rv = iavf_vc_op_get_offload_vlan_v2_caps (vm, dev, &vc)))
- return rv;
+ outer = vc.offloads.stripping_support.outer;
+ inner = vc.offloads.stripping_support.inner;
- outer = vc.offloads.stripping_support.outer;
- inner = vc.offloads.stripping_support.inner;
+ outer = outer & VIRTCHNL_VLAN_TOGGLE ? outer & mask : 0;
+ inner = inner & VIRTCHNL_VLAN_TOGGLE ? inner & mask : 0;
- outer = outer & VIRTCHNL_VLAN_TOGGLE ? outer & mask : 0;
- inner = inner & VIRTCHNL_VLAN_TOGGLE ? inner & mask : 0;
+ virtchnl_vlan_setting_t vs = {
+ .vport_id = ap->vsi_id,
+ .outer_ethertype_setting = outer,
+ .inner_ethertype_setting = inner,
+ };
- virtchnl_vlan_setting_t vs = {
- .vport_id = ap->vsi_id,
- .outer_ethertype_setting = outer,
- .inner_ethertype_setting = inner,
- };
+ if ((rv = iavf_vc_op_disable_vlan_stripping_v2 (vm, dev, &vs)))
+ return rv;
+ }
- return iavf_vc_op_disable_vlan_stripping_v2 (vm, dev, &vs);
+ if (ap->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN)
+ return iavf_vc_op_disable_vlan_stripping (vm, dev);
+
+ return rv;
}
vnet_dev_rv_t
@@ -275,7 +281,12 @@ iavf_port_init (vlib_main_t *vm, vnet_dev_port_t *port)
u64_bit_set (&ap->intr_mode_per_rxq_bitmap, q->queue_id, 1);
if ((rv = iavf_port_vlan_strip_disable (vm, port)))
- return rv;
+ {
+ if (rv == VNET_DEV_ERR_NOT_SUPPORTED)
+ log_warn (port->dev, "device doesn't support vlan stripping");
+ else
+ return rv;
+ }
if ((rv = iavf_port_init_rss (vm, port)))
return rv;
diff --git a/src/plugins/dev_octeon/CMakeLists.txt b/src/plugins/dev_octeon/CMakeLists.txt
index e8abf1a3389..0f6b32bbecd 100644
--- a/src/plugins/dev_octeon/CMakeLists.txt
+++ b/src/plugins/dev_octeon/CMakeLists.txt
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright(c) 2022 Cisco Systems, Inc.
-if (NOT VPP_PLATFORM_NAME STREQUAL "octeon10")
+if (NOT VPP_PLATFORM_NAME STREQUAL "octeon10" AND NOT VPP_PLATFORM_NAME STREQUAL "octeon9")
return()
endif()
@@ -21,6 +21,10 @@ endif()
include_directories (${OCTEON_ROC_DIR}/)
+if (VPP_PLATFORM_NAME STREQUAL "octeon9")
+ add_compile_definitions(PLATFORM_OCTEON9)
+endif()
+
add_vpp_plugin(dev_octeon
SOURCES
init.c
diff --git a/src/plugins/dev_octeon/init.c b/src/plugins/dev_octeon/init.c
index 8c5ed95b062..aacc18415c2 100644
--- a/src/plugins/dev_octeon/init.c
+++ b/src/plugins/dev_octeon/init.c
@@ -51,7 +51,8 @@ static struct
}
_ (0xa063, RVU_PF, "Marvell Octeon Resource Virtualization Unit PF"),
- _ (0xa0f8, RVU_VF, "Marvell Octeon Resource Virtualization Unit VF"),
+ _ (0xa064, RVU_VF, "Marvell Octeon Resource Virtualization Unit VF"),
+ _ (0xa0f8, LBK_VF, "Marvell Octeon Loopback Unit VF"),
_ (0xa0f7, SDP_VF, "Marvell Octeon System DPI Packet Interface Unit VF"),
_ (0xa0f3, CPT_VF, "Marvell Octeon Cryptographic Accelerator Unit VF"),
#undef _
@@ -244,6 +245,7 @@ oct_init (vlib_main_t *vm, vnet_dev_t *dev)
{
case OCT_DEVICE_TYPE_RVU_PF:
case OCT_DEVICE_TYPE_RVU_VF:
+ case OCT_DEVICE_TYPE_LBK_VF:
case OCT_DEVICE_TYPE_SDP_VF:
return oct_init_nix (vm, dev);
diff --git a/src/plugins/dev_octeon/octeon.h b/src/plugins/dev_octeon/octeon.h
index 92ec953ed23..e43cde0a35f 100644
--- a/src/plugins/dev_octeon/octeon.h
+++ b/src/plugins/dev_octeon/octeon.h
@@ -22,6 +22,7 @@ typedef enum
OCT_DEVICE_TYPE_UNKNOWN = 0,
OCT_DEVICE_TYPE_RVU_PF,
OCT_DEVICE_TYPE_RVU_VF,
+ OCT_DEVICE_TYPE_LBK_VF,
OCT_DEVICE_TYPE_SDP_VF,
OCT_DEVICE_TYPE_CPT_VF,
} __clib_packed oct_device_type_t;
@@ -162,7 +163,8 @@ vnet_dev_rv_t oct_flow_query (vlib_main_t *, vnet_dev_port_t *, u32, uword,
_ (AURA_BATCH_ALLOC_ISSUE_FAIL, aura_batch_alloc_issue_fail, ERROR, \
"aura batch alloc issue failed") \
_ (AURA_BATCH_ALLOC_NOT_READY, aura_batch_alloc_not_ready, ERROR, \
- "aura batch alloc not ready")
+ "aura batch alloc not ready") \
+ _ (MTU_EXCEEDED, mtu_exceeded, ERROR, "mtu exceeded")
typedef enum
{
diff --git a/src/plugins/dev_octeon/port.c b/src/plugins/dev_octeon/port.c
index d5f78301adf..2ed278d8841 100644
--- a/src/plugins/dev_octeon/port.c
+++ b/src/plugins/dev_octeon/port.c
@@ -203,7 +203,8 @@ oct_port_poll (vlib_main_t *vm, vnet_dev_port_t *port)
if (cd->speed != link_info.speed)
{
changes.change.link_speed = 1;
- changes.link_speed = link_info.speed;
+ /* Convert to Kbps */
+ changes.link_speed = link_info.speed * 1000;
cd->speed = link_info.speed;
}
@@ -416,6 +417,44 @@ oct_op_config_promisc_mode (vlib_main_t *vm, vnet_dev_port_t *port, int enable)
return VNET_DEV_OK;
}
+static vnet_dev_rv_t
+oct_port_add_del_eth_addr (vlib_main_t *vm, vnet_dev_port_t *port,
+ vnet_dev_hw_addr_t *addr, int is_add,
+ int is_primary)
+{
+ vnet_dev_t *dev = port->dev;
+ oct_device_t *cd = vnet_dev_get_data (dev);
+ struct roc_nix *nix = cd->nix;
+ vnet_dev_rv_t rv = VNET_DEV_OK;
+
+ i32 rrv;
+
+ if (is_primary)
+ {
+ if (is_add)
+ {
+ /* Update mac address at NPC */
+ rrv = roc_nix_npc_mac_addr_set (nix, (u8 *) addr);
+ if (rrv)
+ rv = oct_roc_err (dev, rrv, "roc_nix_npc_mac_addr_set() failed");
+
+ /* Update mac address at CGX for PFs only */
+ if (!roc_nix_is_vf_or_sdp (nix))
+ {
+ rrv = roc_nix_mac_addr_set (nix, (u8 *) addr);
+ if (rrv)
+ {
+ /* Rollback to previous mac address */
+ roc_nix_npc_mac_addr_set (nix,
+ (u8 *) &port->primary_hw_addr);
+ rv = oct_roc_err (dev, rrv, "roc_nix_mac_addr_set() failed");
+ }
+ }
+ }
+ }
+ return rv;
+}
+
vnet_dev_rv_t
oct_port_cfg_change_validate (vlib_main_t *vm, vnet_dev_port_t *port,
vnet_dev_port_cfg_change_req_t *req)
@@ -465,6 +504,9 @@ oct_port_cfg_change (vlib_main_t *vm, vnet_dev_port_t *port,
break;
case VNET_DEV_PORT_CFG_CHANGE_PRIMARY_HW_ADDR:
+ rv = oct_port_add_del_eth_addr (vm, port, &req->addr,
+ /* is_add */ 1,
+ /* is_primary */ 1);
break;
case VNET_DEV_PORT_CFG_ADD_SECONDARY_HW_ADDR:
diff --git a/src/plugins/dev_octeon/roc_helper.c b/src/plugins/dev_octeon/roc_helper.c
index f10c2cb578b..16e0a871a9d 100644
--- a/src/plugins/dev_octeon/roc_helper.c
+++ b/src/plugins/dev_octeon/roc_helper.c
@@ -49,6 +49,12 @@ oct_plt_get_thread_index (void)
return __os_thread_index;
}
+static u64
+oct_plt_get_cache_line_size (void)
+{
+ return CLIB_CACHE_LINE_BYTES;
+}
+
static void
oct_drv_physmem_free (vlib_main_t *vm, void *mem)
{
@@ -178,4 +184,5 @@ oct_plt_init_param_t oct_plt_init_param = {
.oct_plt_spinlock_unlock = oct_plt_spinlock_unlock,
.oct_plt_spinlock_trylock = oct_plt_spinlock_trylock,
.oct_plt_get_thread_index = oct_plt_get_thread_index,
+ .oct_plt_get_cache_line_size = oct_plt_get_cache_line_size,
};
diff --git a/src/plugins/dev_octeon/rx_node.c b/src/plugins/dev_octeon/rx_node.c
index 997f1356199..1f8d5d93fa3 100644
--- a/src/plugins/dev_octeon/rx_node.c
+++ b/src/plugins/dev_octeon/rx_node.c
@@ -165,6 +165,38 @@ oct_rx_batch (vlib_main_t *vm, oct_rx_node_ctx_t *ctx,
return n;
}
+#ifdef PLATFORM_OCTEON9
+static_always_inline u32
+oct_rxq_refill (vlib_main_t *vm, vnet_dev_rx_queue_t *rxq, u16 n_refill)
+{
+ u32 n_alloc, n_free;
+ u32 buffer_indices[n_refill];
+ vlib_buffer_t *buffers[n_refill];
+ u8 bpi = vnet_dev_get_rx_queue_buffer_pool_index (rxq);
+ oct_rxq_t *crq = vnet_dev_get_rx_queue_data (rxq);
+ u64 aura = roc_npa_aura_handle_to_aura (crq->aura_handle);
+ const uint64_t addr =
+ roc_npa_aura_handle_to_base (crq->aura_handle) + NPA_LF_AURA_OP_FREE0;
+
+ if (n_refill < 256)
+ return 0;
+
+ n_alloc = vlib_buffer_alloc (vm, buffer_indices, n_refill);
+ if (PREDICT_FALSE (n_alloc < n_refill))
+ goto alloc_fail;
+
+ vlib_get_buffers (vm, buffer_indices, (vlib_buffer_t **) buffers, n_alloc);
+
+ for (n_free = 0; n_free < n_alloc; n_free++)
+ roc_store_pair ((u64) buffers[n_free], aura, addr);
+
+ return n_alloc;
+
+alloc_fail:
+ vlib_buffer_unalloc_to_pool (vm, buffer_indices, n_alloc, bpi);
+ return 0;
+}
+#else
static_always_inline void
oct_rxq_refill_batch (vlib_main_t *vm, u64 lmt_id, u64 addr,
oct_npa_lf_aura_batch_free_line_t *lines, u32 *bi,
@@ -260,6 +292,7 @@ oct_rxq_refill (vlib_main_t *vm, vnet_dev_rx_queue_t *rxq, u16 n_refill)
return n_enq;
}
+#endif
static_always_inline void
oct_rx_trace (vlib_main_t *vm, vlib_node_runtime_t *node,
diff --git a/src/plugins/dev_octeon/tx_node.c b/src/plugins/dev_octeon/tx_node.c
index ce8709959a5..0907493814d 100644
--- a/src/plugins/dev_octeon/tx_node.c
+++ b/src/plugins/dev_octeon/tx_node.c
@@ -22,13 +22,54 @@ typedef struct
u32 n_tx_bytes;
u32 n_drop;
vlib_buffer_t *drop[VLIB_FRAME_SIZE];
+ u32 n_exd_mtu;
+ vlib_buffer_t *exd_mtu[VLIB_FRAME_SIZE];
u32 batch_alloc_not_ready;
u32 batch_alloc_issue_fail;
+ int max_pkt_len;
u16 lmt_id;
u64 lmt_ioaddr;
lmt_line_t *lmt_lines;
} oct_tx_ctx_t;
+#ifdef PLATFORM_OCTEON9
+static_always_inline u32
+oct_batch_free (vlib_main_t *vm, oct_tx_ctx_t *ctx, vnet_dev_tx_queue_t *txq)
+{
+ oct_txq_t *ctq = vnet_dev_get_tx_queue_data (txq);
+ u16 off = ctq->hdr_off;
+ u64 ah = ctq->aura_handle;
+ u32 n_freed = 0, n;
+
+ ah = ctq->aura_handle;
+
+ if ((n = roc_npa_aura_op_available (ah)) >= 32)
+ {
+ u64 buffers[n];
+ u32 bi[n];
+
+ n_freed = roc_npa_aura_op_bulk_alloc (ah, buffers, n, 0, 1);
+ vlib_get_buffer_indices_with_offset (vm, (void **) &buffers, bi, n_freed,
+ off);
+ vlib_buffer_free_no_next (vm, bi, n_freed);
+ }
+
+ return n_freed;
+}
+
+static_always_inline void
+oct_lmt_copy (void *lmt_addr, u64 io_addr, void *desc, u64 dwords)
+{
+ u64 lmt_status;
+
+ do
+ {
+ roc_lmt_mov_seg (lmt_addr, desc, dwords);
+ lmt_status = roc_lmt_submit_ldeor (io_addr);
+ }
+ while (lmt_status == 0);
+}
+#else
static_always_inline u32
oct_batch_free (vlib_main_t *vm, oct_tx_ctx_t *ctx, vnet_dev_tx_queue_t *txq)
{
@@ -130,6 +171,7 @@ oct_batch_free (vlib_main_t *vm, oct_tx_ctx_t *ctx, vnet_dev_tx_queue_t *txq)
return n_freed;
}
+#endif
static_always_inline u8
oct_tx_enq1 (vlib_main_t *vm, oct_tx_ctx_t *ctx, vlib_buffer_t *b,
@@ -149,6 +191,17 @@ oct_tx_enq1 (vlib_main_t *vm, oct_tx_ctx_t *ctx, vlib_buffer_t *b,
},
};
+ if (PREDICT_FALSE (vlib_buffer_length_in_chain (vm, b) > ctx->max_pkt_len))
+ {
+ ctx->exd_mtu[ctx->n_exd_mtu++] = b;
+ return 0;
+ }
+
+#ifdef PLATFORM_OCTEON9
+ /* Override line for Octeon9 */
+ line = ctx->lmt_lines;
+#endif
+
if (!simple && flags & VLIB_BUFFER_NEXT_PRESENT)
{
u8 n_tail_segs = 0;
@@ -229,8 +282,12 @@ oct_tx_enq1 (vlib_main_t *vm, oct_tx_ctx_t *ctx, vlib_buffer_t *b,
t->sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_TX];
}
+#ifdef PLATFORM_OCTEON9
+ oct_lmt_copy (line, ctx->lmt_ioaddr, &d, n_dwords);
+#else
for (u32 i = 0; i < n_dwords; i++)
line->dwords[i] = d.as_u128[i];
+#endif
*dpl = n_dwords;
*n = *n + 1;
@@ -243,7 +300,7 @@ oct_tx_enq16 (vlib_main_t *vm, oct_tx_ctx_t *ctx, vnet_dev_tx_queue_t *txq,
vlib_buffer_t **b, u32 n_pkts, int trace)
{
u8 dwords_per_line[16], *dpl = dwords_per_line;
- u64 lmt_arg, ioaddr, n_lines;
+ u64 __attribute__ ((unused)) lmt_arg, ioaddr, n_lines;
u32 n_left, or_flags_16 = 0, n = 0;
const u32 not_simple_flags =
VLIB_BUFFER_NEXT_PRESENT | VNET_BUFFER_F_OFFLOAD;
@@ -322,6 +379,7 @@ oct_tx_enq16 (vlib_main_t *vm, oct_tx_ctx_t *ctx, vnet_dev_tx_queue_t *txq,
if (PREDICT_FALSE (!n_lines))
return n_pkts;
+#ifndef PLATFORM_OCTEON9
if (PREDICT_FALSE (or_flags_16 & VLIB_BUFFER_NEXT_PRESENT))
{
dpl = dwords_per_line;
@@ -350,6 +408,7 @@ oct_tx_enq16 (vlib_main_t *vm, oct_tx_ctx_t *ctx, vnet_dev_tx_queue_t *txq,
}
roc_lmt_submit_steorl (lmt_arg, ioaddr);
+#endif
return n_pkts;
}
@@ -360,11 +419,17 @@ VNET_DEV_NODE_FN (oct_tx_node)
vnet_dev_tx_node_runtime_t *rt = vnet_dev_get_tx_node_runtime (node);
vnet_dev_tx_queue_t *txq = rt->tx_queue;
oct_txq_t *ctq = vnet_dev_get_tx_queue_data (txq);
+ vnet_dev_t *dev = txq->port->dev;
+ oct_device_t *cd = vnet_dev_get_data (dev);
u32 node_index = node->node_index;
u32 *from = vlib_frame_vector_args (frame);
u32 n, n_enq, n_left, n_pkts = frame->n_vectors;
vlib_buffer_t *buffers[VLIB_FRAME_SIZE + 8], **b = buffers;
+#ifdef PLATFORM_OCTEON9
+ u64 lmt_id = 0;
+#else
u64 lmt_id = vm->thread_index << ROC_LMT_LINES_PER_CORE_LOG2;
+#endif
oct_tx_ctx_t ctx = {
.node = node,
@@ -373,6 +438,7 @@ VNET_DEV_NODE_FN (oct_tx_node)
.sq = ctq->sq.qid,
.sizem1 = 1,
},
+ .max_pkt_len = roc_nix_max_pkt_len (cd->nix),
.lmt_id = lmt_id,
.lmt_ioaddr = ctq->io_addr,
.lmt_lines = ctq->lmt_addr + (lmt_id << ROC_LMT_LINE_SIZE_LOG2),
@@ -406,7 +472,7 @@ VNET_DEV_NODE_FN (oct_tx_node)
n += oct_tx_enq16 (vm, &ctx, txq, b, n_left, /* trace */ 0);
}
- ctq->n_enq = n_enq + n - ctx.n_drop;
+ ctq->n_enq = n_enq + n - ctx.n_drop - ctx.n_exd_mtu;
if (n < n_pkts)
{
@@ -421,6 +487,10 @@ VNET_DEV_NODE_FN (oct_tx_node)
vlib_error_count (vm, node->node_index, OCT_TX_NODE_CTR_CHAIN_TOO_LONG,
ctx.n_drop);
+ if (PREDICT_FALSE (ctx.n_exd_mtu))
+ vlib_error_count (vm, node->node_index, OCT_TX_NODE_CTR_MTU_EXCEEDED,
+ ctx.n_exd_mtu);
+
if (ctx.batch_alloc_not_ready)
vlib_error_count (vm, node_index,
OCT_TX_NODE_CTR_AURA_BATCH_ALLOC_NOT_READY,
@@ -441,5 +511,13 @@ VNET_DEV_NODE_FN (oct_tx_node)
n_pkts -= ctx.n_drop;
}
+ if (PREDICT_FALSE (ctx.n_exd_mtu))
+ {
+ u32 bi[VLIB_FRAME_SIZE];
+ vlib_get_buffer_indices (vm, ctx.exd_mtu, bi, ctx.n_exd_mtu);
+ vlib_buffer_free (vm, bi, ctx.n_exd_mtu);
+ n_pkts -= ctx.n_exd_mtu;
+ }
+
return n_pkts;
}
diff --git a/src/plugins/dpdk/device/cli.c b/src/plugins/dpdk/device/cli.c
index c838800deb4..77f9a27f97b 100644
--- a/src/plugins/dpdk/device/cli.c
+++ b/src/plugins/dpdk/device/cli.c
@@ -89,12 +89,18 @@ show_dpdk_physmem (vlib_main_t * vm, unformat_input_t * input,
vlib_cli_command_t * cmd)
{
clib_error_t *err = 0;
- u32 pipe_max_size;
int fds[2];
u8 *s = 0;
int n, n_try;
FILE *f;
+ /*
+ * XXX: Pipes on FreeBSD grow dynamically up to 64KB (FreeBSD 15), don't
+ * manually tweak this value on FreeBSD at the moment.
+ */
+#ifdef __linux__
+ u32 pipe_max_size;
+
err = clib_sysfs_read ("/proc/sys/fs/pipe-max-size", "%u", &pipe_max_size);
if (err)
@@ -112,6 +118,7 @@ show_dpdk_physmem (vlib_main_t * vm, unformat_input_t * input,
err = clib_error_return_unix (0, "fcntl(F_SETPIPE_SZ)");
goto error;
}
+#endif /* __linux__ */
if (fcntl (fds[0], F_SETFL, O_NONBLOCK) == -1)
{
diff --git a/src/plugins/dpdk/device/init.c b/src/plugins/dpdk/device/init.c
index 2d038b907bf..e416efe2e4d 100644
--- a/src/plugins/dpdk/device/init.c
+++ b/src/plugins/dpdk/device/init.c
@@ -1045,12 +1045,14 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input)
dpdk_main_t *dm = &dpdk_main;
clib_error_t *error = 0;
dpdk_config_main_t *conf = &dpdk_config_main;
- vlib_thread_main_t *tm = vlib_get_thread_main ();
dpdk_device_config_t *devconf;
vlib_pci_addr_t pci_addr = { 0 };
vlib_vmbus_addr_t vmbus_addr = { 0 };
unformat_input_t sub_input;
+#ifdef __linux
+ vlib_thread_main_t *tm = vlib_get_thread_main ();
uword default_hugepage_sz, x;
+#endif /* __linux__ */
u8 *s, *tmp = 0;
int ret, i;
int num_whitelisted = 0;
@@ -1258,6 +1260,11 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input)
{
vec_add1 (conf->eal_init_args, (u8 *) "--in-memory");
+#ifdef __linux__
+ /*
+ * FreeBSD performs huge page prealloc through a dedicated kernel mode
+ * this process is only required on Linux.
+ */
default_hugepage_sz = clib_mem_get_default_hugepage_size ();
clib_bitmap_foreach (x, tm->cpu_socket_bitmap)
@@ -1272,6 +1279,7 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input)
if ((e = clib_sysfs_prealloc_hugepages(x, 0, n_pages)))
clib_error_report (e);
}
+#endif /* __linux__ */
}
/* on/off dpdk's telemetry thread */
@@ -1280,6 +1288,7 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input)
vec_add1 (conf->eal_init_args, (u8 *) "--no-telemetry");
}
+#ifdef __linux__
if (!file_prefix)
{
tmp = format (0, "--file-prefix%c", 0);
@@ -1287,6 +1296,7 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input)
tmp = format (0, "vpp%c", 0);
vec_add1 (conf->eal_init_args, tmp);
}
+#endif
if (no_pci == 0 && geteuid () == 0)
dpdk_bind_devices_to_uio (conf);
diff --git a/src/plugins/hs_apps/http_cli.c b/src/plugins/hs_apps/http_cli.c
index 5d4d49c0fba..f42f65342c3 100644
--- a/src/plugins/hs_apps/http_cli.c
+++ b/src/plugins/hs_apps/http_cli.c
@@ -323,6 +323,13 @@ hcs_ts_rx_callback (session_t *ts)
return 0;
}
+ if (msg.data.len == 0)
+ {
+ hs->tx_buf = 0;
+ start_send_data (hs, HTTP_STATUS_BAD_REQUEST);
+ return 0;
+ }
+
/* send the command to a new/recycled vlib process */
vec_validate (args.buf, msg.data.len - 1);
rv = svm_fifo_dequeue (ts->rx_fifo, msg.data.len, args.buf);
diff --git a/src/plugins/hs_apps/http_client_cli.c b/src/plugins/hs_apps/http_client_cli.c
index 085a2b69bf7..a99169bafea 100644
--- a/src/plugins/hs_apps/http_client_cli.c
+++ b/src/plugins/hs_apps/http_client_cli.c
@@ -13,11 +13,9 @@
* limitations under the License.
*/
-#include <vnet/session/application.h>
#include <vnet/session/application_interface.h>
#include <vnet/session/session.h>
#include <http/http.h>
-#include <hs_apps/http_cli.h>
#define HCC_DEBUG 0
@@ -68,6 +66,8 @@ typedef struct
typedef enum
{
HCC_REPLY_RECEIVED = 100,
+ HCC_TRANSPORT_CLOSED,
+ HCC_CONNECT_FAILED,
} hcc_cli_signal_t;
static hcc_main_t hcc_main;
@@ -136,6 +136,8 @@ hcc_ts_connected_callback (u32 app_index, u32 hc_index, session_t *as,
{
clib_warning ("connected error: hc_index(%d): %U", hc_index,
format_session_error, err);
+ vlib_process_signal_event_mt (hcm->vlib_main, hcm->cli_node_index,
+ HCC_CONNECT_FAILED, 0);
return -1;
}
@@ -273,6 +275,17 @@ hcc_ts_cleanup_callback (session_t *s, session_cleanup_ntf_t ntf)
hcc_session_free (s->thread_index, hs);
}
+static void
+hcc_ts_transport_closed (session_t *s)
+{
+ hcc_main_t *hcm = &hcc_main;
+
+ HCC_DBG ("transport closed");
+
+ vlib_process_signal_event_mt (hcm->vlib_main, hcm->cli_node_index,
+ HCC_TRANSPORT_CLOSED, 0);
+}
+
static session_cb_vft_t hcc_session_cb_vft = {
.session_accept_callback = hcc_ts_accept_callback,
.session_disconnect_callback = hcc_ts_disconnect_callback,
@@ -281,6 +294,7 @@ static session_cb_vft_t hcc_session_cb_vft = {
.builtin_app_tx_callback = hcc_ts_tx_callback,
.session_reset_callback = hcc_ts_reset_callback,
.session_cleanup_callback = hcc_ts_cleanup_callback,
+ .session_transport_closed_callback = hcc_ts_transport_closed,
};
static clib_error_t *
@@ -411,6 +425,12 @@ hcc_run (vlib_main_t *vm, int print_output)
vlib_cli_output (vm, "%v", hcm->http_response);
vec_free (hcm->http_response);
break;
+ case HCC_TRANSPORT_CLOSED:
+ err = clib_error_return (0, "error, transport closed");
+ break;
+ case HCC_CONNECT_FAILED:
+ err = clib_error_return (0, "failed to connect");
+ break;
default:
err = clib_error_return (0, "unexpected event %d", event_type);
break;
diff --git a/src/plugins/http/http.c b/src/plugins/http/http.c
index 37a6de71bc7..893dd877c29 100644
--- a/src/plugins/http/http.c
+++ b/src/plugins/http/http.c
@@ -267,17 +267,21 @@ http_ts_connected_callback (u32 http_app_index, u32 ho_hc_index, session_t *ts,
app_worker_t *app_wrk;
int rv;
+ ho_hc = http_conn_get_w_thread (ho_hc_index, 0);
+ ASSERT (ho_hc->state == HTTP_CONN_STATE_CONNECTING);
+
if (err)
{
- clib_warning ("ERROR: %d", err);
+ clib_warning ("half-open hc index %d, error: %U", ho_hc_index,
+ format_session_error, err);
+ app_wrk = app_worker_get_if_valid (ho_hc->h_pa_wrk_index);
+ if (app_wrk)
+ app_worker_connect_notify (app_wrk, 0, err, ho_hc->h_pa_app_api_ctx);
return 0;
}
new_hc_index = http_conn_alloc_w_thread (ts->thread_index);
hc = http_conn_get_w_thread (new_hc_index, ts->thread_index);
- ho_hc = http_conn_get_w_thread (ho_hc_index, 0);
-
- ASSERT (ho_hc->state == HTTP_CONN_STATE_CONNECTING);
clib_memcpy_fast (hc, ho_hc, sizeof (*hc));
@@ -378,7 +382,7 @@ static const char *http_response_template = "HTTP/1.1 %s\r\n"
"Content-Length: %lu\r\n\r\n";
static const char *http_request_template = "GET %s HTTP/1.1\r\n"
- "User-Agent: VPP HTTP client\r\n"
+ "User-Agent: %s\r\n"
"Accept: */*\r\n";
static u32
@@ -521,17 +525,19 @@ http_state_wait_server_reply (http_conn_t *hc, transport_send_params_t *sp)
http_msg_t msg = {};
app_worker_t *app_wrk;
session_t *as;
- http_status_code_t ec;
rv = http_read_message (hc);
/* Nothing yet, wait for data or timer expire */
if (rv)
- return HTTP_SM_STOP;
+ {
+ HTTP_DBG (1, "no data to deq");
+ return HTTP_SM_STOP;
+ }
if (vec_len (hc->rx_buf) < 8)
{
- ec = HTTP_STATUS_BAD_REQUEST;
+ clib_warning ("response buffer too short");
goto error;
}
@@ -547,9 +553,7 @@ http_state_wait_server_reply (http_conn_t *hc, transport_send_params_t *sp)
if (rv)
{
clib_warning ("failed to parse http reply");
- session_transport_closing_notify (&hc->connection);
- http_disconnect_transport (hc);
- return -1;
+ goto error;
}
msg.data.len = content_length;
u32 dlen = vec_len (hc->rx_buf) - hc->rx_buf_offset;
@@ -592,17 +596,14 @@ http_state_wait_server_reply (http_conn_t *hc, transport_send_params_t *sp)
}
else
{
- HTTP_DBG (0, "Unknown http method %v", hc->rx_buf);
- ec = HTTP_STATUS_METHOD_NOT_ALLOWED;
+ clib_warning ("Unknown http method %v", hc->rx_buf);
goto error;
}
error:
-
- http_send_error (hc, ec);
session_transport_closing_notify (&hc->connection);
+ session_transport_closed_notify (&hc->connection);
http_disconnect_transport (hc);
-
return HTTP_SM_ERROR;
}
@@ -743,6 +744,10 @@ http_state_wait_app_reply (http_conn_t *hc, transport_send_params_t *sp)
switch (msg.code)
{
+ case HTTP_STATUS_NOT_FOUND:
+ case HTTP_STATUS_METHOD_NOT_ALLOWED:
+ case HTTP_STATUS_BAD_REQUEST:
+ case HTTP_STATUS_INTERNAL_ERROR:
case HTTP_STATUS_OK:
header =
format (0, http_response_template, http_status_code_str[msg.code],
@@ -763,6 +768,7 @@ http_state_wait_app_reply (http_conn_t *hc, transport_send_params_t *sp)
/* Location: http(s)://new-place already queued up as data */
break;
default:
+ clib_warning ("unsupported status code: %d", msg.code);
return HTTP_SM_ERROR;
}
@@ -818,11 +824,18 @@ http_state_wait_app_method (http_conn_t *hc, transport_send_params_t *sp)
goto error;
}
+ /* currently we support only GET method */
+ if (msg.method_type != HTTP_REQ_GET)
+ {
+ clib_warning ("unsupported method %d", msg.method_type);
+ goto error;
+ }
+
vec_validate (buf, msg.data.len - 1);
rv = svm_fifo_dequeue (as->tx_fifo, msg.data.len, buf);
ASSERT (rv == msg.data.len);
- request = format (0, http_request_template, buf);
+ request = format (0, http_request_template, buf, hc->app_name);
offset = http_send_data (hc, request, vec_len (request), 0);
if (offset != vec_len (request))
{
@@ -838,7 +851,9 @@ http_state_wait_app_method (http_conn_t *hc, transport_send_params_t *sp)
return HTTP_SM_STOP;
error:
+ svm_fifo_dequeue_drop_all (as->tx_fifo);
session_transport_closing_notify (&hc->connection);
+ session_transport_closed_notify (&hc->connection);
http_disconnect_transport (hc);
return HTTP_SM_ERROR;
}
@@ -897,6 +912,13 @@ http_state_client_io_more_data (http_conn_t *hc, transport_send_params_t *sp)
hc->to_recv -= rv;
HTTP_DBG (1, "drained %d from ts; remains %d", rv, hc->to_recv);
+ if (hc->to_recv == 0)
+ {
+ hc->rx_buf_offset = 0;
+ vec_reset_length (hc->rx_buf);
+ http_state_change (hc, HTTP_STATE_WAIT_APP_METHOD);
+ }
+
app_wrk = app_worker_get_if_valid (as->app_wrk_index);
if (app_wrk)
app_worker_rx_notify (app_wrk, as);
@@ -1151,6 +1173,11 @@ http_transport_connect (transport_endpoint_cfg_t *tep)
hc->state = HTTP_CONN_STATE_CONNECTING;
cargs->api_context = hc_index;
+ if (vec_len (app->name))
+ hc->app_name = vec_dup (app->name);
+ else
+ hc->app_name = format (0, "VPP HTTP client");
+
HTTP_DBG (1, "hc ho_index %x", hc_index);
if ((error = vnet_connect (cargs)))
@@ -1248,7 +1275,11 @@ http_transport_close (u32 hc_index, u32 thread_index)
http_disconnect_transport (hc);
return;
}
-
+ else if (hc->state == HTTP_CONN_STATE_CLOSED)
+ {
+ HTTP_DBG (1, "nothing to do, already closed");
+ return;
+ }
as = session_get_from_handle (hc->h_pa_session_handle);
/* Nothing more to send, confirm close */
diff --git a/src/plugins/http/http.h b/src/plugins/http/http.h
index c9912dd6db8..7fbefd667f4 100644
--- a/src/plugins/http/http.h
+++ b/src/plugins/http/http.h
@@ -277,6 +277,74 @@ http_state_is_tx_valid (http_conn_t *hc)
state == HTTP_STATE_WAIT_APP_METHOD);
}
+/**
+ * Remove dot segments from path (RFC3986 section 5.2.4)
+ *
+ * @param path Path to sanitize.
+ *
+ * @return New vector with sanitized path.
+ *
+ * The caller is always responsible to free the returned vector.
+ */
+always_inline u8 *
+http_path_remove_dot_segments (u8 *path)
+{
+ u32 *segments = 0, *segments_len = 0, segment_len;
+ u8 *new_path = 0;
+ int i, ii;
+
+ if (!path)
+ return vec_new (u8, 0);
+
+ segments = vec_new (u32, 1);
+ /* first segment */
+ segments[0] = 0;
+ /* find all segments */
+ for (i = 1; i < (vec_len (path) - 1); i++)
+ {
+ if (path[i] == '/')
+ vec_add1 (segments, i + 1);
+ }
+ /* dummy tail */
+ vec_add1 (segments, vec_len (path));
+
+ /* scan all segments for "." and ".." */
+ segments_len = vec_new (u32, vec_len (segments) - 1);
+ for (i = 0; i < vec_len (segments_len); i++)
+ {
+ segment_len = segments[i + 1] - segments[i];
+ if (segment_len == 2 && path[segments[i]] == '.')
+ segment_len = 0;
+ else if (segment_len == 3 && path[segments[i]] == '.' &&
+ path[segments[i] + 1] == '.')
+ {
+ segment_len = 0;
+ /* remove parent (if any) */
+ for (ii = i - 1; ii >= 0; ii--)
+ {
+ if (segments_len[ii])
+ {
+ segments_len[ii] = 0;
+ break;
+ }
+ }
+ }
+ segments_len[i] = segment_len;
+ }
+
+ /* we might end with empty path, so return at least empty vector */
+ new_path = vec_new (u8, 0);
+ /* append all valid segments */
+ for (i = 0; i < vec_len (segments_len); i++)
+ {
+ if (segments_len[i])
+ vec_add (new_path, path + segments[i], segments_len[i]);
+ }
+ vec_free (segments);
+ vec_free (segments_len);
+ return new_path;
+}
+
#endif /* SRC_PLUGINS_HTTP_HTTP_H_ */
/*
diff --git a/src/plugins/http_static/static_server.c b/src/plugins/http_static/static_server.c
index 040cdca9d7a..f433238dcb1 100644
--- a/src/plugins/http_static/static_server.c
+++ b/src/plugins/http_static/static_server.c
@@ -357,7 +357,7 @@ try_file_handler (hss_main_t *hsm, hss_session_t *hs, http_req_method_t rt,
u8 *request)
{
http_status_code_t sc = HTTP_STATUS_OK;
- u8 *path;
+ u8 *path, *sanitized_path;
u32 ce_index;
http_content_type_t type;
@@ -367,6 +367,9 @@ try_file_handler (hss_main_t *hsm, hss_session_t *hs, http_req_method_t rt,
type = content_type_from_request (request);
+ /* Remove dot segments to prevent path traversal */
+ sanitized_path = http_path_remove_dot_segments (request);
+
/*
* Construct the file to open
* Browsers are capable of sporadically including a leading '/'
@@ -374,9 +377,9 @@ try_file_handler (hss_main_t *hsm, hss_session_t *hs, http_req_method_t rt,
if (!request)
path = format (0, "%s%c", hsm->www_root, 0);
else if (request[0] == '/')
- path = format (0, "%s%s%c", hsm->www_root, request, 0);
+ path = format (0, "%s%s%c", hsm->www_root, sanitized_path, 0);
else
- path = format (0, "%s/%s%c", hsm->www_root, request, 0);
+ path = format (0, "%s/%s%c", hsm->www_root, sanitized_path, 0);
if (hsm->debug_level > 0)
clib_warning ("%s '%s'", (rt == HTTP_REQ_GET) ? "GET" : "POST", path);
@@ -419,7 +422,7 @@ try_file_handler (hss_main_t *hsm, hss_session_t *hs, http_req_method_t rt,
hs->cache_pool_index = ce_index;
done:
-
+ vec_free (sanitized_path);
hs->content_type = type;
start_send_data (hs, sc);
if (!hs->data)
diff --git a/src/plugins/ikev2/ikev2_api.c b/src/plugins/ikev2/ikev2_api.c
index a3e71668126..c9608aa660b 100644
--- a/src/plugins/ikev2/ikev2_api.c
+++ b/src/plugins/ikev2/ikev2_api.c
@@ -173,7 +173,7 @@ send_profile (ikev2_profile_t * profile, vl_api_registration_t * reg,
rmp->profile.lifetime_jitter = profile->lifetime_jitter;
rmp->profile.handover = profile->handover;
- vl_api_ikev2_profile_t_endian (&rmp->profile);
+ vl_api_ikev2_profile_t_endian (&rmp->profile, 1 /* to network */);
vl_api_send_msg (reg, (u8 *) rmp);
}
@@ -291,7 +291,7 @@ send_sa (ikev2_sa_t * sa, vl_api_ikev2_sa_dump_t * mp, u32 api_sa_index)
ikev2_copy_stats (&rsa->stats, &sa->stats);
- vl_api_ikev2_sa_t_endian(rsa);
+ vl_api_ikev2_sa_t_endian (rsa, 1 /* to network */);
});
}
@@ -382,7 +382,7 @@ send_sa_v2 (ikev2_sa_t *sa, vl_api_ikev2_sa_v2_dump_t *mp, u32 api_sa_index)
ikev2_copy_stats (&rsa->stats, &sa->stats);
- vl_api_ikev2_sa_v2_t_endian (rsa);
+ vl_api_ikev2_sa_v2_t_endian (rsa, 1 /* to network */);
});
}
@@ -476,7 +476,7 @@ send_sa_v3 (ikev2_sa_t *sa, vl_api_ikev2_sa_v3_dump_t *mp, u32 api_sa_index)
ikev2_copy_stats (&rsa->stats, &sa->stats);
- vl_api_ikev2_sa_v3_t_endian (rsa);
+ vl_api_ikev2_sa_v3_t_endian (rsa, 1 /* to network */);
});
}
@@ -549,7 +549,7 @@ send_child_sa (ikev2_child_sa_t * child,
k->sk_ar_len);
}
- vl_api_ikev2_child_sa_t_endian (&rmp->child_sa);
+ vl_api_ikev2_child_sa_t_endian (&rmp->child_sa, 1 /* to network */);
});
}
@@ -628,7 +628,7 @@ send_child_sa_v2 (ikev2_child_sa_t *child, vl_api_ikev2_child_sa_v2_dump_t *mp,
clib_memcpy (&k->sk_ar, child->sk_ar, k->sk_ar_len);
}
- vl_api_ikev2_child_sa_v2_t_endian (&rmp->child_sa);
+ vl_api_ikev2_child_sa_v2_t_endian (&rmp->child_sa, 1 /* to network */);
});
}
@@ -700,7 +700,7 @@ static void
rmp->ts.sa_index = api_sa_index;
rmp->ts.child_sa_index = child_sa_index;
cp_ts (&rmp->ts, ts, mp->is_initiator);
- vl_api_ikev2_ts_t_endian (&rmp->ts);
+ vl_api_ikev2_ts_t_endian (&rmp->ts, 1 /* to network */);
});
}
}
diff --git a/src/plugins/ikev2/ikev2_test.c b/src/plugins/ikev2/ikev2_test.c
index 5682d7058f6..93683a5b5dc 100644
--- a/src/plugins/ikev2/ikev2_test.c
+++ b/src/plugins/ikev2/ikev2_test.c
@@ -391,7 +391,7 @@ vl_api_ikev2_sa_details_t_handler (vl_api_ikev2_sa_details_t * mp)
ip_address_t iaddr;
ip_address_t raddr;
vl_api_ikev2_keys_t *k = &sa->keys;
- vl_api_ikev2_sa_t_endian (sa);
+ vl_api_ikev2_sa_t_endian (sa, 0 /* from network */);
ip_address_decode2 (&sa->iaddr, &iaddr);
ip_address_decode2 (&sa->raddr, &raddr);
@@ -461,7 +461,7 @@ vl_api_ikev2_sa_v2_details_t_handler (vl_api_ikev2_sa_v2_details_t *mp)
ip_address_t iaddr;
ip_address_t raddr;
vl_api_ikev2_keys_t *k = &sa->keys;
- vl_api_ikev2_sa_v2_t_endian (sa);
+ vl_api_ikev2_sa_v2_t_endian (sa, 0 /* from network */);
ip_address_decode2 (&sa->iaddr, &iaddr);
ip_address_decode2 (&sa->raddr, &raddr);
@@ -533,7 +533,7 @@ vl_api_ikev2_sa_v3_details_t_handler (vl_api_ikev2_sa_v3_details_t *mp)
ip_address_t iaddr;
ip_address_t raddr;
vl_api_ikev2_keys_t *k = &sa->keys;
- vl_api_ikev2_sa_v3_t_endian (sa);
+ vl_api_ikev2_sa_v3_t_endian (sa, 0 /* from network */);
ip_address_decode2 (&sa->iaddr, &iaddr);
ip_address_decode2 (&sa->raddr, &raddr);
@@ -619,7 +619,7 @@ vl_api_ikev2_child_sa_details_t_handler (vl_api_ikev2_child_sa_details_t * mp)
vat_main_t *vam = ikev2_test_main.vat_main;
vl_api_ikev2_child_sa_t *child_sa = &mp->child_sa;
vl_api_ikev2_keys_t *k = &child_sa->keys;
- vl_api_ikev2_child_sa_t_endian (child_sa);
+ vl_api_ikev2_child_sa_t_endian (child_sa, 0 /* from network */);
fformat (vam->ofp, " child sa %u:\n", child_sa->child_sa_index);
@@ -696,7 +696,7 @@ vl_api_ikev2_child_sa_v2_details_t_handler (
vat_main_t *vam = ikev2_test_main.vat_main;
vl_api_ikev2_child_sa_t *child_sa = &mp->child_sa;
vl_api_ikev2_keys_t *k = &child_sa->keys;
- vl_api_ikev2_child_sa_t_endian (child_sa);
+ vl_api_ikev2_child_sa_t_endian (child_sa, 0 /* from network */);
fformat (vam->ofp, " child sa %u:\n", child_sa->child_sa_index);
@@ -784,7 +784,7 @@ static void
vat_main_t *vam = ikev2_test_main.vat_main;
vl_api_ikev2_ts_t *ts = &mp->ts;
ip_address_t start_addr, end_addr;
- vl_api_ikev2_ts_t_endian (ts);
+ vl_api_ikev2_ts_t_endian (ts, 0 /* from network */);
ip_address_decode2 (&ts->start_addr, &start_addr);
ip_address_decode2 (&ts->end_addr, &end_addr);
diff --git a/src/plugins/marvell/pp2/cli.c b/src/plugins/marvell/pp2/cli.c
index f4ecb1873c9..5072a3c035b 100644
--- a/src/plugins/marvell/pp2/cli.c
+++ b/src/plugins/marvell/pp2/cli.c
@@ -31,7 +31,7 @@ mrvl_pp2_create_command_fn (vlib_main_t * vm, unformat_input_t * input,
{
unformat_input_t _line_input, *line_input = &_line_input;
mrvl_pp2_create_if_args_t args = { 0 };
- uint val;
+ unsigned int val;
/* Get a line of input. */
if (!unformat_user (input, unformat_line_input, line_input))
diff --git a/src/plugins/nat/nat44-ed/nat44_ed_api.c b/src/plugins/nat/nat44-ed/nat44_ed_api.c
index 1f01410afce..b6c9d51d777 100644
--- a/src/plugins/nat/nat44-ed/nat44_ed_api.c
+++ b/src/plugins/nat/nat44-ed/nat44_ed_api.c
@@ -442,7 +442,8 @@ send_nat44_ed_output_interface_details (u32 index, vl_api_registration_t *rp,
/* Endian hack until apigen registers _details
* endian functions */
- vl_api_nat44_ed_output_interface_details_t_endian (rmp);
+ vl_api_nat44_ed_output_interface_details_t_endian (rmp,
+ 1 /* to network */);
rmp->_vl_msg_id = htons (rmp->_vl_msg_id);
rmp->context = htonl (rmp->context);
}));
diff --git a/src/plugins/nat/nat44-ei/nat44_ei_api.c b/src/plugins/nat/nat44-ei/nat44_ei_api.c
index 8671a556929..454a5032c6a 100644
--- a/src/plugins/nat/nat44-ei/nat44_ei_api.c
+++ b/src/plugins/nat/nat44-ei/nat44_ei_api.c
@@ -751,7 +751,8 @@ send_nat44_ei_output_interface_details (u32 index, vl_api_registration_t *rp,
/* Endian hack until apigen registers _details
* endian functions */
- vl_api_nat44_ei_output_interface_details_t_endian (rmp);
+ vl_api_nat44_ei_output_interface_details_t_endian (rmp,
+ 1 /* to network */);
rmp->_vl_msg_id = htons (rmp->_vl_msg_id);
rmp->context = htonl (rmp->context);
}));
diff --git a/src/plugins/nat/nat44-ei/nat44_ei_in2out.c b/src/plugins/nat/nat44-ei/nat44_ei_in2out.c
index 01b333a5234..3b981d69986 100644
--- a/src/plugins/nat/nat44-ei/nat44_ei_in2out.c
+++ b/src/plugins/nat/nat44-ei/nat44_ei_in2out.c
@@ -859,7 +859,7 @@ nat44_ei_icmp_in2out (vlib_buffer_t *b0, ip4_header_t *ip0,
nat44_ei_main_t *nm = &nat44_ei_main;
vlib_main_t *vm = vlib_get_main ();
ip4_address_t addr;
- u16 port;
+ u16 port = 0;
u32 fib_index;
nat_protocol_t proto;
icmp_echo_header_t *echo0, *inner_echo0 = 0;
diff --git a/src/plugins/nat/pnat/pnat_api.c b/src/plugins/nat/pnat/pnat_api.c
index 02e61219d1e..a4e7ff192bf 100644
--- a/src/plugins/nat/pnat/pnat_api.c
+++ b/src/plugins/nat/pnat/pnat_api.c
@@ -116,7 +116,8 @@ static void send_bindings_details(u32 index, vl_api_registration_t *rp,
/* Endian hack until apigen registers _details
* endian functions */
- vl_api_pnat_bindings_details_t_endian(rmp);
+ vl_api_pnat_bindings_details_t_endian(
+ rmp, 1 /* to network */);
rmp->_vl_msg_id = htons(rmp->_vl_msg_id);
rmp->context = htonl(rmp->context);
}));
@@ -158,7 +159,7 @@ static void send_interfaces_details(u32 index, vl_api_registration_t *rp,
/* Endian hack until apigen registers _details
* endian functions */
- vl_api_pnat_interfaces_details_t_endian(rmp);
+ vl_api_pnat_interfaces_details_t_endian(rmp, 1 /* to network */);
rmp->_vl_msg_id = htons(rmp->_vl_msg_id);
rmp->context = htonl(rmp->context);
}));
diff --git a/src/plugins/netmap/CMakeLists.txt b/src/plugins/netmap/CMakeLists.txt
new file mode 100644
index 00000000000..d53a9e0911a
--- /dev/null
+++ b/src/plugins/netmap/CMakeLists.txt
@@ -0,0 +1,32 @@
+# SPDX-License-Identifier: Apache-2.0
+# Copyright (c) 2024 Tom Jones <thj@freebsd.org>
+#
+# This software was developed by Tom Jones <thj@freebsd.org> under sponsorship
+# from the FreeBSD Foundation.
+#
+
+if (NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "FreeBSD")
+ message(WARNING "Netmap is only currently support on FreeBSD - netmap plugin disabled")
+ return()
+endif()
+
+add_vpp_plugin(netmap
+ SOURCES
+ plugin.c
+ netmap.c
+ node.c
+ device.c
+ cli.c
+ netmap_api.c
+
+ MULTIARCH_SOURCES
+ node.c
+ device.c
+
+ INSTALL_HEADERS
+ netmap.h
+ net_netmap.h
+
+ API_FILES
+ netmap.api
+)
diff --git a/extras/deprecated/netmap/FEATURE.yaml b/src/plugins/netmap/FEATURE.yaml
index e23e5c243e7..a9dfb2163e4 100644
--- a/extras/deprecated/netmap/FEATURE.yaml
+++ b/src/plugins/netmap/FEATURE.yaml
@@ -1,11 +1,11 @@
---
name: Netmap Device
-maintainer: Damjan Marion <damarion@cisco.com>
+maintainer: Tom Jones <thj@freebsd.org>
features:
- L4 checksum offload
description: "Create a netmap interface, which is a high speed user-space
- interface that allows VPP to patch into a linux namespace,
- a linux container, or a physical NIC without the use of DPDK."
+ interface that allows VPP to patch to a physical or virtual NIC
+ without the use of DPDK"
missing:
- API dump
state: production
diff --git a/extras/deprecated/netmap/cli.c b/src/plugins/netmap/cli.c
index 713632947a1..b54d397ecbe 100644
--- a/extras/deprecated/netmap/cli.c
+++ b/src/plugins/netmap/cli.c
@@ -22,8 +22,8 @@
#include <vlib/unix/unix.h>
#include <vnet/ethernet/ethernet.h>
-#include <vnet/devices/netmap/net_netmap.h>
-#include <vnet/devices/netmap/netmap.h>
+#include <netmap/net_netmap.h>
+#include <netmap/netmap.h>
static clib_error_t *
netmap_create_command_fn (vlib_main_t * vm, unformat_input_t * input,
diff --git a/extras/deprecated/netmap/device.c b/src/plugins/netmap/device.c
index 47407aaaa26..505deb988c4 100644
--- a/extras/deprecated/netmap/device.c
+++ b/src/plugins/netmap/device.c
@@ -23,8 +23,8 @@
#include <vlib/unix/unix.h>
#include <vnet/ethernet/ethernet.h>
-#include <vnet/devices/netmap/net_netmap.h>
-#include <vnet/devices/netmap/netmap.h>
+#include <netmap/net_netmap.h>
+#include <netmap/netmap.h>
#define foreach_netmap_tx_func_error \
_(NO_FREE_SLOTS, "no free tx slots") \
diff --git a/extras/deprecated/netmap/net_netmap.h b/src/plugins/netmap/net_netmap.h
index fd4253b7c0c..ecccedd4484 100644
--- a/extras/deprecated/netmap/net_netmap.h
+++ b/src/plugins/netmap/net_netmap.h
@@ -39,10 +39,10 @@
#ifndef _NET_NETMAP_H_
#define _NET_NETMAP_H_
-#define NETMAP_API 11 /* current API version */
+#define NETMAP_API 14 /* current API version */
-#define NETMAP_MIN_API 11 /* min and max versions accepted */
-#define NETMAP_MAX_API 15
+#define NETMAP_MIN_API 14 /* min and max versions accepted */
+#define NETMAP_MAX_API 15
/*
* Some fields should be cache-aligned to reduce contention.
* The alignment is architecture and OS dependent, but rather than
diff --git a/extras/deprecated/netmap/netmap.api b/src/plugins/netmap/netmap.api
index a14753cad9c..a14753cad9c 100644
--- a/extras/deprecated/netmap/netmap.api
+++ b/src/plugins/netmap/netmap.api
diff --git a/extras/deprecated/netmap/netmap.c b/src/plugins/netmap/netmap.c
index 7cab6bb0289..ebef215eb3b 100644
--- a/extras/deprecated/netmap/netmap.c
+++ b/src/plugins/netmap/netmap.c
@@ -20,22 +20,17 @@
#include <sys/ioctl.h>
#include <sys/types.h>
#include <fcntl.h>
-#include <vnet/devices/netmap/net_netmap.h>
#include <vlib/vlib.h>
#include <vlib/unix/unix.h>
#include <vnet/ethernet/ethernet.h>
-#include <vnet/devices/netmap/netmap.h>
-netmap_main_t netmap_main;
+#include <netmap/net_netmap.h>
+#include <netmap/netmap.h>
+#include <netmap/netmap.api_enum.h>
+#include <netmap/netmap.api_types.h>
-static u32
-netmap_eth_flag_change (vnet_main_t * vnm, vnet_hw_interface_t * hi,
- u32 flags)
-{
- /* nothing for now */
- return 0;
-}
+netmap_main_t netmap_main;
static clib_error_t *
netmap_fd_read_ready (clib_file_t * uf)
@@ -88,12 +83,11 @@ int
netmap_worker_thread_enable ()
{
/* if worker threads are enabled, switch to polling mode */
- foreach_vlib_main ((
- {
- vlib_node_set_state (this_vlib_main,
- netmap_input_node.index,
- VLIB_NODE_STATE_POLLING);
- }));
+ foreach_vlib_main ()
+ {
+ vlib_node_set_state (this_vlib_main, netmap_input_node.index,
+ VLIB_NODE_STATE_POLLING);
+ }
return 0;
}
@@ -101,12 +95,11 @@ netmap_worker_thread_enable ()
int
netmap_worker_thread_disable ()
{
- foreach_vlib_main ((
- {
- vlib_node_set_state (this_vlib_main,
- netmap_input_node.index,
- VLIB_NODE_STATE_INTERRUPT);
- }));
+ foreach_vlib_main ()
+ {
+ vlib_node_set_state (this_vlib_main, netmap_input_node.index,
+ VLIB_NODE_STATE_INTERRUPT);
+ }
return 0;
}
@@ -117,9 +110,9 @@ netmap_create_if (vlib_main_t * vm, u8 * if_name, u8 * hw_addr_set,
{
netmap_main_t *nm = &netmap_main;
int ret = 0;
+ uint32_t nr_reg;
netmap_if_t *nif = 0;
u8 hw_addr[6];
- clib_error_t *error = 0;
vnet_sw_interface_t *sw;
vnet_main_t *vnm = vnet_get_main ();
uword *p;
@@ -179,10 +172,39 @@ netmap_create_if (vlib_main_t * vm, u8 * if_name, u8 * hw_addr_set,
reg->refcnt++;
nif->nifp = NETMAP_IF (reg->mem, req->nr_offset);
- nif->first_rx_ring = 0;
- nif->last_rx_ring = 0;
- nif->first_tx_ring = 0;
- nif->last_tx_ring = 0;
+ nr_reg = nif->req->nr_flags & NR_REG_MASK;
+
+ if (nr_reg == NR_REG_SW)
+ { /* host stack */
+ nif->first_tx_ring = nif->last_tx_ring = nif->req->nr_tx_rings;
+ nif->first_rx_ring = nif->last_rx_ring = nif->req->nr_rx_rings;
+ }
+ else if (nr_reg == NR_REG_ALL_NIC)
+ { /* only nic */
+ nif->first_tx_ring = 0;
+ nif->first_rx_ring = 0;
+ nif->last_tx_ring = nif->req->nr_tx_rings - 1;
+ nif->last_rx_ring = nif->req->nr_rx_rings - 1;
+ }
+ else if (nr_reg == NR_REG_NIC_SW)
+ {
+ nif->first_tx_ring = 0;
+ nif->first_rx_ring = 0;
+ nif->last_tx_ring = nif->req->nr_tx_rings;
+ nif->last_rx_ring = nif->req->nr_rx_rings;
+ }
+ else if (nr_reg == NR_REG_ONE_NIC)
+ {
+ /* XXX check validity */
+ nif->first_tx_ring = nif->last_tx_ring = nif->first_rx_ring =
+ nif->last_rx_ring = nif->req->nr_ringid & NETMAP_RING_MASK;
+ }
+ else
+ { /* pipes */
+ nif->first_tx_ring = nif->last_tx_ring = 0;
+ nif->first_rx_ring = nif->last_rx_ring = 0;
+ }
+
nif->host_if_name = if_name;
nif->per_interface_next_index = ~0;
@@ -213,17 +235,14 @@ netmap_create_if (vlib_main_t * vm, u8 * if_name, u8 * hw_addr_set,
hw_addr[1] = 0xfe;
}
- error = ethernet_register_interface (vnm, netmap_device_class.index,
- nif->if_index, hw_addr,
- &nif->hw_if_index,
- netmap_eth_flag_change);
+ vnet_eth_interface_registration_t eir = {};
- if (error)
- {
- clib_error_report (error);
- ret = VNET_API_ERROR_SYSCALL_ERROR_1;
- goto error;
- }
+ eir.dev_class_index = netmap_device_class.index;
+ eir.dev_instance = nif->if_index;
+ eir.address = hw_addr;
+ eir.cb.set_max_frame_size = NULL;
+
+ nif->hw_if_index = vnet_eth_register_interface (vnm, &eir);
sw = vnet_get_hw_sw_interface (vnm, nif->hw_if_index);
nif->sw_if_index = sw->sw_if_index;
diff --git a/extras/deprecated/netmap/netmap.h b/src/plugins/netmap/netmap.h
index 29f855fda8e..29f855fda8e 100644
--- a/extras/deprecated/netmap/netmap.h
+++ b/src/plugins/netmap/netmap.h
diff --git a/extras/deprecated/netmap/netmap_api.c b/src/plugins/netmap/netmap_api.c
index ee05ec22d25..51f572a23e6 100644
--- a/extras/deprecated/netmap/netmap_api.c
+++ b/src/plugins/netmap/netmap_api.c
@@ -22,23 +22,11 @@
#include <vnet/interface.h>
#include <vnet/api_errno.h>
-#include <vnet/devices/netmap/netmap.h>
+#include <netmap/netmap.h>
-#include <vnet/vnet_msg_enum.h>
-
-#define vl_typedefs /* define message structures */
-#include <vnet/vnet_all_api_h.h>
-#undef vl_typedefs
-
-#define vl_endianfun /* define message structures */
-#include <vnet/vnet_all_api_h.h>
-#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 <vnet/vnet_all_api_h.h>
-#undef vl_printfun
+#include <vnet/format_fns.h>
+#include <netmap/netmap.api_enum.h>
+#include <netmap/netmap.api_types.h>
#include <vlibapi/api_helper_macros.h>
@@ -84,44 +72,14 @@ vl_api_netmap_delete_t_handler (vl_api_netmap_delete_t * mp)
REPLY_MACRO (VL_API_NETMAP_DELETE_REPLY);
}
-/*
- * netmap_api_hookup
- * Add vpe's API message handlers to the table.
- * vlib has already mapped shared memory and
- * added the client registration handlers.
- * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process()
- */
-#define vl_msg_name_crc_list
-#include <vnet/vnet_all_api_h.h>
-#undef vl_msg_name_crc_list
-
-static void
-setup_message_id_table (api_main_t * am)
-{
-#define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
- foreach_vl_msg_name_crc_netmap;
-#undef _
-}
-
+#include <netmap/netmap.api.c>
static clib_error_t *
netmap_api_hookup (vlib_main_t * vm)
{
- api_main_t *am = vlibapi_get_main ();
-
-#define _(N,n) \
- vl_msg_api_set_handlers(VL_API_##N, #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_msg;
-#undef _
-
/*
* Set up the (msg_name, crc, message-id) table
*/
- setup_message_id_table (am);
+ setup_message_id_table ();
return 0;
}
diff --git a/extras/deprecated/netmap/node.c b/src/plugins/netmap/node.c
index b0a68824b9c..6169847fa79 100644
--- a/extras/deprecated/netmap/node.c
+++ b/src/plugins/netmap/node.c
@@ -25,8 +25,8 @@
#include <vnet/devices/devices.h>
#include <vnet/feature/feature.h>
-#include <vnet/devices/netmap/net_netmap.h>
-#include <vnet/devices/netmap/netmap.h>
+#include <netmap/net_netmap.h>
+#include <netmap/netmap.h>
#define foreach_netmap_input_error
@@ -112,7 +112,7 @@ netmap_device_input_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
n_free_bufs +=
vlib_buffer_alloc (vm, &nm->rx_buffers[thread_index][n_free_bufs],
VLIB_FRAME_SIZE);
- _vec_len (nm->rx_buffers[thread_index]) = n_free_bufs;
+ vec_set_len (nm->rx_buffers[thread_index], n_free_bufs);
}
cur_ring = nif->first_rx_ring;
@@ -166,7 +166,8 @@ netmap_device_input_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
prev_bi0 = bi0;
bi0 = nm->rx_buffers[thread_index][last_empty_buffer];
b0 = vlib_get_buffer (vm, bi0);
- _vec_len (nm->rx_buffers[thread_index]) = last_empty_buffer;
+ vec_set_len (nm->rx_buffers[thread_index],
+ last_empty_buffer);
n_free_bufs--;
/* copy data */
@@ -200,11 +201,12 @@ netmap_device_input_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
/* trace */
if (PREDICT_FALSE (n_trace > 0))
{
- if (PREDICT_TRUE (first_b0 != 0))
+ if (PREDICT_TRUE (first_b0 != 0) &&
+ vlib_trace_buffer (vm, node, next0, first_b0,
+ /* follow_chain */ 0))
{
netmap_input_trace_t *tr;
- vlib_trace_buffer (vm, node, next0, first_b0,
- /* follow_chain */ 0);
+
vlib_set_trace_count (vm, node, --n_trace);
tr = vlib_add_trace (vm, node, first_b0, sizeof (*tr));
tr->next_index = next0;
@@ -213,10 +215,6 @@ netmap_device_input_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
}
}
- /* redirect if feature path enabled */
- vnet_feature_start_device_input_x1 (nif->sw_if_index, &next0,
- first_b0);
-
/* enque and take next packet */
vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
n_left_to_next, first_bi0,
diff --git a/src/plugins/netmap/plugin.c b/src/plugins/netmap/plugin.c
new file mode 100644
index 00000000000..1673225b683
--- /dev/null
+++ b/src/plugins/netmap/plugin.c
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: Apache-2.0
+ * Copyright (c) 2024 Tom Jones <thj@freebsd.org>
+ *
+ * This software was developed by Tom Jones <thj@freebsd.org> under sponsorship
+ * from the FreeBSD Foundation.
+ *
+ */
+
+#include <vlib/vlib.h>
+#include <vnet/plugin/plugin.h>
+#include <vpp/app/version.h>
+
+VLIB_PLUGIN_REGISTER () = {
+ .version = VPP_BUILD_VER,
+ .description = "netmap",
+};
diff --git a/src/plugins/srmpls/CMakeLists.txt b/src/plugins/srmpls/CMakeLists.txt
new file mode 100644
index 00000000000..25905d31e1b
--- /dev/null
+++ b/src/plugins/srmpls/CMakeLists.txt
@@ -0,0 +1,30 @@
+# Copyright (c) 2024 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.
+
+add_vpp_plugin(srmpls
+ SOURCES
+ sr_mpls_policy.c
+ sr_mpls_steering.c
+ sr_mpls_api.c
+ plugin.c
+
+ INSTALL_HEADERS
+ sr_mpls.h
+
+ API_FILES
+ sr_mpls.api
+
+ # This might need to be VAT_AUTO_TEST? Not documented
+ API_TEST_SOURCES
+ sr_mpls_test.c
+)
diff --git a/src/vnet/srmpls/FEATURE.yaml b/src/plugins/srmpls/FEATURE.yaml
index c5b958224c7..c5b958224c7 100644
--- a/src/vnet/srmpls/FEATURE.yaml
+++ b/src/plugins/srmpls/FEATURE.yaml
diff --git a/src/vnet/srmpls/dir.dox b/src/plugins/srmpls/dir.dox
index 76ec1d6a41b..76ec1d6a41b 100644
--- a/src/vnet/srmpls/dir.dox
+++ b/src/plugins/srmpls/dir.dox
diff --git a/extras/deprecated/netmap/dir.dox b/src/plugins/srmpls/plugin.c
index 7ddbf947c29..af87607764f 100644
--- a/extras/deprecated/netmap/dir.dox
+++ b/src/plugins/srmpls/plugin.c
@@ -1,6 +1,7 @@
/*
- * Copyright (c) 2017 Cisco and/or its affiliates.
+ * plugin.c: srmpls
*
+ * Copyright (c) 2024 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:
@@ -14,14 +15,12 @@
* limitations under the License.
*/
-/* Doxygen directory documentation */
+#include <vlib/vlib.h>
+#include <vnet/plugin/plugin.h>
+#include <vpp/app/version.h>
-/**
-@dir
-@brief netmap Interface Implementation.
-
-This directory contains the source code for the netmap driver.
-
-*/
-/*? %%clicmd:group_label netmap %% ?*/
-/*? %%syscfg:group_label netmap %% ?*/
+// register a plugin
+VLIB_PLUGIN_REGISTER () = {
+ .version = VPP_BUILD_VER,
+ .description = "Segment Routing for MPLS plugin",
+};
diff --git a/src/vnet/srmpls/sr_doc.rst b/src/plugins/srmpls/sr_doc.rst
index ed847fa0d42..ed847fa0d42 100644
--- a/src/vnet/srmpls/sr_doc.rst
+++ b/src/plugins/srmpls/sr_doc.rst
diff --git a/src/vnet/srmpls/sr_mpls.api b/src/plugins/srmpls/sr_mpls.api
index 742f135d493..742f135d493 100644
--- a/src/vnet/srmpls/sr_mpls.api
+++ b/src/plugins/srmpls/sr_mpls.api
diff --git a/src/vnet/srmpls/sr_mpls.h b/src/plugins/srmpls/sr_mpls.h
index a8f9494428f..a8f9494428f 100644
--- a/src/vnet/srmpls/sr_mpls.h
+++ b/src/plugins/srmpls/sr_mpls.h
diff --git a/src/vnet/srmpls/sr_mpls_api.c b/src/plugins/srmpls/sr_mpls_api.c
index 920856acff6..3e89017dbc1 100644
--- a/src/vnet/srmpls/sr_mpls_api.c
+++ b/src/plugins/srmpls/sr_mpls_api.c
@@ -17,7 +17,7 @@
*/
#include <vnet/vnet.h>
-#include <vnet/srmpls/sr_mpls.h>
+#include "sr_mpls.h"
#include <vlibmemory/api.h>
#include <vnet/interface.h>
@@ -26,28 +26,27 @@
#include <vnet/ip/ip_types_api.h>
#include <vnet/format_fns.h>
-#include <vnet/srmpls/sr_mpls.api_enum.h>
-#include <vnet/srmpls/sr_mpls.api_types.h>
-
+#include <plugins/srmpls/sr_mpls.api_enum.h>
+#include <plugins/srmpls/sr_mpls.api_types.h>
#define vl_api_version(n, v) static u32 api_version = v;
-#include <vnet/srmpls/sr_mpls.api.h>
+#include <plugins/srmpls/sr_mpls.api.h>
#undef vl_api_version
#define vl_endianfun
-#include <vnet/srmpls/sr_mpls.api.h>
+#include <plugins/srmpls/sr_mpls.api.h>
#undef vl_endianfun
#define vl_calcsizefun
-#include <vnet/srmpls/sr_mpls.api.h>
+#include <plugins/srmpls/sr_mpls.api.h>
#undef vl_calcsizefun
#define vl_printfun
-#include <vnet/srmpls/sr_mpls.api.h>
+#include <plugins/srmpls/sr_mpls.api.h>
#undef vl_printfun
#define vl_msg_name_crc_list
-#include <vnet/srmpls/sr_mpls.api.h>
+#include <plugins/srmpls/sr_mpls.api.h>
#undef vl_msg_name_crc_list
#define REPLY_MSG_ID_BASE msg_id_base
diff --git a/src/vnet/srmpls/sr_mpls_policy.c b/src/plugins/srmpls/sr_mpls_policy.c
index 41cb71601e9..af24acd8cf6 100644
--- a/src/vnet/srmpls/sr_mpls_policy.c
+++ b/src/plugins/srmpls/sr_mpls_policy.c
@@ -31,7 +31,7 @@
#include <vlib/vlib.h>
#include <vnet/vnet.h>
-#include <vnet/srmpls/sr_mpls.h>
+#include "sr_mpls.h"
#include <vnet/fib/mpls_fib.h>
#include <vnet/dpo/dpo.h>
#include <vnet/ip/ip.h>
diff --git a/src/vnet/srmpls/sr_mpls_steering.c b/src/plugins/srmpls/sr_mpls_steering.c
index e8920df542b..24c8b0e2d9f 100644
--- a/src/vnet/srmpls/sr_mpls_steering.c
+++ b/src/plugins/srmpls/sr_mpls_steering.c
@@ -31,7 +31,7 @@
#include <vlib/vlib.h>
#include <vnet/vnet.h>
-#include <vnet/srmpls/sr_mpls.h>
+#include "sr_mpls.h"
#include <vnet/ip/ip4_packet.h>
#include <vnet/ip/ip6_packet.h>
#include <vnet/fib/mpls_fib.h>
diff --git a/src/vnet/srmpls/sr_mpls_test.c b/src/plugins/srmpls/sr_mpls_test.c
index e5d68462443..7aff4c32b06 100644
--- a/src/vnet/srmpls/sr_mpls_test.c
+++ b/src/plugins/srmpls/sr_mpls_test.c
@@ -25,11 +25,11 @@
/* Declare message IDs */
#include <vnet/format_fns.h>
-#include <vnet/srmpls/sr_mpls.api_enum.h>
-#include <vnet/srmpls/sr_mpls.api_types.h>
+#include <plugins/srmpls/sr_mpls.api_enum.h>
+#include <plugins/srmpls/sr_mpls.api_types.h>
#define vl_endianfun /* define message structures */
-#include <vnet/srmpls/sr_mpls.api.h>
+#include <plugins/srmpls/sr_mpls.api.h>
#undef vl_endianfun
typedef struct
@@ -163,7 +163,7 @@ api_sr_mpls_policy_del (vat_main_t *vam)
return ret;
}
-#include <vnet/srmpls/sr_mpls.api_test.c>
+#include <plugins/srmpls/sr_mpls.api_test.c>
/*
* fd.io coding-style-patch-verification: ON
diff --git a/src/plugins/unittest/policer_test.c b/src/plugins/unittest/policer_test.c
index 2b14bf687bf..41f769960a3 100644
--- a/src/plugins/unittest/policer_test.c
+++ b/src/plugins/unittest/policer_test.c
@@ -21,7 +21,7 @@ policer_test (vlib_main_t *vm, unformat_input_t *input,
vlib_cli_command_t *cmd_arg)
{
int policer_index, i;
- uint rate_kbps, burst, num_pkts;
+ unsigned int rate_kbps, burst, num_pkts;
double total_bytes, cpu_ticks_per_pkt, time = 0;
double cpu_speed, cpu_ticks_per_byte;
policer_result_e result, input_colour = POLICE_CONFORM;
diff --git a/src/plugins/urpf/CMakeLists.txt b/src/plugins/urpf/CMakeLists.txt
index 2f44e3b2344..f665d30b0bb 100644
--- a/src/plugins/urpf/CMakeLists.txt
+++ b/src/plugins/urpf/CMakeLists.txt
@@ -22,6 +22,10 @@ add_vpp_plugin(urpf
ip4_urpf.c
ip6_urpf.c
+ INSTALL_HEADERS
+ urpf_dp.h
+ urpf.h
+
API_FILES
urpf.api
)
diff --git a/src/plugins/urpf/urpf.c b/src/plugins/urpf/urpf.c
index e5209caafb4..1e7d6c0fb91 100644
--- a/src/plugins/urpf/urpf.c
+++ b/src/plugins/urpf/urpf.c
@@ -60,7 +60,17 @@ static const char *urpf_feats[N_AF][VLIB_N_DIR][URPF_N_MODES] =
urpf_data_t *urpf_cfgs[N_AF][VLIB_N_DIR];
u8 *
-format_urpf_mode (u8 * s, va_list * a)
+format_urpf_trace (u8 *s, va_list *va)
+{
+ CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
+ CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
+ urpf_trace_t *t = va_arg (*va, urpf_trace_t *);
+
+ return format (s, "uRPF:%d fib:%d", t->urpf, t->fib_index);
+}
+
+__clib_export u8 *
+format_urpf_mode (u8 *s, va_list *a)
{
urpf_mode_t mode = va_arg (*a, int);
@@ -76,8 +86,8 @@ format_urpf_mode (u8 * s, va_list * a)
return (format (s, "unknown"));
}
-static uword
-unformat_urpf_mode (unformat_input_t * input, va_list * args)
+__clib_export uword
+unformat_urpf_mode (unformat_input_t *input, va_list *args)
{
urpf_mode_t *mode = va_arg (*args, urpf_mode_t *);
@@ -94,7 +104,16 @@ unformat_urpf_mode (unformat_input_t * input, va_list * args)
return 0;
}
-int
+__clib_export int
+urpf_feature_enable_disable (ip_address_family_t af, vlib_dir_t dir,
+ urpf_mode_t mode, u32 sw_if_index, int enable)
+{
+ return vnet_feature_enable_disable (urpf_feat_arcs[af][dir],
+ urpf_feats[af][dir][mode], sw_if_index,
+ enable, 0, 0);
+}
+
+__clib_export int
urpf_update (urpf_mode_t mode, u32 sw_if_index, ip_address_family_t af,
vlib_dir_t dir, u32 table_id)
{
diff --git a/src/plugins/urpf/urpf.h b/src/plugins/urpf/urpf.h
index 6983a2b440c..a40a25df16b 100644
--- a/src/plugins/urpf/urpf.h
+++ b/src/plugins/urpf/urpf.h
@@ -32,7 +32,15 @@ typedef enum urpf_mode_t_
#define URPF_N_MODES (URPF_MODE_STRICT+1)
-extern u8 *format_urpf_mode (u8 * s, va_list * a);
+typedef struct
+{
+ index_t urpf;
+ u32 fib_index;
+} urpf_trace_t;
+
+u8 *format_urpf_trace (u8 *s, va_list *va);
+u8 *format_urpf_mode (u8 *s, va_list *a);
+uword unformat_urpf_mode (unformat_input_t *input, va_list *args);
typedef struct
{
@@ -43,8 +51,8 @@ typedef struct
extern urpf_data_t *urpf_cfgs[N_AF][VLIB_N_DIR];
-extern int urpf_update (urpf_mode_t mode, u32 sw_if_index,
- ip_address_family_t af, vlib_dir_t dir, u32 table_id);
+int urpf_update (urpf_mode_t mode, u32 sw_if_index, ip_address_family_t af,
+ vlib_dir_t dir, u32 table_id);
#endif
diff --git a/src/plugins/urpf/urpf_dp.h b/src/plugins/urpf/urpf_dp.h
index 816d8b70b90..b17fed7e04b 100644
--- a/src/plugins/urpf/urpf_dp.h
+++ b/src/plugins/urpf/urpf_dp.h
@@ -53,22 +53,6 @@
*
* This file contains the interface unicast source check.
*/
-typedef struct
-{
- index_t urpf;
-} urpf_trace_t;
-
-static u8 *
-format_urpf_trace (u8 * s, va_list * va)
-{
- CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
- CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
- urpf_trace_t *t = va_arg (*va, urpf_trace_t *);
-
- s = format (s, "uRPF:%d", t->urpf);
-
- return s;
-}
#define foreach_urpf_error \
_(DROP, "uRPF Drop") \
@@ -87,10 +71,157 @@ typedef enum
URPF_N_NEXT,
} urpf_next_t;
+static_always_inline u32
+urpf_get_fib_index (vlib_buffer_t *b, ip_address_family_t af, vlib_dir_t dir)
+{
+ u32 sw_if_index = vnet_buffer (b)->sw_if_index[dir];
+ return vec_elt (urpf_cfgs[af][dir], sw_if_index).fib_index;
+}
+
+static_always_inline void
+urpf_perform_check_x1 (ip_address_family_t af, vlib_dir_t dir,
+ urpf_mode_t mode, vlib_buffer_t *b, const u8 *h,
+ u32 fib_index, load_balance_t **lb, u32 *pass)
+{
+ load_balance_t *llb;
+ u32 lpass;
+ u32 lb_index;
+
+ ASSERT (fib_index != ~0);
+
+ if (AF_IP4 == af)
+ {
+ const ip4_header_t *ip;
+
+ ip = (ip4_header_t *) h;
+
+ lb_index = ip4_fib_forwarding_lookup (fib_index, &ip->src_address);
+
+ /* Pass multicast. */
+ lpass = (ip4_address_is_multicast (&ip->src_address) ||
+ ip4_address_is_global_broadcast (&ip->src_address));
+ }
+ else
+ {
+ const ip6_header_t *ip;
+
+ ip = (ip6_header_t *) h;
+
+ lb_index = ip6_fib_table_fwding_lookup (fib_index, &ip->src_address);
+ lpass = ip6_address_is_multicast (&ip->src_address);
+ }
+
+ llb = load_balance_get (lb_index);
+
+ if (URPF_MODE_STRICT == mode)
+ {
+ int res;
+
+ res = fib_urpf_check (llb->lb_urpf, vnet_buffer (b)->sw_if_index[dir]);
+ if (VLIB_RX == dir)
+ lpass |= res;
+ else
+ {
+ lpass |= !res && fib_urpf_check_size (llb->lb_urpf);
+ lpass |= b->flags & VNET_BUFFER_F_LOCALLY_ORIGINATED;
+ }
+ }
+ else
+ lpass |= fib_urpf_check_size (llb->lb_urpf);
+
+ *lb = llb;
+ *pass = lpass;
+}
+
+static_always_inline void
+urpf_perform_check_x2 (ip_address_family_t af, vlib_dir_t dir,
+ urpf_mode_t mode, vlib_buffer_t *b0, vlib_buffer_t *b1,
+ const u8 *h0, const u8 *h1, u32 fib_index0,
+ u32 fib_index1, load_balance_t **lb0,
+ load_balance_t **lb1, u32 *pass0, u32 *pass1)
+{
+ load_balance_t *llb0, *llb1;
+ u32 lpass0, lpass1;
+ u32 lb_index0, lb_index1;
+
+ ASSERT (fib_index0 != ~0);
+ ASSERT (fib_index1 != ~0);
+
+ if (AF_IP4 == af)
+ {
+ const ip4_header_t *ip0, *ip1;
+
+ ip0 = (ip4_header_t *) h0;
+ ip1 = (ip4_header_t *) h1;
+
+ ip4_fib_forwarding_lookup_x2 (fib_index0, fib_index1, &ip0->src_address,
+ &ip1->src_address, &lb_index0, &lb_index1);
+ /* Pass multicast. */
+ lpass0 = (ip4_address_is_multicast (&ip0->src_address) ||
+ ip4_address_is_global_broadcast (&ip0->src_address));
+ lpass1 = (ip4_address_is_multicast (&ip1->src_address) ||
+ ip4_address_is_global_broadcast (&ip1->src_address));
+ }
+ else
+ {
+ const ip6_header_t *ip0, *ip1;
+
+ ip0 = (ip6_header_t *) h0;
+ ip1 = (ip6_header_t *) h1;
+
+ lb_index0 = ip6_fib_table_fwding_lookup (fib_index0, &ip0->src_address);
+ lb_index1 = ip6_fib_table_fwding_lookup (fib_index1, &ip1->src_address);
+ lpass0 = ip6_address_is_multicast (&ip0->src_address);
+ lpass1 = ip6_address_is_multicast (&ip1->src_address);
+ }
+
+ llb0 = load_balance_get (lb_index0);
+ llb1 = load_balance_get (lb_index1);
+
+ if (URPF_MODE_STRICT == mode)
+ {
+ /* for RX the check is: would this source adddress be
+ * forwarded out of the interface on which it was recieved,
+ * if yes allow. For TX it's; would this source address be
+ * forwarded out of the interface through which it is being
+ * sent, if yes drop.
+ */
+ int res0, res1;
+
+ res0 =
+ fib_urpf_check (llb0->lb_urpf, vnet_buffer (b0)->sw_if_index[dir]);
+ res1 =
+ fib_urpf_check (llb1->lb_urpf, vnet_buffer (b1)->sw_if_index[dir]);
+
+ if (VLIB_RX == dir)
+ {
+ lpass0 |= res0;
+ lpass1 |= res1;
+ }
+ else
+ {
+ lpass0 |= !res0 && fib_urpf_check_size (llb0->lb_urpf);
+ lpass1 |= !res1 && fib_urpf_check_size (llb1->lb_urpf);
+
+ /* allow locally generated */
+ lpass0 |= b0->flags & VNET_BUFFER_F_LOCALLY_ORIGINATED;
+ lpass1 |= b1->flags & VNET_BUFFER_F_LOCALLY_ORIGINATED;
+ }
+ }
+ else
+ {
+ lpass0 |= fib_urpf_check_size (llb0->lb_urpf);
+ lpass1 |= fib_urpf_check_size (llb1->lb_urpf);
+ }
+
+ *lb0 = llb0;
+ *lb1 = llb1;
+ *pass0 = lpass0;
+ *pass1 = lpass1;
+}
+
static_always_inline uword
-urpf_inline (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * frame,
+urpf_inline (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame,
ip_address_family_t af, vlib_dir_t dir, urpf_mode_t mode)
{
vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b;
@@ -106,8 +237,8 @@ urpf_inline (vlib_main_t * vm,
while (n_left >= 4)
{
- u32 pass0, lb_index0, pass1, lb_index1;
- const load_balance_t *lb0, *lb1;
+ u32 pass0, pass1;
+ load_balance_t *lb0 = 0, *lb1 = 0;
u32 fib_index0, fib_index1;
const u8 *h0, *h1;
@@ -121,87 +252,32 @@ urpf_inline (vlib_main_t * vm,
h0 = (u8 *) vlib_buffer_get_current (b[0]);
h1 = (u8 *) vlib_buffer_get_current (b[1]);
-
if (VLIB_TX == dir)
{
h0 += vnet_buffer (b[0])->ip.save_rewrite_length;
h1 += vnet_buffer (b[1])->ip.save_rewrite_length;
}
- fib_index0 =
- urpf_cfgs[af][dir][vnet_buffer (b[0])->sw_if_index[dir]].fib_index;
- fib_index1 =
- urpf_cfgs[af][dir][vnet_buffer (b[1])->sw_if_index[dir]].fib_index;
+ fib_index0 = urpf_get_fib_index (b[0], af, dir);
+ fib_index1 = urpf_get_fib_index (b[1], af, dir);
+ urpf_perform_check_x2 (af, dir, mode, b[0], b[1], h0, h1, fib_index0,
+ fib_index1, &lb0, &lb1, &pass0, &pass1);
- if (AF_IP4 == af)
- {
- const ip4_header_t *ip0, *ip1;
-
- ip0 = (ip4_header_t *) h0;
- ip1 = (ip4_header_t *) h1;
-
- ip4_fib_forwarding_lookup_x2 (fib_index0,
- fib_index1,
- &ip0->src_address,
- &ip1->src_address,
- &lb_index0, &lb_index1);
- /* Pass multicast. */
- pass0 = (ip4_address_is_multicast (&ip0->src_address) ||
- ip4_address_is_global_broadcast (&ip0->src_address));
- pass1 = (ip4_address_is_multicast (&ip1->src_address) ||
- ip4_address_is_global_broadcast (&ip1->src_address));
- }
- else
+ if (b[0]->flags & VLIB_BUFFER_IS_TRACED)
{
- const ip6_header_t *ip0, *ip1;
-
- ip0 = (ip6_header_t *) h0;
- ip1 = (ip6_header_t *) h1;
-
- lb_index0 = ip6_fib_table_fwding_lookup (fib_index0,
- &ip0->src_address);
- lb_index1 = ip6_fib_table_fwding_lookup (fib_index1,
- &ip1->src_address);
- pass0 = ip6_address_is_multicast (&ip0->src_address);
- pass1 = ip6_address_is_multicast (&ip1->src_address);
- }
-
- lb0 = load_balance_get (lb_index0);
- lb1 = load_balance_get (lb_index1);
+ urpf_trace_t *t;
- if (URPF_MODE_STRICT == mode)
- {
- /* for RX the check is: would this source adddress be forwarded
- * out of the interface on which it was recieved, if yes allow.
- * For TX it's; would this source address be forwarded out of the
- * interface through which it is being sent, if yes drop.
- */
- int res0, res1;
-
- res0 = fib_urpf_check (lb0->lb_urpf,
- vnet_buffer (b[0])->sw_if_index[dir]);
- res1 = fib_urpf_check (lb1->lb_urpf,
- vnet_buffer (b[1])->sw_if_index[dir]);
-
- if (VLIB_RX == dir)
- {
- pass0 |= res0;
- pass1 |= res1;
- }
- else
- {
- pass0 |= !res0 && fib_urpf_check_size (lb0->lb_urpf);
- pass1 |= !res1 && fib_urpf_check_size (lb1->lb_urpf);
-
- /* allow locally generated */
- pass0 |= b[0]->flags & VNET_BUFFER_F_LOCALLY_ORIGINATED;
- pass1 |= b[1]->flags & VNET_BUFFER_F_LOCALLY_ORIGINATED;
- }
+ t = vlib_add_trace (vm, node, b[0], sizeof (*t));
+ t->urpf = lb0 ? lb0->lb_urpf : ~0;
+ t->fib_index = fib_index0;
}
- else
+ if (b[1]->flags & VLIB_BUFFER_IS_TRACED)
{
- pass0 |= fib_urpf_check_size (lb0->lb_urpf);
- pass1 |= fib_urpf_check_size (lb1->lb_urpf);
+ urpf_trace_t *t;
+
+ t = vlib_add_trace (vm, node, b[1], sizeof (*t));
+ t->urpf = lb1 ? lb1->lb_urpf : ~0;
+ t->fib_index = fib_index1;
}
if (PREDICT_TRUE (pass0))
@@ -218,22 +294,6 @@ urpf_inline (vlib_main_t * vm,
next[1] = URPF_NEXT_DROP;
b[1]->error = node->errors[URPF_ERROR_DROP];
}
-
- if (b[0]->flags & VLIB_BUFFER_IS_TRACED)
- {
- urpf_trace_t *t;
-
- t = vlib_add_trace (vm, node, b[0], sizeof (*t));
- t->urpf = lb0->lb_urpf;
- }
- if (b[1]->flags & VLIB_BUFFER_IS_TRACED)
- {
- urpf_trace_t *t;
-
- t = vlib_add_trace (vm, node, b[1], sizeof (*t));
- t->urpf = lb1->lb_urpf;
- }
-
b += 2;
next += 2;
n_left -= 2;
@@ -241,8 +301,8 @@ urpf_inline (vlib_main_t * vm,
while (n_left)
{
- u32 pass0, lb_index0, fib_index0;
- const load_balance_t *lb0;
+ u32 pass0, fib_index0;
+ load_balance_t *lb0 = 0;
const u8 *h0;
h0 = (u8 *) vlib_buffer_get_current (b[0]);
@@ -250,51 +310,18 @@ urpf_inline (vlib_main_t * vm,
if (VLIB_TX == dir)
h0 += vnet_buffer (b[0])->ip.save_rewrite_length;
- fib_index0 =
- urpf_cfgs[af][dir][vnet_buffer (b[0])->sw_if_index[dir]].fib_index;
-
- if (AF_IP4 == af)
- {
- const ip4_header_t *ip0;
-
- ip0 = (ip4_header_t *) h0;
-
- lb_index0 = ip4_fib_forwarding_lookup (fib_index0,
- &ip0->src_address);
+ fib_index0 = urpf_get_fib_index (b[0], af, dir);
+ urpf_perform_check_x1 (af, dir, mode, b[0], h0, fib_index0, &lb0,
+ &pass0);
- /* Pass multicast. */
- pass0 = (ip4_address_is_multicast (&ip0->src_address) ||
- ip4_address_is_global_broadcast (&ip0->src_address));
- }
- else
+ if (b[0]->flags & VLIB_BUFFER_IS_TRACED)
{
- const ip6_header_t *ip0;
-
- ip0 = (ip6_header_t *) h0;
-
- lb_index0 = ip6_fib_table_fwding_lookup (fib_index0,
- &ip0->src_address);
- pass0 = ip6_address_is_multicast (&ip0->src_address);
- }
-
- lb0 = load_balance_get (lb_index0);
+ urpf_trace_t *t;
- if (URPF_MODE_STRICT == mode)
- {
- int res0;
-
- res0 = fib_urpf_check (lb0->lb_urpf,
- vnet_buffer (b[0])->sw_if_index[dir]);
- if (VLIB_RX == dir)
- pass0 |= res0;
- else
- {
- pass0 |= !res0 && fib_urpf_check_size (lb0->lb_urpf);
- pass0 |= b[0]->flags & VNET_BUFFER_F_LOCALLY_ORIGINATED;
- }
+ t = vlib_add_trace (vm, node, b[0], sizeof (*t));
+ t->urpf = lb0 ? lb0->lb_urpf : ~0;
+ t->fib_index = fib_index0;
}
- else
- pass0 |= fib_urpf_check_size (lb0->lb_urpf);
if (PREDICT_TRUE (pass0))
vnet_feature_next_u16 (&next[0], b[0]);
@@ -303,14 +330,6 @@ urpf_inline (vlib_main_t * vm,
next[0] = URPF_NEXT_DROP;
b[0]->error = node->errors[URPF_ERROR_DROP];
}
-
- if (b[0]->flags & VLIB_BUFFER_IS_TRACED)
- {
- urpf_trace_t *t;
-
- t = vlib_add_trace (vm, node, b[0], sizeof (*t));
- t->urpf = lb0->lb_urpf;
- }
b++;
next++;
n_left--;
diff --git a/src/plugins/wireguard/wireguard_chachapoly.c b/src/plugins/wireguard/wireguard_chachapoly.c
index 0dd7908d2e2..ad644ff6cb8 100644
--- a/src/plugins/wireguard/wireguard_chachapoly.c
+++ b/src/plugins/wireguard/wireguard_chachapoly.c
@@ -72,11 +72,11 @@ wg_xchacha20poly1305_encrypt (vlib_main_t *vm, u8 *src, u32 src_len, u8 *dst,
u64 h_nonce;
clib_memcpy (&h_nonce, nonce + 16, sizeof (h_nonce));
- h_nonce = le64toh (h_nonce);
+ h_nonce = clib_little_to_host_u64 (h_nonce);
hchacha20 (derived_key, nonce, key);
for (i = 0; i < (sizeof (derived_key) / sizeof (derived_key[0])); i++)
- (derived_key[i]) = htole32 ((derived_key[i]));
+ (derived_key[i]) = clib_host_to_little_u32 ((derived_key[i]));
uint32_t key_idx;
@@ -102,11 +102,11 @@ wg_xchacha20poly1305_decrypt (vlib_main_t *vm, u8 *src, u32 src_len, u8 *dst,
u64 h_nonce;
clib_memcpy (&h_nonce, nonce + 16, sizeof (h_nonce));
- h_nonce = le64toh (h_nonce);
+ h_nonce = clib_little_to_host_u64 (h_nonce);
hchacha20 (derived_key, nonce, key);
for (i = 0; i < (sizeof (derived_key) / sizeof (derived_key[0])); i++)
- (derived_key[i]) = htole32 ((derived_key[i]));
+ (derived_key[i]) = clib_host_to_little_u32 ((derived_key[i]));
uint32_t key_idx;
diff --git a/src/plugins/wireguard/wireguard_noise.c b/src/plugins/wireguard/wireguard_noise.c
index 5fe2e44b03b..c3f28f442f5 100644
--- a/src/plugins/wireguard/wireguard_noise.c
+++ b/src/plugins/wireguard/wireguard_noise.c
@@ -751,8 +751,8 @@ noise_tai64n_now (uint8_t output[NOISE_TIMESTAMP_LEN])
unix_nanosec &= REJECT_INTERVAL_MASK;
/* https://cr.yp.to/libtai/tai64.html */
- sec = htobe64 (0x400000000000000aULL + unix_sec);
- nsec = htobe32 (unix_nanosec);
+ sec = clib_host_to_big_u64 (0x400000000000000aULL + unix_sec);
+ nsec = clib_host_to_big_u32 (unix_nanosec);
/* memcpy to output buffer, assuming output could be unaligned. */
clib_memcpy (output, &sec, sizeof (sec));
diff --git a/src/tools/vppapigen/vppapigen_c.py b/src/tools/vppapigen/vppapigen_c.py
index fb7de0a023f..c2e1e7da7b7 100755
--- a/src/tools/vppapigen/vppapigen_c.py
+++ b/src/tools/vppapigen/vppapigen_c.py
@@ -365,7 +365,7 @@ class FromJSON:
write(" char *p = cJSON_GetStringValue(item);\n")
write(" size_t plen = strlen(p);\n")
write(
- " {msgvar} = cJSON_realloc({msgvar}, {msgsize} + plen, {msgsize});\n".format(
+ " {msgvar} = cJSON_realloc({msgvar}, {msgsize} + plen);\n".format(
msgvar=msgvar, msgsize=msgsize
)
)
@@ -434,7 +434,7 @@ class FromJSON:
cJSON *array = cJSON_GetObjectItem(o, "{n}");
int size = cJSON_GetArraySize(array);
{lfield} = size;
- {realloc} = cJSON_realloc({realloc}, {msgsize} + sizeof({t}) * size, {msgsize});
+ {realloc} = cJSON_realloc({realloc}, {msgsize} + sizeof({t}) * size);
{t} *d = (void *){realloc} + {msgsize};
{msgsize} += sizeof({t}) * size;
for (i = 0; i < size; i++) {{
@@ -461,12 +461,12 @@ class FromJSON:
write(
" {realloc} = cJSON_realloc({realloc}, {msgsize} + "
- "vec_len(s), {msgsize});\n".format(
+ "vec_len(s));\n".format(
msgvar=msgvar, msgsize=msgsize, realloc=realloc
)
)
write(
- " memcpy((void *){realloc} + {msgsize}, s, "
+ " clib_memcpy((void *){realloc} + {msgsize}, s, "
"vec_len(s));\n".format(realloc=realloc, msgsize=msgsize)
)
write(" {msgsize} += vec_len(s);\n".format(msgsize=msgsize))
@@ -1143,20 +1143,14 @@ ENDIAN_STRINGS = {
}
-def get_endian_string(o, type):
+def get_endian_string(o, fieldtype):
"""Return proper endian string conversion function"""
- try:
- if o.to_network:
- return ENDIAN_STRINGS[type].replace("net_to_host", "host_to_net")
- except:
- pass
- return ENDIAN_STRINGS[type]
+ return ENDIAN_STRINGS[fieldtype]
def endianfun_array(o):
"""Generate endian functions for arrays"""
forloop = """\
- {comment}
ASSERT((u32){length} <= (u32)VL_API_MAX_ARRAY_SIZE);
for (i = 0; i < {length}; i++) {{
a->{name}[i] = {format}(a->{name}[i]);
@@ -1165,31 +1159,26 @@ def endianfun_array(o):
forloop_format = """\
for (i = 0; i < {length}; i++) {{
- {type}_endian(&a->{name}[i]);
+ {type}_endian(&a->{name}[i], to_net);
}}
"""
- to_network_comment = ""
- try:
- if o.to_network:
- to_network_comment = """/*
- * Array fields processed first to handle variable length arrays and size
- * field endian conversion in the proper order for to-network messages.
- * Message fields have been sorted by type in the code generator, thus fields
- * in this generated code may be converted in a different order than specified
- * in the *.api file.
- */"""
- except:
- pass
-
output = ""
if o.fieldtype == "u8" or o.fieldtype == "string" or o.fieldtype == "bool":
output += " /* a->{n} = a->{n} (no-op) */\n".format(n=o.fieldname)
else:
lfield = "a->" + o.lengthfield if o.lengthfield else o.length
+ if o.lengthfield:
+ output += (
+ f" u32 count = to_net ? clib_host_to_net_u32(a->{o.lengthfield}) : "
+ f"a->{o.lengthfield};\n"
+ )
+ lfield = "count"
+ else:
+ lfield = o.length
+
if o.fieldtype in ENDIAN_STRINGS:
output += forloop.format(
- comment=to_network_comment,
length=lfield,
format=get_endian_string(o, o.fieldtype),
name=o.fieldname,
@@ -1222,7 +1211,7 @@ def endianfun_obj(o):
name=o.fieldname, format=get_endian_string(o, o.fieldtype)
)
elif o.fieldtype.startswith("vl_api_"):
- output += " {type}_endian(&a->{name});\n".format(
+ output += " {type}_endian(&a->{name}, to_net);\n".format(
type=o.fieldtype, name=o.fieldname
)
else:
@@ -1254,19 +1243,12 @@ def endianfun(objs, modulename):
output = output.format(module=modulename)
signature = """\
-static inline void vl_api_{name}_t_endian (vl_api_{name}_t *a)
+static inline void vl_api_{name}_t_endian (vl_api_{name}_t *a, bool to_net)
{{
int i __attribute__((unused));
"""
for t in objs:
- # Outbound (to network) messages are identified by message nomenclature
- # i.e. message names ending with these suffixes are 'to network'
- if t.name.endswith("_reply") or t.name.endswith("_details"):
- t.to_network = True
- else:
- t.to_network = False
-
if t.__class__.__name__ == "Enum" or t.__class__.__name__ == "EnumFlag":
output += signature.format(name=t.name)
if t.enumtype in ENDIAN_STRINGS:
@@ -1300,15 +1282,7 @@ static inline void vl_api_{name}_t_endian (vl_api_{name}_t *a)
output += signature.format(name=t.name)
- # For outbound (to network) messages:
- # some arrays have dynamic length -- iterate over
- # them before changing endianness for the length field
- # by making the Array types show up first
- if t.to_network:
- t.block.sort(key=lambda x: x.type)
-
for o in t.block:
- o.to_network = t.to_network
output += endianfun_obj(o)
output += "}\n\n"
@@ -1852,7 +1826,7 @@ api_{n} (cJSON *o)
}}
mp->_vl_msg_id = vac_get_msg_index(VL_API_{N}_CRC);
- vl_api_{n}_t_endian(mp);
+ vl_api_{n}_t_endian(mp, 1);
vac_write((char *)mp, len);
cJSON_free(mp);
@@ -1867,7 +1841,7 @@ api_{n} (cJSON *o)
return 0;
}}
vl_api_{r}_t *rmp = (vl_api_{r}_t *)p;
- vl_api_{r}_t_endian(rmp);
+ vl_api_{r}_t_endian(rmp, 0);
return vl_api_{r}_t_tojson(rmp);
}}
@@ -1885,7 +1859,7 @@ api_{n} (cJSON *o)
return 0;
}}
mp->_vl_msg_id = msg_id;
- vl_api_{n}_t_endian(mp);
+ vl_api_{n}_t_endian(mp, 1);
vac_write((char *)mp, len);
cJSON_free(mp);
@@ -1919,7 +1893,7 @@ api_{n} (cJSON *o)
return 0;
}}
vl_api_{r}_t *rmp = (vl_api_{r}_t *)p;
- vl_api_{r}_t_endian(rmp);
+ vl_api_{r}_t_endian(rmp, 0);
cJSON_AddItemToArray(reply, vl_api_{r}_t_tojson(rmp));
}}
}}
@@ -1941,7 +1915,7 @@ api_{n} (cJSON *o)
}}
mp->_vl_msg_id = msg_id;
- vl_api_{n}_t_endian(mp);
+ vl_api_{n}_t_endian(mp, 1);
vac_write((char *)mp, len);
cJSON_free(mp);
@@ -1962,14 +1936,14 @@ api_{n} (cJSON *o)
u16 msg_id = ntohs(*((u16 *)p));
if (msg_id == reply_msg_id) {{
vl_api_{r}_t *rmp = (vl_api_{r}_t *)p;
- vl_api_{r}_t_endian(rmp);
+ vl_api_{r}_t_endian(rmp, 0);
cJSON_AddItemToArray(reply, vl_api_{r}_t_tojson(rmp));
break;
}}
if (msg_id == details_msg_id) {{
vl_api_{d}_t *rmp = (vl_api_{d}_t *)p;
- vl_api_{d}_t_endian(rmp);
+ vl_api_{d}_t_endian(rmp, 0);
cJSON_AddItemToArray(reply, vl_api_{d}_t_tojson(rmp));
}}
}}
diff --git a/src/vat2/vat2_helpers.h b/src/vat2/vat2_helpers.h
index 7b197608a7b..d9ce2af6b35 100644
--- a/src/vat2/vat2_helpers.h
+++ b/src/vat2/vat2_helpers.h
@@ -29,7 +29,7 @@ vat2_control_ping (u32 context)
vl_api_control_ping_t mp = {0};
mp._vl_msg_id = vac_get_msg_index(VL_API_CONTROL_PING_CRC);
mp.context = context;
- vl_api_control_ping_t_endian(&mp);
+ vl_api_control_ping_t_endian (&mp, 1 /* to network */);
vac_write((char *)&mp, sizeof(mp));
}
diff --git a/src/vlib/CMakeLists.txt b/src/vlib/CMakeLists.txt
index 7ec9b2050e9..3c354b764dd 100644
--- a/src/vlib/CMakeLists.txt
+++ b/src/vlib/CMakeLists.txt
@@ -55,6 +55,7 @@ install(
# vlib shared library
##############################################################################
+if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
set(PLATFORM_SOURCES
linux/pci.c
linux/vfio.c
@@ -64,6 +65,11 @@ set(PLATFORM_SOURCES
set(PLATFORM_HEADERS
linux/vfio.h
)
+elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "FreeBSD")
+set(PLATFORM_SOURCES
+ freebsd/pci.c
+)
+endif()
add_vpp_library(vlib
SOURCES
diff --git a/src/vlib/linux/pci.c b/src/vlib/linux/pci.c
index f7c63bc3607..29ca3d97523 100644
--- a/src/vlib/linux/pci.c
+++ b/src/vlib/linux/pci.c
@@ -1561,14 +1561,17 @@ linux_pci_init (vlib_main_t * vm)
ASSERT (sizeof (vlib_pci_addr_t) == sizeof (u32));
- addrs = vlib_pci_get_all_dev_addrs ();
- vec_foreach (addr, addrs)
+ if (pm->pci_device_registrations)
{
- vlib_pci_device_info_t *d;
- if ((d = vlib_pci_get_device_info (vm, addr, 0)))
+ addrs = vlib_pci_get_all_dev_addrs ();
+ vec_foreach (addr, addrs)
{
- init_device_from_registered (vm, d);
- vlib_pci_free_device_info (d);
+ vlib_pci_device_info_t *d;
+ if ((d = vlib_pci_get_device_info (vm, addr, 0)))
+ {
+ init_device_from_registered (vm, d);
+ vlib_pci_free_device_info (d);
+ }
}
}
diff --git a/src/vlib/pci/pci.c b/src/vlib/pci/pci.c
index 0bc90c5532d..7284e6675fd 100644
--- a/src/vlib/pci/pci.c
+++ b/src/vlib/pci/pci.c
@@ -119,7 +119,7 @@ vlib_pci_intr_enable (vlib_main_t *vm, vlib_pci_dev_handle_t h)
{
const vlib_pci_config_reg_command_t cmd = { .intx_disable = 1 };
clib_error_t *err;
- int already_set;
+ int already_set = 0;
err = _vlib_pci_config_set_control_bit (vm, h, cmd.as_u16, 0, &already_set);
log_debug (h, "interrupt%senabled", already_set ? " " : " already ");
@@ -131,7 +131,7 @@ vlib_pci_intr_disable (vlib_main_t *vm, vlib_pci_dev_handle_t h)
{
const vlib_pci_config_reg_command_t cmd = { .intx_disable = 1 };
clib_error_t *err;
- int already_set;
+ int already_set = 0;
err = _vlib_pci_config_set_control_bit (vm, h, cmd.as_u16, 1, &already_set);
log_debug (h, "interrupt%sdisabled", already_set ? " " : " already ");
@@ -143,7 +143,7 @@ vlib_pci_bus_master_enable (vlib_main_t *vm, vlib_pci_dev_handle_t h)
{
const vlib_pci_config_reg_command_t cmd = { .bus_master = 1 };
clib_error_t *err;
- int already_set;
+ int already_set = 0;
err = _vlib_pci_config_set_control_bit (vm, h, cmd.as_u16, 1, &already_set);
log_debug (h, "bus-master%senabled", already_set ? " " : " already ");
@@ -155,7 +155,7 @@ vlib_pci_bus_master_disable (vlib_main_t *vm, vlib_pci_dev_handle_t h)
{
const vlib_pci_config_reg_command_t cmd = { .bus_master = 1 };
clib_error_t *err;
- int already_set;
+ int already_set = 0;
err = _vlib_pci_config_set_control_bit (vm, h, cmd.as_u16, 0, &already_set);
log_debug (h, "bus-master%sdisabled", already_set ? " " : " already ");
diff --git a/src/vlib/threads.c b/src/vlib/threads.c
index bbcb4ec2979..ef2c5616f21 100644
--- a/src/vlib/threads.c
+++ b/src/vlib/threads.c
@@ -182,9 +182,7 @@ vlib_thread_init (vlib_main_t * vm)
u32 n_vlib_mains = 1;
u32 first_index = 1;
u32 i;
- pid_t pid;
- uword *avail_cpu, *affinity_cpu;
- uword n_cpus;
+ uword *avail_cpu;
u32 stats_num_worker_threads_dir_index;
stats_num_worker_threads_dir_index =
@@ -195,41 +193,22 @@ vlib_thread_init (vlib_main_t * vm)
tm->cpu_core_bitmap = os_get_online_cpu_core_bitmap ();
tm->cpu_socket_bitmap = os_get_online_cpu_node_bitmap ();
- /* get bitmap of active cpu cores vpp has affinity to */
- pid = getpid ();
- tm->cpu_affinity_bitmap = os_get_cpu_affinity_bitmap (pid);
-
- /* if fetching affinity fails, return online cpu core bmp */
- if (tm->cpu_affinity_bitmap == 0)
- tm->cpu_affinity_bitmap = os_get_online_cpu_core_bitmap ();
-
avail_cpu = clib_bitmap_dup (tm->cpu_core_bitmap);
- affinity_cpu = clib_bitmap_dup (tm->cpu_affinity_bitmap);
/* skip cores */
- n_cpus = clib_bitmap_count_set_bits (avail_cpu);
- if (tm->skip_cores >= n_cpus)
- return clib_error_return (0, "skip-core greater than available cpus");
- n_cpus = clib_bitmap_count_set_bits (affinity_cpu);
- if (tm->skip_cores >= n_cpus)
- return clib_error_return (0, "skip-core greater than affinity cpus");
-
for (i = 0; i < tm->skip_cores; i++)
{
- uword c;
- c = clib_bitmap_first_set (avail_cpu);
+ uword c = clib_bitmap_first_set (avail_cpu);
if (c == ~0)
return clib_error_return (0, "no available cpus to skip");
avail_cpu = clib_bitmap_set (avail_cpu, c, 0);
-
- c = clib_bitmap_first_set (affinity_cpu);
- if (c == ~0)
- return clib_error_return (0, "no available env cpus to skip");
-
- affinity_cpu = clib_bitmap_set (affinity_cpu, c, 0);
}
+ /* if main thread affinity is unspecified, set to current running cpu */
+ if (tm->main_lcore == ~0)
+ tm->main_lcore = sched_getcpu ();
+
/* grab cpu for main thread */
if (tm->main_lcore != ~0)
{
@@ -237,17 +216,6 @@ vlib_thread_init (vlib_main_t * vm)
return clib_error_return (0, "cpu %u is not available to be used"
" for the main thread", tm->main_lcore);
avail_cpu = clib_bitmap_set (avail_cpu, tm->main_lcore, 0);
- affinity_cpu = clib_bitmap_set (affinity_cpu, tm->main_lcore, 0);
- }
- /* if auto enabled, grab first cpu vpp has affinity to for main thread */
- else if (tm->use_main_core_auto)
- {
- uword c = clib_bitmap_first_set (affinity_cpu);
- if (c != ~0)
- tm->main_lcore = c;
-
- avail_cpu = clib_bitmap_set (avail_cpu, tm->main_lcore, 0);
- affinity_cpu = clib_bitmap_set (affinity_cpu, tm->main_lcore, 0);
}
/* assume that there is socket 0 only if there is no data from sysfs */
@@ -332,23 +300,13 @@ vlib_thread_init (vlib_main_t * vm)
}
else
{
- /* for automatic pinning, use cpu affinity list */
- uword n_env_cpu = 0;
- n_env_cpu = clib_bitmap_count_set_bits (affinity_cpu);
-
- if (n_env_cpu < tr->count)
- return clib_error_return (0,
- "no available cpus to be used for"
- " the '%s' thread #%u",
- tr->name, n_env_cpu);
-
for (j = 0; j < tr->count; j++)
{
/* Do not use CPU 0 by default - leave it to the host and IRQs */
- uword avail_c0 = clib_bitmap_get (affinity_cpu, 0);
- affinity_cpu = clib_bitmap_set (affinity_cpu, 0, 0);
+ uword avail_c0 = clib_bitmap_get (avail_cpu, 0);
+ avail_cpu = clib_bitmap_set (avail_cpu, 0, 0);
- uword c = clib_bitmap_first_set (affinity_cpu);
+ uword c = clib_bitmap_first_set (avail_cpu);
/* Use CPU 0 as a last resort */
if (c == ~0 && avail_c0)
{
@@ -362,15 +320,14 @@ vlib_thread_init (vlib_main_t * vm)
" the '%s' thread #%u",
tr->name, tr->count);
- affinity_cpu = clib_bitmap_set (affinity_cpu, 0, avail_c0);
- affinity_cpu = clib_bitmap_set (affinity_cpu, c, 0);
+ avail_cpu = clib_bitmap_set (avail_cpu, 0, avail_c0);
+ avail_cpu = clib_bitmap_set (avail_cpu, c, 0);
tr->coremask = clib_bitmap_set (tr->coremask, c, 1);
}
}
}
clib_bitmap_free (avail_cpu);
- clib_bitmap_free (affinity_cpu);
tm->n_vlib_mains = n_vlib_mains;
vlib_stats_set_gauge (stats_num_worker_threads_dir_index, n_vlib_mains - 1);
@@ -417,6 +374,8 @@ void
vlib_worker_thread_init (vlib_worker_thread_t * w)
{
vlib_thread_main_t *tm = vlib_get_thread_main ();
+ sigset_t signals;
+ int rv;
/*
* Note: disabling signals in worker threads as follows
@@ -426,7 +385,17 @@ vlib_worker_thread_init (vlib_worker_thread_t * w)
* sigfillset (&s);
* pthread_sigmask (SIG_SETMASK, &s, 0);
* }
+ * We can still disable signals for SIGINT,SIGHUP and SIGTERM as they don't
+ * trigger post-dump handlers anyway.
*/
+ sigemptyset (&signals);
+ sigaddset (&signals, SIGINT);
+ sigaddset (&signals, SIGHUP);
+ sigaddset (&signals, SIGTERM);
+ rv = pthread_sigmask (SIG_BLOCK, &signals, NULL);
+
+ if (rv)
+ clib_warning ("Failed to set the worker signal mask");
clib_mem_set_heap (w->thread_mheap);
@@ -1169,6 +1138,7 @@ cpu_config (vlib_main_t * vm, unformat_input_t * input)
u8 *name;
uword *bitmap;
u32 count;
+ int use_corelist = 0;
tm->thread_registrations_by_name = hash_create_string (0, sizeof (uword));
@@ -1176,7 +1146,6 @@ cpu_config (vlib_main_t * vm, unformat_input_t * input)
tm->sched_policy = ~0;
tm->sched_priority = ~0;
tm->main_lcore = ~0;
- tm->use_main_core_auto = 0;
tr = tm->next;
@@ -1192,8 +1161,6 @@ cpu_config (vlib_main_t * vm, unformat_input_t * input)
tm->use_pthreads = 1;
else if (unformat (input, "thread-prefix %v", &tm->thread_prefix))
;
- else if (unformat (input, "main-core auto"))
- tm->use_main_core_auto = 1;
else if (unformat (input, "main-core %u", &tm->main_lcore))
;
else if (unformat (input, "skip-cores %u", &tm->skip_cores))
@@ -1223,6 +1190,7 @@ cpu_config (vlib_main_t * vm, unformat_input_t * input)
tr->coremask = bitmap;
tr->count = clib_bitmap_count_set_bits (tr->coremask);
+ use_corelist = 1;
}
else
if (unformat
@@ -1252,13 +1220,9 @@ cpu_config (vlib_main_t * vm, unformat_input_t * input)
break;
}
- if (tm->main_lcore != ~0 && tm->use_main_core_auto)
- {
- return clib_error_return (
- 0, "cannot set both 'main-core %u' and 'main-core auto'",
- tm->main_lcore);
- }
-
+ if (use_corelist && tm->main_lcore == ~0)
+ return clib_error_return (0, "main-core must be specified when using "
+ "corelist-* or coremask-* attribute");
if (tm->sched_priority != ~0)
{
if (tm->sched_policy == SCHED_FIFO || tm->sched_policy == SCHED_RR)
diff --git a/src/vlib/threads.h b/src/vlib/threads.h
index 3072d0e67dd..ac0c1d5d266 100644
--- a/src/vlib/threads.h
+++ b/src/vlib/threads.h
@@ -255,8 +255,6 @@ typedef struct
int use_pthreads;
- int use_main_core_auto;
-
/* Number of vlib_main / vnet_main clones */
u32 n_vlib_mains;
@@ -284,9 +282,6 @@ typedef struct
/* Bitmap of available CPU sockets (NUMA nodes) */
uword *cpu_socket_bitmap;
- /* Bitmap of CPU affinity for VPP process */
- uword *cpu_affinity_bitmap;
-
/* Worker handoff queues */
vlib_frame_queue_main_t *frame_queue_mains;
diff --git a/src/vlib/unix/main.c b/src/vlib/unix/main.c
index ee28ca8f1aa..11d0cb1160c 100644
--- a/src/vlib/unix/main.c
+++ b/src/vlib/unix/main.c
@@ -40,6 +40,8 @@
#include <vlib/unix/unix.h>
#include <vlib/unix/plugin.h>
#include <vppinfra/unix.h>
+#include <vppinfra/stack.h>
+#include <vppinfra/format_ansi.h>
#include <limits.h>
#include <signal.h>
@@ -97,20 +99,42 @@ int vlib_last_signum = 0;
uword vlib_last_faulting_address = 0;
static void
+log_one_line ()
+{
+ vec_terminate_c_string (syslog_msg);
+ if (unix_main.flags & (UNIX_FLAG_INTERACTIVE | UNIX_FLAG_NOSYSLOG))
+ fprintf (stderr, "%s\n", syslog_msg);
+ else
+ syslog (LOG_ERR | LOG_DAEMON, "%s", syslog_msg);
+ vec_reset_length (syslog_msg);
+}
+
+static void
unix_signal_handler (int signum, siginfo_t * si, ucontext_t * uc)
{
uword fatal = 0;
+ int color =
+ (unix_main.flags & (UNIX_FLAG_INTERACTIVE | UNIX_FLAG_NOSYSLOG)) &&
+ (unix_main.flags & UNIX_FLAG_NOCOLOR) == 0;
/* These come in handy when looking at core files from optimized images */
vlib_last_signum = signum;
vlib_last_faulting_address = (uword) si->si_addr;
+ if (color)
+ syslog_msg = format (syslog_msg, ANSI_FG_BR_RED);
+
syslog_msg = format (syslog_msg, "received signal %U, PC %U",
format_signal, signum, format_ucontext_pc, uc);
- if (signum == SIGSEGV)
+ if (signum == SIGSEGV || signum == SIGBUS)
syslog_msg = format (syslog_msg, ", faulting address %p", si->si_addr);
+ if (color)
+ syslog_msg = format (syslog_msg, ANSI_FG_DEFAULT);
+
+ log_one_line ();
+
switch (signum)
{
/* these (caught) signals cause the application to exit */
@@ -120,11 +144,17 @@ unix_signal_handler (int signum, siginfo_t * si, ucontext_t * uc)
*/
if (unix_main.vlib_main && unix_main.vlib_main->main_loop_exit_set)
{
- syslog (LOG_ERR | LOG_DAEMON, "received SIGTERM, exiting...");
+ syslog_msg = format (
+ syslog_msg, "received SIGTERM from PID %d UID %d, exiting...",
+ si->si_pid, si->si_uid);
+ log_one_line ();
unix_main.vlib_main->main_loop_exit_now = 1;
}
else
- syslog (LOG_ERR | LOG_DAEMON, "IGNORE early SIGTERM...");
+ {
+ syslog_msg = format (syslog_msg, "IGNORE early SIGTERM...");
+ log_one_line ();
+ }
break;
/* fall through */
case SIGQUIT:
@@ -144,26 +174,75 @@ unix_signal_handler (int signum, siginfo_t * si, ucontext_t * uc)
break;
}
- /* Null terminate. */
- vec_add1 (syslog_msg, 0);
if (fatal)
{
- syslog (LOG_ERR | LOG_DAEMON, "%s", syslog_msg);
+ int skip = 1, index = 0;
- /* Address of callers: outer first, inner last. */
- uword callers[15];
- uword n_callers = clib_backtrace (callers, ARRAY_LEN (callers), 0);
- int i;
- for (i = 0; i < n_callers; i++)
+ foreach_clib_stack_frame (sf)
{
- vec_reset_length (syslog_msg);
+ if (sf->is_signal_frame)
+ {
+ int pipefd[2];
+ const int n_bytes = 20;
+ u8 *ip = (void *) sf->ip;
+
+ if (pipe (pipefd) == 0)
+ {
+ /* check PC points to valid memory */
+ if (write (pipefd[1], ip, n_bytes) == n_bytes)
+ {
+ syslog_msg = format (syslog_msg, "Code: ");
+ if (color)
+ syslog_msg = format (syslog_msg, ANSI_FG_CYAN);
+ for (int i = 0; i < n_bytes; i++)
+ syslog_msg = format (syslog_msg, " %02x", ip[i]);
+ if (color)
+ syslog_msg = format (syslog_msg, ANSI_FG_DEFAULT);
+ }
+ else
+ {
+ syslog_msg = format (
+ syslog_msg, "PC contains invalid memory address");
+ }
+ log_one_line ();
+ foreach_int (i, 0, 1)
+ close (pipefd[i]);
+ }
+ skip = 0;
+ }
+
+ if (skip)
+ continue;
+
+ syslog_msg = format (syslog_msg, "#%-2d ", index++);
+ if (color)
+ syslog_msg = format (syslog_msg, ANSI_FG_BLUE);
+ syslog_msg = format (syslog_msg, "0x%016lx", sf->ip);
+ if (color)
+ syslog_msg = format (syslog_msg, ANSI_FG_DEFAULT);
+
+ if (sf->name[0])
+ {
+ if (color)
+ syslog_msg = format (syslog_msg, ANSI_FG_YELLOW);
+ syslog_msg =
+ format (syslog_msg, " %s + 0x%x", sf->name, sf->offset);
+ if (color)
+ syslog_msg = format (syslog_msg, ANSI_FG_DEFAULT);
+ }
- syslog_msg =
- format (syslog_msg, "#%-2d 0x%016lx %U%c", i, callers[i],
- format_clib_elf_symbol_with_address, callers[i], 0);
+ log_one_line ();
- syslog (LOG_ERR | LOG_DAEMON, "%s", syslog_msg);
+ if (sf->file_name)
+ {
+ if (color)
+ syslog_msg = format (syslog_msg, ANSI_FG_GREEN);
+ syslog_msg = format (syslog_msg, " from %s", sf->file_name);
+ if (color)
+ syslog_msg = format (syslog_msg, ANSI_FG_DEFAULT);
+ log_one_line ();
+ }
}
/* have to remove SIGABRT to avoid recursive - os_exit calling abort() */
@@ -175,9 +254,6 @@ unix_signal_handler (int signum, siginfo_t * si, ucontext_t * uc)
else
os_exit (1);
}
- else
- clib_warning ("%s", syslog_msg);
-
}
static clib_error_t *
diff --git a/src/vlib/unix/plugin.c b/src/vlib/unix/plugin.c
index fd3a050b944..5cac9abc8fe 100644
--- a/src/vlib/unix/plugin.c
+++ b/src/vlib/unix/plugin.c
@@ -306,8 +306,12 @@ process_reg:
}
vec_free (version_required);
+#if defined(RTLD_DEEPBIND)
handle = dlopen ((char *) pi->filename,
RTLD_LAZY | (reg->deep_bind ? RTLD_DEEPBIND : 0));
+#else
+ handle = dlopen ((char *) pi->filename, RTLD_LAZY);
+#endif
if (handle == 0)
{
diff --git a/src/vlibapi/api_common.h b/src/vlibapi/api_common.h
index 62a8d4c62d8..c09334136c0 100644
--- a/src/vlibapi/api_common.h
+++ b/src/vlibapi/api_common.h
@@ -235,8 +235,8 @@ typedef struct
/** Message convert function vector */
void *(*fromjson_handler) (cJSON *, int *);
- /** Message endian handler vector */
- void (*endian_handler) (void *);
+ /** Message endian handler vector. */
+ void (*endian_handler) (void *, bool to_net);
/** Message calc size function vector */
uword (*calc_size_func) (void *);
diff --git a/src/vlibapi/api_helper_macros.h b/src/vlibapi/api_helper_macros.h
index 9c93d33934b..0380692b80e 100644
--- a/src/vlibapi/api_helper_macros.h
+++ b/src/vlibapi/api_helper_macros.h
@@ -29,9 +29,9 @@
#define _NATIVE_TO_NETWORK(t, rmp) \
api_main_t *am = vlibapi_get_main (); \
- void (*endian_fp) (void *); \
+ void (*endian_fp) (void *, bool); \
endian_fp = am->msg_data[t + (REPLY_MSG_ID_BASE)].endian_handler; \
- (*endian_fp) (rmp);
+ (*endian_fp) (rmp, 1 /* to network */);
#define REPLY_MACRO(msg) \
do \
diff --git a/src/vlibapi/api_shared.c b/src/vlibapi/api_shared.c
index 7de1906f17a..79064b292c9 100644
--- a/src/vlibapi/api_shared.c
+++ b/src/vlibapi/api_shared.c
@@ -230,7 +230,7 @@ vl_msg_api_trace_write_one (api_main_t *am, u8 *msg, FILE *fp)
if (m && m->endian_handler)
{
- m->endian_handler (tmpmem);
+ m->endian_handler (tmpmem, 1);
}
if (m && m->tojson_handler)
@@ -561,7 +561,7 @@ msg_handler_internal (api_main_t *am, void *the_msg, uword msg_len,
}
if (m->is_autoendian)
- m->endian_handler (the_msg);
+ m->endian_handler (the_msg, 0);
if (PREDICT_FALSE (vec_len (am->perf_counter_cbs) != 0))
clib_call_callbacks (am->perf_counter_cbs, am, id,
diff --git a/src/vlibmemory/memclnt_api.c b/src/vlibmemory/memclnt_api.c
index d4106b10559..b0b0c72eae0 100644
--- a/src/vlibmemory/memclnt_api.c
+++ b/src/vlibmemory/memclnt_api.c
@@ -197,6 +197,7 @@ vlib_api_init (void)
cJSON_Hooks cjson_hooks = {
.malloc_fn = clib_mem_alloc,
.free_fn = clib_mem_free,
+ .realloc_fn = clib_mem_realloc,
};
cJSON_InitHooks (&cjson_hooks);
diff --git a/src/vlibmemory/memory_api.c b/src/vlibmemory/memory_api.c
index 39c6b0fd15b..57373b91e31 100644
--- a/src/vlibmemory/memory_api.c
+++ b/src/vlibmemory/memory_api.c
@@ -823,9 +823,9 @@ vl_mem_api_handler_with_vm_node (api_main_t *am, svm_region_t *vlib_rp,
if (m->is_autoendian)
{
- void (*endian_fp) (void *);
+ void (*endian_fp) (void *, bool);
endian_fp = am->msg_data[id].endian_handler;
- (*endian_fp) (the_msg);
+ (*endian_fp) (the_msg, 0);
}
if (PREDICT_FALSE (vec_len (am->perf_counter_cbs) != 0))
clib_call_callbacks (am->perf_counter_cbs, am, id, 0 /* before */);
diff --git a/src/vlibmemory/vlib_api_cli.c b/src/vlibmemory/vlib_api_cli.c
index 4492f5af980..6ae81cd13df 100644
--- a/src/vlibmemory/vlib_api_cli.c
+++ b/src/vlibmemory/vlib_api_cli.c
@@ -554,7 +554,7 @@ vl_msg_api_process_file (vlib_main_t * vm, u8 * filename,
}
if (m)
{
- m->endian_handler (tmpbuf + sizeof (uword));
+ m->endian_handler (tmpbuf + sizeof (uword), 1 /* to network */);
}
}
@@ -674,7 +674,7 @@ vl_msg_print_trace (u8 *msg, void *ctx)
clib_memcpy_fast (tmpbuf, msg, msg_length);
msg = tmpbuf;
- m->endian_handler (tmpbuf);
+ m->endian_handler (tmpbuf, 0 /* from network */);
}
vlib_cli_output (a->vm, "%U\n",
@@ -824,7 +824,7 @@ vl_msg_exec_json_command (vlib_main_t *vm, cJSON *o)
}
if (clib_arch_is_little_endian)
- m->endian_handler (msg);
+ m->endian_handler (msg, 1 /* to network */);
if (!m->handler)
{
diff --git a/src/vnet/CMakeLists.txt b/src/vnet/CMakeLists.txt
index fb8d294009d..eb74f5de84c 100644
--- a/src/vnet/CMakeLists.txt
+++ b/src/vnet/CMakeLists.txt
@@ -813,24 +813,6 @@ list(APPEND VNET_API_FILES
)
##############################################################################
-# mpls segment routing
-##############################################################################
-
-list(APPEND VNET_SOURCES
- srmpls/sr_mpls_policy.c
- srmpls/sr_mpls_steering.c
- srmpls/sr_mpls_api.c
-)
-
-list(APPEND VNET_HEADERS
- srmpls/sr_mpls.h
-)
-
-list(APPEND VNET_API_FILES
- srmpls/sr_mpls.api
-)
-
-##############################################################################
# IPFIX / netflow v10
##############################################################################
list(APPEND VNET_SOURCES
@@ -1162,6 +1144,7 @@ list(APPEND VNET_HEADERS
fib/fib_path_list.h
fib/fib_sas.h
fib/fib_source.h
+ fib/fib_urpf_list.h
)
list(APPEND VNET_API_FILES
@@ -1460,7 +1443,6 @@ add_vat_test_library(vnet
ip/ip_test.c
arp/arp_test.c
ip6-nd/ip6_nd_test.c
- srmpls/sr_mpls_test.c
session/session_test.c
l2/l2_test.c
ipsec/ipsec_test.c
diff --git a/src/vnet/dev/format.c b/src/vnet/dev/format.c
index ed83a0eba95..f599c0f8b85 100644
--- a/src/vnet/dev/format.c
+++ b/src/vnet/dev/format.c
@@ -101,7 +101,7 @@ format_vnet_dev_port_info (u8 *s, va_list *args)
u32 indent = format_get_indent (s);
s = format (s, "Hardware Address is %U", format_vnet_dev_hw_addr,
- &port->attr.hw_addr);
+ &port->primary_hw_addr);
s = format (s, ", %u RX queues (max %u), %u TX queues (max %u)",
pool_elts (port->rx_queues), port->attr.max_rx_queues,
pool_elts (port->tx_queues), port->attr.max_tx_queues);
diff --git a/src/vnet/devices/virtio/node.c b/src/vnet/devices/virtio/node.c
index 8c837575cf8..027e1ed4e74 100644
--- a/src/vnet/devices/virtio/node.c
+++ b/src/vnet/devices/virtio/node.c
@@ -282,6 +282,16 @@ virtio_device_input_gso_inline (vlib_main_t *vm, vlib_node_runtime_t *node,
if (n_left == 0)
return 0;
+ if (PREDICT_FALSE (n_left == vring->queue_size))
+ {
+ /*
+ * Informational error logging when VPP is not pulling packets fast
+ * enough.
+ */
+ vlib_error_count (vm, node->node_index, VIRTIO_INPUT_ERROR_FULL_RX_QUEUE,
+ 1);
+ }
+
if (type == VIRTIO_IF_TYPE_TUN)
{
next_index = VNET_DEVICE_INPUT_NEXT_IP4_INPUT;
diff --git a/src/vnet/devices/virtio/virtio_inline.h b/src/vnet/devices/virtio/virtio_inline.h
index 179f319aa4c..41bba755934 100644
--- a/src/vnet/devices/virtio/virtio_inline.h
+++ b/src/vnet/devices/virtio/virtio_inline.h
@@ -17,6 +17,7 @@
#define foreach_virtio_input_error \
_ (BUFFER_ALLOC, "buffer alloc error") \
+ _ (FULL_RX_QUEUE, "full rx queue (driver tx drop)") \
_ (UNKNOWN, "unknown")
typedef enum
diff --git a/src/vnet/ethernet/node.c b/src/vnet/ethernet/node.c
index e2558eeca41..03cbdde1c2b 100644
--- a/src/vnet/ethernet/node.c
+++ b/src/vnet/ethernet/node.c
@@ -982,8 +982,31 @@ eth_input_process_frame (vlib_main_t * vm, vlib_node_runtime_t * node,
else
{
for (int j = 0; j < 16; j++)
- if (next[j] == 0)
- slowpath_indices[n_slowpath++] = i + j;
+ {
+ if (next[j] == 0)
+ slowpath_indices[n_slowpath++] = i + j;
+ else if (dmac_check && main_is_l3 && dmacs_bad[i + j])
+ {
+ next[j] = 0;
+ slowpath_indices[n_slowpath++] = i + j;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (dmac_check && main_is_l3)
+ {
+ u8x16 dmac_bad = u8x16_load_unaligned (&dmacs_bad[i]);
+ if (!u8x16_is_all_zero (dmac_bad))
+ {
+ for (int j = 0; j < 16; j++)
+ if (dmacs_bad[i + j])
+ {
+ next[j] = 0;
+ slowpath_indices[n_slowpath++] = i + j;
+ }
+ }
}
}
@@ -994,7 +1017,12 @@ eth_input_process_frame (vlib_main_t * vm, vlib_node_runtime_t * node,
continue;
}
#endif
- if (main_is_l3 && etype[0] == et_ip4)
+ if (dmac_check && main_is_l3 && dmacs_bad[i])
+ {
+ next[0] = 0;
+ slowpath_indices[n_slowpath++] = i;
+ }
+ else if (main_is_l3 && etype[0] == et_ip4)
next[0] = next_ip4;
else if (main_is_l3 && etype[0] == et_ip6)
next[0] = next_ip6;
@@ -1052,7 +1080,7 @@ eth_input_process_frame (vlib_main_t * vm, vlib_node_runtime_t * node,
}
else
{
- /* untagged packet with not well known etyertype */
+ /* untagged packet with not well known ethertype */
if (last_unknown_etype != etype)
{
last_unknown_etype = etype;
diff --git a/src/vnet/ip-neighbor/ip_neighbor.c b/src/vnet/ip-neighbor/ip_neighbor.c
index d340037a15d..614b78489cd 100644
--- a/src/vnet/ip-neighbor/ip_neighbor.c
+++ b/src/vnet/ip-neighbor/ip_neighbor.c
@@ -460,6 +460,7 @@ ip_neighbor_destroy (ip_neighbor_t * ipn)
af = ip_neighbor_get_af (ipn);
IP_NEIGHBOR_DBG ("free: %U", format_ip_neighbor,
+ vlib_time_now (vlib_get_main ()),
ip_neighbor_get_index (ipn));
ip_neighbor_publish (ip_neighbor_get_index (ipn),
@@ -944,20 +945,20 @@ ip_neighbor_show_sorted_i (vlib_main_t * vm,
vlib_cli_command_t * cmd, ip_address_family_t af)
{
ip_neighbor_elt_t *elt, *head;
+ f64 now;
head = pool_elt_at_index (ip_neighbor_elt_pool, ip_neighbor_list_head[af]);
+ now = vlib_time_now (vm);
-
- vlib_cli_output (vm, "%=12s%=40s%=6s%=20s%=24s", "Time", "IP",
- "Flags", "Ethernet", "Interface");
+ vlib_cli_output (vm, "%=12s%=40s%=6s%=20s%=24s", "Age", "IP", "Flags",
+ "Ethernet", "Interface");
/* the list is time sorted, newest first, so start from the back
* and work forwards. Stop when we get to one that is alive */
- clib_llist_foreach_reverse(ip_neighbor_elt_pool,
- ipne_anchor, head, elt,
- ({
- vlib_cli_output (vm, "%U", format_ip_neighbor, elt->ipne_index);
- }));
+ clib_llist_foreach_reverse (ip_neighbor_elt_pool, ipne_anchor, head, elt, ({
+ vlib_cli_output (vm, "%U", format_ip_neighbor,
+ now, elt->ipne_index);
+ }));
return (NULL);
}
@@ -969,6 +970,7 @@ ip_neighbor_show_i (vlib_main_t * vm,
{
index_t *ipni, *ipnis = NULL;
u32 sw_if_index;
+ f64 now;
/* Filter entries by interface if given. */
sw_if_index = ~0;
@@ -976,14 +978,15 @@ ip_neighbor_show_i (vlib_main_t * vm,
&sw_if_index);
ipnis = ip_neighbor_entries (sw_if_index, af);
+ now = vlib_time_now (vm);
if (ipnis)
- vlib_cli_output (vm, "%=12s%=40s%=6s%=20s%=24s", "Time", "IP",
- "Flags", "Ethernet", "Interface");
+ vlib_cli_output (vm, "%=12s%=40s%=6s%=20s%=24s", "Age", "IP", "Flags",
+ "Ethernet", "Interface");
vec_foreach (ipni, ipnis)
{
- vlib_cli_output (vm, "%U", format_ip_neighbor, *ipni);
+ vlib_cli_output (vm, "%U", format_ip_neighbor, now, *ipni);
}
vec_free (ipnis);
@@ -1573,13 +1576,12 @@ ip_neighbour_age_out (index_t ipni, f64 now, f64 * wait)
if (ttl > ipndb_age)
{
- IP_NEIGHBOR_DBG ("aged: %U @%f - %f > %d",
- format_ip_neighbor, ipni, now,
- ipn->ipn_time_last_updated, ipndb_age);
+ IP_NEIGHBOR_DBG ("aged: %U @%f - %f > %d", format_ip_neighbor, now, ipni,
+ now, ipn->ipn_time_last_updated, ipndb_age);
if (ipn->ipn_n_probes > 2)
{
/* 3 strikes and yea-re out */
- IP_NEIGHBOR_DBG ("dead: %U", format_ip_neighbor, ipni);
+ IP_NEIGHBOR_DBG ("dead: %U", format_ip_neighbor, now, ipni);
*wait = 1;
return (IP_NEIGHBOR_AGE_DEAD);
}
diff --git a/src/vnet/ip-neighbor/ip_neighbor_types.c b/src/vnet/ip-neighbor/ip_neighbor_types.c
index 39039a48249..a6f3c26d42f 100644
--- a/src/vnet/ip-neighbor/ip_neighbor_types.c
+++ b/src/vnet/ip-neighbor/ip_neighbor_types.c
@@ -68,19 +68,18 @@ format_ip_neighbor_watcher (u8 * s, va_list * va)
u8 *
format_ip_neighbor (u8 * s, va_list * va)
{
+ f64 now = va_arg (*va, f64);
index_t ipni = va_arg (*va, index_t);
ip_neighbor_t *ipn;
ipn = ip_neighbor_get (ipni);
- return (format (s, "%=12U%=40U%=6U%=20U%U",
- format_vlib_time, vlib_get_main (),
- ipn->ipn_time_last_updated,
- format_ip_address, &ipn->ipn_key->ipnk_ip,
- format_ip_neighbor_flags, ipn->ipn_flags,
- format_mac_address_t, &ipn->ipn_mac,
- format_vnet_sw_if_index_name, vnet_get_main (),
- ipn->ipn_key->ipnk_sw_if_index));
+ return (
+ format (s, "%=12U%=40U%=6U%=20U%U", format_vlib_time, vlib_get_main (),
+ now - ipn->ipn_time_last_updated, format_ip_address,
+ &ipn->ipn_key->ipnk_ip, format_ip_neighbor_flags, ipn->ipn_flags,
+ format_mac_address_t, &ipn->ipn_mac, format_vnet_sw_if_index_name,
+ vnet_get_main (), ipn->ipn_key->ipnk_sw_if_index));
}
static void
diff --git a/src/vnet/ip/icmp6.c b/src/vnet/ip/icmp6.c
index b095f679cc8..f93ebce4bf1 100644
--- a/src/vnet/ip/icmp6.c
+++ b/src/vnet/ip/icmp6.c
@@ -338,7 +338,7 @@ ip6_icmp_error (vlib_main_t * vm,
if (throttle_check (&icmp_throttle, thread_index, r0, seed))
{
- vlib_error_count (vm, node->node_index, ICMP4_ERROR_DROP, 1);
+ vlib_error_count (vm, node->node_index, ICMP6_ERROR_DROP, 1);
from += 1;
n_left_from -= 1;
continue;
diff --git a/src/vnet/session/session_lookup.c b/src/vnet/session/session_lookup.c
index 9d028dbb28c..ff20bc2d835 100644
--- a/src/vnet/session/session_lookup.c
+++ b/src/vnet/session/session_lookup.c
@@ -1184,7 +1184,6 @@ session_lookup_connection_wt6 (u32 fib_index, ip6_address_t * lcl,
rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
if (rv == 0)
{
- ASSERT ((u32) (kv6.value >> 32) == thread_index);
if (PREDICT_FALSE ((u32) (kv6.value >> 32) != thread_index))
{
*result = SESSION_LOOKUP_RESULT_WRONG_THREAD;
diff --git a/src/vnet/udp/udp.c b/src/vnet/udp/udp.c
index b3c02510232..9c1121f7cfb 100644
--- a/src/vnet/udp/udp.c
+++ b/src/vnet/udp/udp.c
@@ -232,18 +232,43 @@ udp_session_get_listener (u32 listener_index)
return &us->connection;
}
+always_inline u16
+udp_compute_checksum (vlib_main_t *vm, vlib_buffer_t *b, u8 csum_offload,
+ u8 is_ip4)
+{
+ u16 csum = 0;
+
+ if (csum_offload)
+ vnet_buffer_offload_flags_set (b, VNET_BUFFER_OFFLOAD_F_UDP_CKSUM);
+ else
+ {
+ if (is_ip4)
+ csum =
+ ip4_tcp_udp_compute_checksum (vm, b, vlib_buffer_get_current (b));
+ else
+ {
+ int bogus = 0;
+ csum = ip6_tcp_udp_icmp_compute_checksum (
+ vm, b, vlib_buffer_get_current (b), &bogus);
+ }
+ }
+
+ return csum;
+}
+
always_inline u32
udp_push_one_header (vlib_main_t *vm, udp_connection_t *uc, vlib_buffer_t *b,
u8 is_cless)
{
+ udp_header_t *uh;
+
b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
/* reuse tcp medatada for now */
vnet_buffer (b)->tcp.connection_index = uc->c_c_index;
if (!is_cless)
{
- vlib_buffer_push_udp (b, uc->c_lcl_port, uc->c_rmt_port,
- udp_csum_offload (uc));
+ uh = vlib_buffer_push_udp (b, uc->c_lcl_port, uc->c_rmt_port);
if (uc->c_is_ip4)
vlib_buffer_push_ip4_custom (vm, b, &uc->c_lcl_ip4, &uc->c_rmt_ip4,
@@ -263,8 +288,7 @@ udp_push_one_header (vlib_main_t *vm, udp_connection_t *uc, vlib_buffer_t *b,
hdr = *(session_dgram_hdr_t *) (data - sizeof (hdr));
/* Local port assumed to be bound, not overwriting it */
- vlib_buffer_push_udp (b, uc->c_lcl_port, hdr.rmt_port,
- udp_csum_offload (uc));
+ uh = vlib_buffer_push_udp (b, uc->c_lcl_port, hdr.rmt_port);
if (uc->c_is_ip4)
vlib_buffer_push_ip4_custom (vm, b, &hdr.lcl_ip.ip4, &hdr.rmt_ip.ip4,
@@ -279,6 +303,9 @@ udp_push_one_header (vlib_main_t *vm, udp_connection_t *uc, vlib_buffer_t *b,
vnet_buffer (b)->tcp.flags |= UDP_CONN_F_LISTEN;
}
+ uh->checksum =
+ udp_compute_checksum (vm, b, udp_csum_offload (uc), uc->c_is_ip4);
+
return 0;
}
diff --git a/src/vnet/udp/udp_inlines.h b/src/vnet/udp/udp_inlines.h
index f0dd44f48b5..ceec0b191b1 100644
--- a/src/vnet/udp/udp_inlines.h
+++ b/src/vnet/udp/udp_inlines.h
@@ -26,7 +26,7 @@
#include <vnet/udp/udp_encap.h>
always_inline void *
-vlib_buffer_push_udp (vlib_buffer_t * b, u16 sp, u16 dp, u8 offload_csum)
+vlib_buffer_push_udp (vlib_buffer_t *b, u16 sp, u16 dp)
{
udp_header_t *uh;
u16 udp_len = sizeof (udp_header_t) + b->current_length;
@@ -38,8 +38,6 @@ vlib_buffer_push_udp (vlib_buffer_t * b, u16 sp, u16 dp, u8 offload_csum)
uh->dst_port = dp;
uh->checksum = 0;
uh->length = clib_host_to_net_u16 (udp_len);
- if (offload_csum)
- vnet_buffer_offload_flags_set (b, VNET_BUFFER_OFFLOAD_F_UDP_CKSUM);
vnet_buffer (b)->l4_hdr_offset = (u8 *) uh - b->data;
b->flags |= VNET_BUFFER_F_L4_HDR_OFFSET_VALID;
return uh;
diff --git a/src/vpp/vnet/main.c b/src/vpp/vnet/main.c
index c57efd59a62..dd4f4cc3353 100644
--- a/src/vpp/vnet/main.c
+++ b/src/vpp/vnet/main.c
@@ -329,6 +329,10 @@ defaulted:
unformat_free (&input);
+ /* if main thread affinity is unspecified, set to current running cpu */
+ if (main_core == ~0)
+ main_core = sched_getcpu ();
+
/* set process affinity for main thread */
if (main_core != ~0)
{
diff --git a/src/vppinfra/CMakeLists.txt b/src/vppinfra/CMakeLists.txt
index 5878f0612f0..233e75d6e2a 100644
--- a/src/vppinfra/CMakeLists.txt
+++ b/src/vppinfra/CMakeLists.txt
@@ -14,6 +14,34 @@
enable_language(ASM)
##############################################################################
+# find libdl
+##############################################################################
+vpp_find_path(LIBDL_INCLUDE_DIR dlfcn.h)
+vpp_find_library(LIBDL_LIB NAMES dl)
+
+if (LIBDL_INCLUDE_DIR AND LIBDL_LIB)
+ message(STATUS "libdl found at ${LIBDL_LIB}")
+ list(APPEND VPPINFRA_LIBS ${LIBDL_LIB})
+else()
+ message(FATAL_ERROR "libdl not found")
+endif()
+
+##############################################################################
+# find libunwind
+##############################################################################
+vpp_find_path(LIBUNWIND_INCLUDE_DIR unwind.h)
+vpp_find_library(LIBUNWIND_LIB NAMES unwind libunwind)
+
+if (LIBUNWIND_INCLUDE_DIR AND LIBUNWIND_LIB)
+ message(STATUS "libunwind found at ${LIBUNWIND_LIB}")
+ list(APPEND VPPINFRA_LIBS ${LIBUNWIND_LIB})
+ add_definitions(-DHAVE_LIBUNWIND=1)
+else()
+ message(WARNING "libunwind not found - stack traces disabled")
+ add_definitions(-DHAVE_LIBUNWIND=0)
+endif()
+
+##############################################################################
# Generate vppinfra/config.h
##############################################################################
set(LOG2_CACHE_LINE_BYTES ${VPP_LOG2_CACHE_LINE_SIZE})
@@ -42,12 +70,10 @@ add_definitions(-fvisibility=hidden)
set_source_files_properties( cJSON.c jsonformat.c PROPERTIES
COMPILE_DEFINITIONS " CJSON_API_VISIBILITY " )
-
##############################################################################
# vppinfra sources
##############################################################################
set(VPPINFRA_SRCS
- backtrace.c
bitmap.c
bihash_all_vector.c
cpu.c
@@ -80,6 +106,7 @@ set(VPPINFRA_SRCS
rbtree.c
serialize.c
socket.c
+ stack.c
std-formats.c
string.c
time.c
@@ -142,6 +169,7 @@ set(VPPINFRA_HEADERS
fifo.h
file.h
format.h
+ format_ansi.h
format_table.h
hash.h
heap.h
@@ -175,6 +203,7 @@ set(VPPINFRA_HEADERS
smp.h
socket.h
sparse_vec.h
+ stack.h
string.h
time.h
time_range.h
@@ -229,18 +258,9 @@ elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "FreeBSD")
)
endif()
-if("${CMAKE_SYSTEM_NAME}" STREQUAL "FreeBSD")
- option(VPP_USE_EXTERNAL_LIBEXECINFO "Use external libexecinfo (useful for non-glibc targets)." ON)
-else()
- option(VPP_USE_EXTERNAL_LIBEXECINFO "Use external libexecinfo (useful for non-glibc targets)." OFF)
-endif()
-
-if(VPP_USE_EXTERNAL_LIBEXECINFO)
- set(EXECINFO_LIB execinfo)
-endif()
add_vpp_library(vppinfra
SOURCES ${VPPINFRA_SRCS}
- LINK_LIBRARIES m ${EXECINFO_LIB}
+ LINK_LIBRARIES m ${VPPINFRA_LIBS}
INSTALL_HEADERS ${VPPINFRA_HEADERS}
COMPONENT libvppinfra
LTO
@@ -265,6 +285,7 @@ if(VPP_BUILD_VPPINFRA_TESTS)
longjmp
macros
maplog
+ mhash
pmalloc
pool_alloc
pool_iterate
diff --git a/src/vppinfra/asm_mips.h b/src/vppinfra/asm_mips.h
deleted file mode 100644
index 7c9e69586f4..00000000000
--- a/src/vppinfra/asm_mips.h
+++ /dev/null
@@ -1,351 +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.
- */
-/*
- Copyright (c) 2004 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 included_asm_mips_h
-#define included_asm_mips_h
-
-/* Encoding of MIPS instructions. */
-/* Encoding of opcode field (op). */
-#define mips_foreach_opcode \
- _(SPECIAL) _(REGIMM) _(j) _(jal) _(beq) _(bne) _(blez) _(bgtz) \
- _(addi) _(addiu) _(slti) _(sltiu) _(andi) _(ori) _(xori) _(lui) \
- _(COP0) _(COP1) _(COP2) _(COP1X) _(beql) _(bnel) _(blezl) _(bgtzl) \
- _(daddi) _(daddiu) _(ldl) _(ldr) _(SPECIAL2) _(jalx) _(MDMX) _(O37) \
- _(lb) _(lh) _(lwl) _(lw) _(lbu) _(lhu) _(lwr) _(lwu) \
- _(sb) _(sh) _(swl) _(sw) _(sdl) _(sdr) _(swr) _(cache) \
- _(ll) _(lwc1) _(lwc2) _(pref) _(lld) _(ldc1) _(ldc2) _(ld) \
- _(sc) _(swc1) _(swc2) _(o73) _(scd) _(sdc1) _(sdc2) _(sd)
-
-/* Encoding of funct field. */
-#define mips_foreach_special_funct \
- _(sll) _(MOVCI) _(srl) _(sra) _(sllv) _(o05) _(srlv) _(srav) \
- _(jr) _(jalr) _(movz) _(movn) _(syscall) _(break) _(o16) _(sync) \
- _(mfhi) _(mthi) _(mflo) _(mtlo) _(dsllv) _(o25) _(dsrlv) _(dsrav) \
- _(mult) _(multu) _(div) _(divu) _(dmult) _(dmultu) _(ddiv) _(ddivu) \
- _(add) _(addu) _(sub) _(subu) _(and) _(or) _(xor) _(nor) \
- _(o50) _(o51) _(slt) _(sltu) _(dadd) _(daddu) _(dsub) _(dsubu) \
- _(tge) _(tgeu) _(tlt) _(tltu) _(teq) _(o65) _(tne) _(o67) \
- _(dsll) _(o71) _(dsrl) _(dsra) _(dsll32) _(o75) _(dsrl32) _(dsra32)
-
-/* SPECIAL2 encoding of funct field. */
-#define mips_foreach_special2_funct \
- _(madd) _(maddu) _(mul) _(o03) _(msub) _(msubu) _(o06) _(o07) \
- _(o10) _(o11) _(o12) _(o13) _(o14) _(o15) _(o16) _(o17) \
- _(o20) _(o21) _(o22) _(o23) _(o24) _(o25) _(o26) _(o27) \
- _(o30) _(o31) _(o32) _(o33) _(o34) _(o35) _(o36) _(o37) \
- _(clz) _(clo) _(o42) _(o43) _(dclz) _(dclo) _(o46) _(o47) \
- _(o50) _(o51) _(o52) _(o53) _(o54) _(o55) _(o56) _(o57) \
- _(o60) _(o61) _(o62) _(o63) _(o64) _(o65) _(o66) _(o67) \
- _(o70) _(o71) _(o72) _(o73) _(o74) _(o75) _(o76) _(sdbbp)
-
-/* REGIMM encoding of rt field. */
-#define mips_foreach_regimm_rt \
- _(bltz) _(bgez) _(bltzl) _(bgezl) _(o04) _(o05) _(o06) _(o07) \
- _(tgei) _(tgeiu) _(tltiu) _(teqi) _(o14) _(tnei) _(o16) _(o17) \
- _(bltzal) _(bgezal) _(bltzall) _(bgezall) _(o24) _(o25) _(o26) _(o27) \
- _(o30) _(o31) _(o32) _(o33) _(o34) _(o35) _(o36) _(o37)
-
-/* COP0 encoding of rs field. */
-#define mips_foreach_cop0_rs \
- _(mfc0) _(dmfc0) _(o02) _(o03) _(mtc0) _(dmtc0) _(o06) _(o07) \
- _(o10) _(o11) _(o12) _(o13) _(o14) _(o15) _(o16) _(o17) \
- _(C0) _(o21) _(o22) _(o23) _(o24) _(o25) _(o26) _(o27) \
- _(o30) _(o31) _(o32) _(o33) _(o34) _(o35) _(o36) _(o37)
-
-/* COP0 encoding of funct when rs == RS_CO */
-#define mips_foreach_cop0_funct \
- _(o00) _(tlbr) _(tlbwi) _(o03) _(o04) _(o05) _(tlbwr) _(o07) \
- _(tlbp) _(o11) _(o12) _(o13) _(o14) _(o15) _(o16) _(o17) \
- _(o20) _(o21) _(o22) _(o23) _(o24) _(o25) _(o26) _(o27) \
- _(eret) _(o31) _(o32) _(o33) _(o34) _(o35) _(o36) _(deret) \
- _(wait) _(o41) _(o42) _(o43) _(o44) _(o45) _(o46) _(o47) \
- _(o50) _(o51) _(o52) _(o53) _(o54) _(o55) _(o56) _(o57) \
- _(o60) _(o61) _(o62) _(o63) _(o64) _(o65) _(o66) _(o67) \
- _(o70) _(o71) _(o72) _(o73) _(o74) _(o75) _(o76) _(o77)
-
-/* COP1 encoding of rs field. */
-#define mips_foreach_cop1_rs \
- _(mfc1) _(dmfc1) _(cfc1) _(o03) _(mtc1) _(dmtc1) _(ctc1) _(o07) \
- _(BC1) _(o11) _(o12) _(o13) _(o14) _(o15) _(o16) _(o17) \
- _(S) _(D) _(o22) _(o23) _(W) _(L) _(o26) _(o27) \
- _(o30) _(o31) _(o32) _(o33) _(o34) _(o35) _(o36) _(o37)
-
-/* COP1 encoding of funct for S and D */
-#define mips_foreach_cop1_funct \
- _(add) _(sub) _(mul) _(div) _(sqrt) _(abs) _(mov) _(neg) \
- _(roundl) _(truncl) _(ceill) _(floorl) _(roundw) _(truncw) _(ceilw) _(floorw) \
- _(o20) _(MOVCF) _(movz) _(movn) _(o24) _(recip) _(rsqrt) _(o27) \
- _(o30) _(o31) _(o32) _(o33) _(o34) _(o35) _(o36) _(o37) \
- _(cvts) _(cvtd) _(o42) _(o43) _(cvtw) _(cvtl) _(o46) _(o47) \
- _(o50) _(o51) _(o52) _(o53) _(o54) _(o55) _(o56) _(o57) \
- _(cf) _(cun) _(ceq) _(cueq) _(colt) _(cult) _(cole) _(cule) \
- _(csf) _(cngle) _(cseq) _(cngl) _(clt) _(cnge) _(cle) _(cngt)
-
-/* COP1X encoding of funct */
-#define mips_foreach_cop1x_funct \
- _(lwxc1) _(ldxc1) _(o02) _(o03) _(o04) _(luxc1) _(o06) _(o07) \
- _(swxc1) _(sdxc1) _(o12) _(o13) _(o14) _(suxc1) _(o16) _(prefx) \
- _(o20) _(o21) _(o22) _(o23) _(o24) _(o25) _(o26) _(o27) \
- _(o30) _(o31) _(o32) _(o33) _(o34) _(o35) _(o36) _(o37) \
- _(madds) _(maddd) _(o42) _(o43) _(o44) _(o45) _(o46) _(o47) \
- _(msubs) _(msubd) _(o52) _(o53) _(o54) _(o55) _(o56) _(o57) \
- _(nmadds) _(nmaddd) _(o62) _(o63) _(o64) _(o65) _(o66) _(o67) \
- _(nmsubs) _(nmsubd) _(o72) _(o73) _(o74) _(o75) _(o76) _(o77)
-
-#define mips_foreach_mdmx_funct \
- _(msgn) _(ceq) _(pickf) _(pickt) _(clt) _(cle) _(min) _(max) \
- _(o10) _(o11) _(sub) _(add) _(and) _(xor) _(or) _(nor) \
- _(sll) _(o21) _(srl) _(sra) _(o24) _(o25) _(o26) _(o27) \
- _(alniob) _(alnvob) _(alniqh) _(alnvqh) _(o34) _(o35) _(o36) _(shfl) \
- _(rzu) _(rnau) _(rneu) _(o43) _(rzs) _(rnas) _(rnes) _(o47) \
- _(o50) _(o51) _(o52) _(o53) _(o54) _(o55) _(o56) _(o57) \
- _(mul) _(o61) _(muls) _(mula) _(o64) _(o65) _(suba) _(adda) \
- _(o70) _(o71) _(o72) _(o73) _(o74) _(o75) _(wac) _(rac)
-
-#define _(f) MIPS_OPCODE_##f,
-typedef enum
-{
- mips_foreach_opcode
-} mips_insn_opcode_t;
-#undef _
-
-#define _(f) MIPS_SPECIAL_FUNCT_##f,
-typedef enum
-{
- mips_foreach_special_funct
-} mips_insn_special_funct_t;
-#undef _
-
-#define _(f) MIPS_SPECIAL2_FUNCT_##f,
-typedef enum
-{
- mips_foreach_special2_funct
-} mips_insn_special2_funct_t;
-#undef _
-
-#define _(f) MIPS_REGIMM_RT_##f,
-typedef enum
-{
- mips_foreach_regimm_rt
-} mips_insn_regimm_rt_t;
-#undef _
-
-#define _(f) MIPS_COP0_RS_##f,
-typedef enum
-{
- mips_foreach_cop0_rs
-} mips_insn_cop0_rs_t;
-#undef _
-
-#define _(f) MIPS_COP0_FUNCT_##f,
-typedef enum
-{
- mips_foreach_cop0_funct
-} mips_insn_cop0_funct_t;
-#undef _
-
-#define _(f) MIPS_COP1_RS_##f,
-typedef enum
-{
- mips_foreach_cop1_rs
-} mips_insn_cop1_rs_t;
-#undef _
-
-#define _(f) MIPS_COP1_FUNCT_##f,
-typedef enum
-{
- mips_foreach_cop1_funct
-} mips_insn_cop1_funct_t;
-#undef _
-
-#define _(f) MIPS_COP1X_FUNCT_##f,
-typedef enum
-{
- mips_foreach_cop1x_funct
-} mips_insn_cop1x_funct_t;
-#undef _
-
-#define _(f) MIPS_MDMX_FUNCT_##f,
-typedef enum
-{
- mips_foreach_mdmx_funct
-} mips_insn_mdmx_funct_t;
-#undef _
-
-always_inline mips_insn_opcode_t
-mips_insn_get_op (u32 insn)
-{
- return (insn >> 26) & 0x3f;
-}
-
-always_inline u32
-mips_insn_get_rs (u32 insn)
-{
- return (insn >> 21) & 0x1f;
-}
-
-always_inline u32
-mips_insn_get_rt (u32 insn)
-{
- return (insn >> 16) & 0x1f;
-}
-
-always_inline u32
-mips_insn_get_rd (u32 insn)
-{
- return (insn >> 11) & 0x1f;
-}
-
-always_inline u32
-mips_insn_get_sa (u32 insn)
-{
- return (insn >> 6) & 0x1f;
-}
-
-always_inline u32
-mips_insn_get_funct (u32 insn)
-{
- return (insn >> 0) & 0x3f;
-}
-
-always_inline i32
-mips_insn_get_immediate (u32 insn)
-{
- return (((i32) insn) << 16) >> 16;
-}
-
-always_inline u32
-mips_insn_encode_i_type (int op, int rs, int rt, int immediate)
-{
- u32 insn;
- insn = immediate;
- insn |= rt << 16;
- insn |= rs << 21;
- insn |= op << 26;
-
- ASSERT (mips_insn_get_immediate (insn) == immediate);
- ASSERT (mips_insn_get_rt (insn) == rt);
- ASSERT (mips_insn_get_rs (insn) == rt);
- ASSERT (mips_insn_get_op (insn) == op);
-
- return insn;
-}
-
-always_inline u32
-mips_insn_encode_j_type (int op, u32 addr)
-{
- u32 insn;
-
- insn = (addr & ((1 << 28) - 1)) / 4;
- insn |= op << 26;
-
- return insn;
-}
-
-always_inline u32
-mips_insn_encode_r_type (int op, int rs, int rt, int rd, int sa, int funct)
-{
- u32 insn;
- insn = funct;
- insn |= sa << 6;
- insn |= rd << 11;
- insn |= rt << 16;
- insn |= rs << 21;
- insn |= op << 26;
-
- ASSERT (mips_insn_get_funct (insn) == funct);
- ASSERT (mips_insn_get_sa (insn) == sa);
- ASSERT (mips_insn_get_rd (insn) == rd);
- ASSERT (mips_insn_get_rt (insn) == rt);
- ASSERT (mips_insn_get_rs (insn) == rt);
- ASSERT (mips_insn_get_op (insn) == op);
-
- return insn;
-}
-
-#define mips_insn_r(op,funct,rd,rs,rt,sa) \
- mips_insn_encode_r_type (MIPS_OPCODE_##op, \
- (rs), (rt), (rd), (sa), \
- MIPS_##op##_FUNCT_##funct)
-
-#define mips_insn_i(op,rs,rt,imm) \
- mips_insn_encode_i_type (MIPS_OPCODE_##op, (rs), (rt), (imm))
-
-#define mips_insn_j(op,target) \
- mips_insn_encode_i_type (MIPS_OPCODE_##op, (rs), (rt), (imm))
-
-/* Generate unsigned load instructions of data of various sizes. */
-always_inline u32
-mips_insn_load (u32 rd, i32 offset, u32 base, u32 log2_bytes)
-{
- int op;
-
- ASSERT (log2_bytes < 4);
- switch (log2_bytes)
- {
- case 0:
- op = MIPS_OPCODE_lbu;
- break;
- case 1:
- op = MIPS_OPCODE_lhu;
- break;
- case 2:
- op = MIPS_OPCODE_lwu;
- break;
- case 3:
- op = MIPS_OPCODE_ld;
- break;
- }
-
- return mips_insn_encode_i_type (op, base, rd, offset);
-}
-
-typedef enum
-{
- MIPS_REG_SP = 29,
- MIPS_REG_RA = 31,
-} mips_reg_t;
-
-#endif /* included_asm_mips_h */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/src/vppinfra/asm_x86.c b/src/vppinfra/asm_x86.c
deleted file mode 100644
index e6e00ce5543..00000000000
--- a/src/vppinfra/asm_x86.c
+++ /dev/null
@@ -1,1947 +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.
- */
-/* FIXME
- opcode name remove to save table space; enum
- x87
- 3dnow
- cbw naming
-*/
-
-#include <vppinfra/error.h>
-#include <vppinfra/byte_order.h>
-#include <vppinfra/asm_x86.h>
-
-#define foreach_x86_gp_register \
- _ (AX) _ (CX) _ (DX) _ (BX) \
- _ (SP) _ (BP) _ (SI) _ (DI)
-
-typedef enum {
-#define _(r) X86_INSN_GP_REG_##r,
- foreach_x86_gp_register
-#undef _
-} x86_insn_gp_register_t;
-
-typedef union {
- struct {
- u8 rm : 3;
- u8 reg : 3;
- u8 mode : 2;
- };
- u8 byte;
-} x86_insn_modrm_byte_t;
-
-typedef union {
- struct {
- u8 base : 3;
- u8 index : 3;
- u8 log2_scale : 2;
- };
- u8 byte;
-} x86_insn_sib_byte_t;
-
-always_inline uword
-x86_insn_has_modrm_byte (x86_insn_t * insn)
-{
- int i;
- for (i = 0; i < ARRAY_LEN (insn->operands); i++)
- switch (insn->operands[i].code)
- {
- case 'G': case 'E': case 'M': case 'R':
- return 1;
- }
- return 0;
-}
-
-always_inline uword
-x86_insn_immediate_type (x86_insn_t * insn)
-{
- int i;
- for (i = 0; i < ARRAY_LEN (insn->operands); i++)
- switch (insn->operands[i].code)
- {
- case 'J':
- case 'I':
- case 'O':
- return insn->operands[i].type;
- }
- return 0;
-}
-
-/* Opcode extension in modrm byte reg field. */
-#define foreach_x86_insn_modrm_reg_group \
- _ (1) _ (1a) _ (2) _ (3) _ (4) _ (5) _ (6) _ (7) \
- _ (8) _ (9) _ (10) _ (11) _ (12) _ (13) _ (14) \
- _ (15) _ (16) _ (p)
-
-#define foreach_x86_insn_sse_group \
- _ (10) _ (28) _ (50) _ (58) _ (60) _ (68) _ (70) _ (78) \
- _ (c0) _ (d0) _ (d8) _ (e0) _ (e8) _ (f0) _ (f8)
-
-enum {
-#define _(x) X86_INSN_MODRM_REG_GROUP_##x,
- foreach_x86_insn_modrm_reg_group
-#undef _
-#define _(x) X86_INSN_SSE_GROUP_##x,
- foreach_x86_insn_sse_group
-#undef _
-};
-
-enum {
-#define _(x) \
- X86_INSN_FLAG_MODRM_REG_GROUP_##x \
- = X86_INSN_FLAG_SET_MODRM_REG_GROUP (1 + X86_INSN_MODRM_REG_GROUP_##x),
- foreach_x86_insn_modrm_reg_group
-#undef _
-
-#define _(x) \
- X86_INSN_FLAG_SSE_GROUP_##x \
- = X86_INSN_FLAG_SET_SSE_GROUP (1 + X86_INSN_SSE_GROUP_##x),
- foreach_x86_insn_sse_group
-#undef _
-};
-
-#define foreach_x86_gp_reg \
- _ (AX) _ (CX) _ (DX) _ (BX) \
- _ (SP) _ (BP) _ (SI) _ (DI)
-
-#define foreach_x86_condition \
- _ (o) _ (no) _ (b) _ (nb) \
- _ (z) _ (nz) _ (be) _ (nbe) \
- _ (s) _ (ns) _ (p) _ (np) \
- _ (l) _ (nl) _ (le) _ (nle)
-
-#define _3f(x,f,o0,o1,o2) \
-{ \
- .name = #x, \
- .flags = (f), \
- .operands[0] = { .data = #o0 }, \
- .operands[1] = { .data = #o1 }, \
- .operands[2] = { .data = #o2 }, \
-}
-
-#define _2f(x,f,o0,o1) _3f(x,f,o0,o1,__)
-#define _1f(x,f,o0) _2f(x,f,o0,__)
-#define _0f(x,f) _1f(x,f,__)
-
-#define _3(x,o0,o1,o2) _3f(x,0,o0,o1,o2)
-#define _2(x,o0,o1) _2f(x,0,o0,o1)
-#define _1(x,o0) _1f(x,0,o0)
-#define _0(x) _0f(x,0)
-
-static x86_insn_t x86_insns_one_byte[256] = {
-
-#define _(x) \
- _2 (x, Eb, Gb), \
- _2 (x, Ev, Gv), \
- _2 (x, Gb, Eb), \
- _2 (x, Gv, Ev), \
- _2 (x, AL, Ib), \
- _2 (x, AX, Iz)
-
- /* 0x00 */
- _ (add),
- _0 (push_es),
- _0 (pop_es),
- _ (or),
- _0 (push_cs),
- _0 (escape_two_byte),
-
- /* 0x10 */
- _ (adc),
- _0 (push_ss),
- _0 (pop_ss),
- _ (sbb),
- _0 (push_ds),
- _0 (pop_ds),
-
- /* 0x20 */
- _ (and),
- _0 (segment_es),
- _0 (daa),
- _ (sub),
- _0 (segment_cs),
- _0 (das),
-
- /* 0x30 */
- _ (xor),
- _0 (segment_ss),
- _0 (aaa),
- _ (cmp),
- _0 (segment_ds),
- _0 (aas),
-
-#undef _
-
- /* 0x40 */
-#define _(r) _1 (inc, r),
- foreach_x86_gp_reg
-#undef _
-#define _(r) _1 (dec, r),
- foreach_x86_gp_reg
-#undef _
-
- /* 0x50 */
-#define _(r) _1f (push, X86_INSN_FLAG_DEFAULT_64_BIT, r),
- foreach_x86_gp_reg
-#undef _
-#define _(r) _1f (pop, X86_INSN_FLAG_DEFAULT_64_BIT, r),
- foreach_x86_gp_reg
-#undef _
-
- /* 0x60 */
- _0 (pusha),
- _0 (popa),
- _2 (bound, Gv, Ma),
- _2 (movsxd, Gv, Ed),
- _0 (segment_fs),
- _0 (segment_gs),
- _0 (operand_type),
- _0 (address_size),
- _1f (push, X86_INSN_FLAG_DEFAULT_64_BIT, Iz),
- _3 (imul, Gv, Ev, Iz),
- _1f (push, X86_INSN_FLAG_DEFAULT_64_BIT, Ib),
- _3 (imul, Gv, Ev, Ib),
- _1 (insb, DX),
- _1 (insw, DX),
- _1 (outsb, DX),
- _1 (outsw, DX),
-
- /* 0x70 */
-#define _(x) _1 (j##x, Jb),
- foreach_x86_condition
-#undef _
-
- /* 0x80 */
- _2f (modrm_group_1, X86_INSN_FLAG_MODRM_REG_GROUP_1, Eb, Ib),
- _2f (modrm_group_1, X86_INSN_FLAG_MODRM_REG_GROUP_1, Ev, Iz),
- _2f (modrm_group_1, X86_INSN_FLAG_MODRM_REG_GROUP_1, Eb, Ib),
- _2f (modrm_group_1, X86_INSN_FLAG_MODRM_REG_GROUP_1, Ev, Ib),
- _2 (test, Eb, Gb),
- _2 (test, Ev, Gv),
- _2 (xchg, Eb, Gb),
- _2 (xchg, Ev, Gv),
- _2 (mov, Eb, Gb),
- _2 (mov, Ev, Gv),
- _2 (mov, Gb, Eb),
- _2 (mov, Gv, Ev),
- _2 (mov, Ev, Sw),
- _2 (lea, Gv, Ev),
- _2 (mov, Sw, Ew),
- _1f (modrm_group_1a, X86_INSN_FLAG_MODRM_REG_GROUP_1a, Ev),
-
- /* 0x90 */
- _0 (nop),
- _1 (xchg, CX),
- _1 (xchg, DX),
- _1 (xchg, BX),
- _1 (xchg, SP),
- _1 (xchg, BP),
- _1 (xchg, SI),
- _1 (xchg, DI),
- _0 (cbw),
- _0 (cwd),
- _1 (call, Ap),
- _0 (wait),
- _0 (pushf),
- _0 (popf),
- _0 (sahf),
- _0 (lahf),
-
- /* 0xa0 */
- _2 (mov, AL, Ob),
- _2 (mov, AX, Ov),
- _2 (mov, Ob, AL),
- _2 (mov, Ov, AX),
- _0 (movsb),
- _0 (movsw),
- _0 (cmpsb),
- _0 (cmpsw),
- _2 (test, AL, Ib),
- _2 (test, AX, Iz),
- _1 (stosb, AL),
- _1 (stosw, AX),
- _1 (lodsb, AL),
- _1 (lodsw, AX),
- _1 (scasb, AL),
- _1 (scasw, AX),
-
- /* 0xb0 */
- _2 (mov, AL, Ib),
- _2 (mov, CL, Ib),
- _2 (mov, DL, Ib),
- _2 (mov, BL, Ib),
- _2 (mov, AH, Ib),
- _2 (mov, CH, Ib),
- _2 (mov, DH, Ib),
- _2 (mov, BH, Ib),
-#define _(r) _2 (mov, r, Iv),
- foreach_x86_gp_reg
-#undef _
-
- /* 0xc0 */
- _2f (modrm_group_2, X86_INSN_FLAG_MODRM_REG_GROUP_2, Eb, Ib),
- _2f (modrm_group_2, X86_INSN_FLAG_MODRM_REG_GROUP_2, Ev, Ib),
- _1 (ret, Iw),
- _0 (ret),
- _2 (les, Gz, Mp),
- _2 (lds, Gz, Mp),
- _2f (modrm_group_11, X86_INSN_FLAG_MODRM_REG_GROUP_11, Eb, Ib),
- _2f (modrm_group_11, X86_INSN_FLAG_MODRM_REG_GROUP_11, Ev, Iz),
- _2 (enter, Iw, Ib),
- _0 (leave),
- _1 (ret, Iw),
- _0 (ret),
- _0 (int3),
- _1 (int, Ib),
- _0 (into),
- _0 (iret),
-
- /* 0xd0 */
- _2f (modrm_group_2, X86_INSN_FLAG_MODRM_REG_GROUP_2, Eb, 1b),
- _2f (modrm_group_2, X86_INSN_FLAG_MODRM_REG_GROUP_2, Ev, 1b),
- _2f (modrm_group_2, X86_INSN_FLAG_MODRM_REG_GROUP_2, Eb, CL),
- _2f (modrm_group_2, X86_INSN_FLAG_MODRM_REG_GROUP_2, Ev, CL),
- _0 (aam),
- _0 (aad),
- _0 (salc),
- _0 (xlat),
- /* FIXME x87 */
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
-
- /* 0xe0 */
- _1 (loopnz, Jb),
- _1 (loopz, Jb),
- _1 (loop, Jb),
- _1 (jcxz, Jb),
- _2 (in, AL, Ib),
- _2 (in, AX, Ib),
- _2 (out, Ib, AL),
- _2 (out, Ib, AX),
- _1f (call, X86_INSN_FLAG_DEFAULT_64_BIT, Jz),
- _1f ( jmp, X86_INSN_FLAG_DEFAULT_64_BIT, Jz),
- _1 (jmp, Ap),
- _1 (jmp, Jb),
- _2 (in, AL, DX),
- _2 (in, AX, DX),
- _2 (out, DX, AL),
- _2 (out, DX, AX),
-
- /* 0xf0 */
- _0 (lock),
- _0 (int1),
- _0 (repne),
- _0 (rep),
- _0 (hlt),
- _0 (cmc),
- _0f (modrm_group_3, X86_INSN_FLAG_MODRM_REG_GROUP_3),
- _0f (modrm_group_3, X86_INSN_FLAG_MODRM_REG_GROUP_3),
- _0 (clc),
- _0 (stc),
- _0 (cli),
- _0 (sti),
- _0 (cld),
- _0 (std),
- _1f (modrm_group_4, X86_INSN_FLAG_MODRM_REG_GROUP_4, Eb),
- _0f (modrm_group_5, X86_INSN_FLAG_MODRM_REG_GROUP_5),
-};
-
-static x86_insn_t x86_insns_two_byte[256] = {
- /* 0x00 */
- _0f (modrm_group_6, X86_INSN_FLAG_MODRM_REG_GROUP_6),
- _0f (modrm_group_7, X86_INSN_FLAG_MODRM_REG_GROUP_7),
- _2 (lar, Gv, Ew),
- _2 (lsl, Gv, Ew),
- _0 (bad),
- _0 (syscall),
- _0 (clts),
- _0 (sysret),
- _0 (invd),
- _0 (wbinvd),
- _0 (bad),
- _0 (ud2),
- _0 (bad),
- _0f (modrm_group_p, X86_INSN_FLAG_MODRM_REG_GROUP_p),
- _0 (femms),
- _0 (escape_3dnow),
-
- /* 0x10 */
- _2f (movups, X86_INSN_FLAG_SSE_GROUP_10, Gx, Ex),
- _2f (movups, X86_INSN_FLAG_SSE_GROUP_10, Ex, Gx),
- _2f (movlps, X86_INSN_FLAG_SSE_GROUP_10, Ex, Gx),
- _2f (movlps, X86_INSN_FLAG_SSE_GROUP_10, Gx, Ex),
- _2f (unpcklps, X86_INSN_FLAG_SSE_GROUP_10, Gx, Ex),
- _2f (unpckhps, X86_INSN_FLAG_SSE_GROUP_10, Gx, Ex),
- _2f (movhps, X86_INSN_FLAG_SSE_GROUP_10, Ex, Gx),
- _2f (movhps, X86_INSN_FLAG_SSE_GROUP_10, Gx, Ex),
- _0f (modrm_group_16, X86_INSN_FLAG_MODRM_REG_GROUP_16),
- _0 (nop),
- _0 (nop),
- _0 (nop),
- _0 (nop),
- _0 (nop),
- _0 (nop),
- _0 (nop),
-
- /* 0x20 */
- _2 (mov, Rv, Cv),
- _2 (mov, Rv, Dv),
- _2 (mov, Cv, Rv),
- _2 (mov, Dv, Rv),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _2f (movaps, X86_INSN_FLAG_SSE_GROUP_28, Gx, Ex),
- _2f (movaps, X86_INSN_FLAG_SSE_GROUP_28, Ex, Gx),
- _2f (cvtpi2ps, X86_INSN_FLAG_SSE_GROUP_28, Gx, Ex),
- _2f (movntps, X86_INSN_FLAG_SSE_GROUP_28, Mx, Gx),
- _2f (cvttps2pi, X86_INSN_FLAG_SSE_GROUP_28, Gx, Ex),
- _2f (cvtps2pi, X86_INSN_FLAG_SSE_GROUP_28, Gx, Ex),
- _2f (ucomiss, X86_INSN_FLAG_SSE_GROUP_28, Gx, Ex),
- _2f (comiss, X86_INSN_FLAG_SSE_GROUP_28, Gx, Ex),
-
- /* 0x30 */
- _0 (wrmsr),
- _0 (rdtsc),
- _0 (rdmsr),
- _0 (rdpmc),
- _0 (sysenter),
- _0 (sysexit),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
-
- /* 0x40 */
-#define _(x) _2 (cmov##x, Gv, Ev),
- foreach_x86_condition
-#undef _
-
- /* 0x50 */
- _2f (movmskps, X86_INSN_FLAG_SSE_GROUP_50, Gd, Rx),
- _2f (sqrtps, X86_INSN_FLAG_SSE_GROUP_50, Gx, Ex),
- _2f (rsqrtps, X86_INSN_FLAG_SSE_GROUP_50, Gx, Ex),
- _2f (rcpps, X86_INSN_FLAG_SSE_GROUP_50, Gx, Ex),
- _2f (andps, X86_INSN_FLAG_SSE_GROUP_50, Gx, Ex),
- _2f (andnps, X86_INSN_FLAG_SSE_GROUP_50, Gx, Ex),
- _2f (orps, X86_INSN_FLAG_SSE_GROUP_50, Gx, Ex),
- _2f (xorps, X86_INSN_FLAG_SSE_GROUP_50, Gx, Ex),
- _2f (addps, X86_INSN_FLAG_SSE_GROUP_58, Gx, Ex),
- _2f (mulps, X86_INSN_FLAG_SSE_GROUP_58, Gx, Ex),
- _2f (cvtps2pd, X86_INSN_FLAG_SSE_GROUP_58, Gx, Ex),
- _2f (cvtdq2ps, X86_INSN_FLAG_SSE_GROUP_58, Gx, Ex),
- _2f (subps, X86_INSN_FLAG_SSE_GROUP_58, Gx, Ex),
- _2f (minps, X86_INSN_FLAG_SSE_GROUP_58, Gx, Ex),
- _2f (divps, X86_INSN_FLAG_SSE_GROUP_58, Gx, Ex),
- _2f (maxps, X86_INSN_FLAG_SSE_GROUP_58, Gx, Ex),
-
- /* 0x60 */
- _2f (punpcklbw, X86_INSN_FLAG_SSE_GROUP_60, Gm, Em),
- _2f (punpcklwd, X86_INSN_FLAG_SSE_GROUP_60, Gm, Em),
- _2f (punpckldq, X86_INSN_FLAG_SSE_GROUP_60, Gm, Em),
- _2f (packsswb, X86_INSN_FLAG_SSE_GROUP_60, Gm, Em),
- _2f (pcmpgtb, X86_INSN_FLAG_SSE_GROUP_60, Gm, Em),
- _2f (pcmpgtw, X86_INSN_FLAG_SSE_GROUP_60, Gm, Em),
- _2f (pcmpgtd, X86_INSN_FLAG_SSE_GROUP_60, Gm, Em),
- _2f (packuswb, X86_INSN_FLAG_SSE_GROUP_60, Gm, Em),
- _2f (punpckhbw, X86_INSN_FLAG_SSE_GROUP_68, Gm, Em),
- _2f (punpckhwd, X86_INSN_FLAG_SSE_GROUP_68, Gm, Em),
- _2f (punpckhdq, X86_INSN_FLAG_SSE_GROUP_68, Gm, Em),
- _2f (packssdw, X86_INSN_FLAG_SSE_GROUP_68, Gm, Em),
- _0f (bad, X86_INSN_FLAG_SSE_GROUP_68),
- _0f (bad, X86_INSN_FLAG_SSE_GROUP_68),
- _2f (movd, X86_INSN_FLAG_SSE_GROUP_68, Gm, Em),
- _2f (movq, X86_INSN_FLAG_SSE_GROUP_68, Gm, Em),
-
- /* 0x70 */
- _3f (pshufw, X86_INSN_FLAG_SSE_GROUP_70, Gm, Em, Ib),
- _0f (modrm_group_12, X86_INSN_FLAG_MODRM_REG_GROUP_12),
- _0f (modrm_group_13, X86_INSN_FLAG_MODRM_REG_GROUP_13),
- _0f (modrm_group_14, X86_INSN_FLAG_MODRM_REG_GROUP_14),
- _2f (pcmpeqb, X86_INSN_FLAG_SSE_GROUP_70, Gm, Em),
- _2f (pcmpeqw, X86_INSN_FLAG_SSE_GROUP_70, Gm, Em),
- _2f (pcmpeqd, X86_INSN_FLAG_SSE_GROUP_70, Gm, Em),
- _0f (emms, X86_INSN_FLAG_SSE_GROUP_70),
- _0f (bad, X86_INSN_FLAG_SSE_GROUP_78),
- _0f (bad, X86_INSN_FLAG_SSE_GROUP_78),
- _0f (bad, X86_INSN_FLAG_SSE_GROUP_78),
- _0f (bad, X86_INSN_FLAG_SSE_GROUP_78),
- _0f (bad, X86_INSN_FLAG_SSE_GROUP_78),
- _0f (bad, X86_INSN_FLAG_SSE_GROUP_78),
- _2f (movd, X86_INSN_FLAG_SSE_GROUP_78, Em, Gm),
- _2f (movq, X86_INSN_FLAG_SSE_GROUP_78, Em, Gm),
-
- /* 0x80 */
-#define _(x) _1 (jmp##x, Jz),
- foreach_x86_condition
-#undef _
-
- /* 0x90 */
-#define _(x) _1 (set##x, Eb),
- foreach_x86_condition
-#undef _
-
- /* 0xa0 */
- _0 (push_fs),
- _0 (pop_fs),
- _0 (cpuid),
- _2 (bt, Ev, Gv),
- _3 (shld, Ev, Gv, Ib),
- _3 (shld, Ev, Gv, CL),
- _0 (bad),
- _0 (bad),
- _0 (push_gs),
- _0 (pop_gs),
- _0 (rsm),
- _2 (bts, Ev, Gv),
- _3 (shrd, Ev, Gv, Ib),
- _3 (shrd, Ev, Gv, CL),
- _0f (modrm_group_15, X86_INSN_FLAG_MODRM_REG_GROUP_15),
- _2 (imul, Gv, Ev),
-
- /* 0xb0 */
- _2 (cmpxchg, Eb, Gb),
- _2 (cmpxchg, Ev, Gv),
- _2 (lss, Gz, Mp),
- _2 (btr, Ev, Gv),
- _2 (lfs, Gz, Mp),
- _2 (lgs, Gz, Mp),
- _2 (movzbl, Gv, Eb),
- _2 (movzwl, Gv, Ew),
- _0 (bad),
- _0f (modrm_group_10, X86_INSN_FLAG_MODRM_REG_GROUP_10),
- _2f (modrm_group_8, X86_INSN_FLAG_MODRM_REG_GROUP_8, Ev, Ib),
- _2 (btc, Ev, Gv),
- _2 (bsf, Gv, Ev),
- _2 (bsr, Gv, Ev),
- _2 (movsx, Gv, Eb),
- _2 (movsx, Gv, Ew),
-
- /* 0xc0 */
- _2 (xadd, Eb, Gb),
- _2 (xadd, Ev, Gv),
- _3f (cmpps, X86_INSN_FLAG_SSE_GROUP_c0, Gx, Ex, Ib),
- _2 (movnti, Mv, Gv),
- _3f (pinsrw, X86_INSN_FLAG_SSE_GROUP_c0, Gm, Ew, Ib),
- _3f (pextrw, X86_INSN_FLAG_SSE_GROUP_c0, Gd, Rm, Ib),
- _3f (shufps, X86_INSN_FLAG_SSE_GROUP_c0, Gx, Ex, Ib),
- _1f (modrm_group_9, X86_INSN_FLAG_MODRM_REG_GROUP_9, Mx),
-#define _(r) _1 (bswap, r),
- foreach_x86_gp_reg
-#undef _
-
- /* 0xd0 */
- _0f (bad, X86_INSN_FLAG_SSE_GROUP_d0),
- _2f (psrlw, X86_INSN_FLAG_SSE_GROUP_d0, Gm, Em),
- _2f (psrld, X86_INSN_FLAG_SSE_GROUP_d0, Gm, Em),
- _2f (psrlq, X86_INSN_FLAG_SSE_GROUP_d0, Gm, Em),
- _2f (paddq, X86_INSN_FLAG_SSE_GROUP_d0, Gm, Em),
- _2f (pmullw, X86_INSN_FLAG_SSE_GROUP_d0, Gm, Em),
- _0f (bad, X86_INSN_FLAG_SSE_GROUP_d0),
- _2f (pmovmskb, X86_INSN_FLAG_SSE_GROUP_d0, Gd, Rm),
- _2f (psubusb, X86_INSN_FLAG_SSE_GROUP_d8, Gm, Em),
- _2f (psubusw, X86_INSN_FLAG_SSE_GROUP_d8, Gm, Em),
- _2f (pminub, X86_INSN_FLAG_SSE_GROUP_d8, Gm, Em),
- _2f (pand, X86_INSN_FLAG_SSE_GROUP_d8, Gm, Em),
- _2f (paddusb, X86_INSN_FLAG_SSE_GROUP_d8, Gm, Em),
- _2f (paddusw, X86_INSN_FLAG_SSE_GROUP_d8, Gm, Em),
- _2f (pmaxub, X86_INSN_FLAG_SSE_GROUP_d8, Gm, Em),
- _2f (pandn, X86_INSN_FLAG_SSE_GROUP_d8, Gm, Em),
-
- /* 0xe0 */
- _2f (pavgb, X86_INSN_FLAG_SSE_GROUP_e0, Gm, Em),
- _2f (psraw, X86_INSN_FLAG_SSE_GROUP_e0, Gm, Em),
- _2f (psrad, X86_INSN_FLAG_SSE_GROUP_e0, Gm, Em),
- _2f (pavgw, X86_INSN_FLAG_SSE_GROUP_e0, Gm, Em),
- _2f (pmulhuw, X86_INSN_FLAG_SSE_GROUP_e0, Gm, Em),
- _2f (pmulhw, X86_INSN_FLAG_SSE_GROUP_e0, Gm, Em),
- _2f (bad, X86_INSN_FLAG_SSE_GROUP_e0, Gm, Em),
- _2f (movntq, X86_INSN_FLAG_SSE_GROUP_e0, Mm, Gm),
- _2f (psubsb, X86_INSN_FLAG_SSE_GROUP_e8, Gm, Em),
- _2f (psubsw, X86_INSN_FLAG_SSE_GROUP_e8, Gm, Em),
- _2f (pminsw, X86_INSN_FLAG_SSE_GROUP_e8, Gm, Em),
- _2f (por, X86_INSN_FLAG_SSE_GROUP_e8, Gm, Em),
- _2f (paddsb, X86_INSN_FLAG_SSE_GROUP_e8, Gm, Em),
- _2f (paddsw, X86_INSN_FLAG_SSE_GROUP_e8, Gm, Em),
- _2f (pmaxsw, X86_INSN_FLAG_SSE_GROUP_e8, Gm, Em),
- _2f (pxor, X86_INSN_FLAG_SSE_GROUP_e8, Gm, Em),
-
- /* 0xf0 */
- _0f (bad, X86_INSN_FLAG_SSE_GROUP_f0),
- _2f (psllw, X86_INSN_FLAG_SSE_GROUP_f0, Gm, Em),
- _2f (pslld, X86_INSN_FLAG_SSE_GROUP_f0, Gm, Em),
- _2f (psllq, X86_INSN_FLAG_SSE_GROUP_f0, Gm, Em),
- _2f (pmuludq, X86_INSN_FLAG_SSE_GROUP_f0, Gm, Em),
- _2f (pmaddwd, X86_INSN_FLAG_SSE_GROUP_f0, Gm, Em),
- _2f (psadbw, X86_INSN_FLAG_SSE_GROUP_f0, Gm, Em),
- _2f (maskmovq, X86_INSN_FLAG_SSE_GROUP_f0, Gm, Em),
- _2f (psubb, X86_INSN_FLAG_SSE_GROUP_f8, Gm, Em),
- _2f (psubw, X86_INSN_FLAG_SSE_GROUP_f8, Gm, Em),
- _2f (psubd, X86_INSN_FLAG_SSE_GROUP_f8, Gm, Em),
- _2f (psubq, X86_INSN_FLAG_SSE_GROUP_f8, Gm, Em),
- _2f (paddb, X86_INSN_FLAG_SSE_GROUP_f8, Gm, Em),
- _2f (paddw, X86_INSN_FLAG_SSE_GROUP_f8, Gm, Em),
- _2f (paddd, X86_INSN_FLAG_SSE_GROUP_f8, Gm, Em),
- _0f (bad, X86_INSN_FLAG_SSE_GROUP_f8),
-};
-
-typedef struct {
- x86_insn_t insns[8];
-} x86_insn_group8_t;
-
-/* Escape groups are indexed by modrm reg field. */
-static x86_insn_group8_t x86_insn_modrm_reg_groups[] = {
- [X86_INSN_MODRM_REG_GROUP_1].insns = {
- _0 (add), _0 ( or), _0 (adc), _0 (sbb),
- _0 (and), _0 (sub), _0 (xor), _0 (cmp),
- },
-
- [X86_INSN_MODRM_REG_GROUP_1a].insns = {
- _0f (pop, X86_INSN_FLAG_DEFAULT_64_BIT),
- _0 (bad), _0 (bad), _0 (bad),
- _0 (bad), _0 (bad), _0 (bad), _0 (bad),
- },
-
- [X86_INSN_MODRM_REG_GROUP_2].insns = {
- _0 (rol), _0 (ror), _0 (rcl), _0 (rcr),
- _0 (shl), _0 (shr), _0 (sal), _0 (sar),
- },
-
- [X86_INSN_MODRM_REG_GROUP_3].insns = {
- _0 (test), _0 (test), _0 (not), _0 (neg),
- _0 (mul), _0 (imul), _0 (div), _0 (idiv),
- },
-
- [X86_INSN_MODRM_REG_GROUP_4].insns = {
- _0 (inc), _0 (dec), _0 (bad), _0 (bad),
- _0 (bad), _0 (bad), _0 (bad), _0 (bad),
- },
-
- [X86_INSN_MODRM_REG_GROUP_5].insns = {
- _1 (inc, Ev),
- _1 (dec, Ev),
- _1f (call, X86_INSN_FLAG_DEFAULT_64_BIT, Ev),
- _1 (call, Mp),
- _1f (jmp, X86_INSN_FLAG_DEFAULT_64_BIT, Ev),
- _1 (jmp, Mp),
- _1f (push, X86_INSN_FLAG_DEFAULT_64_BIT, Ev),
- _0 (bad),
- },
-
- [X86_INSN_MODRM_REG_GROUP_6].insns = {
- _1 (sldt, Ev),
- _1 (str, Ev),
- _1 (lldt, Ev),
- _1 (ltr, Ev),
- _1 (verr, Ev),
- _1 (verw, Ev),
- _0 (bad),
- _0 (bad),
- },
-
- [X86_INSN_MODRM_REG_GROUP_7].insns = {
- _1 (sgdt, Mv),
- _1 (sidt, Mv),
- _1 (lgdt, Mv),
- _1 (lidt, Mv),
- _1 (smsw, Ev),
- _0 (bad),
- _1 (lmsw, Ew),
- _1 (invlpg, Mv),
- },
-
- [X86_INSN_MODRM_REG_GROUP_8].insns = {
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _2 (bt, Ev, Ib),
- _2 (bts, Ev, Ib),
- _2 (btr, Ev, Ib),
- _2 (btc, Ev, Ib),
- },
-
- [X86_INSN_MODRM_REG_GROUP_9].insns = {
- _0 (bad),
- _1 (cmpxchg, Mx),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- },
-
- [X86_INSN_MODRM_REG_GROUP_10].insns = {
- _0 (bad), _0 (bad), _0 (bad), _0 (bad),
- _0 (bad), _0 (bad), _0 (bad), _0 (bad),
- },
-
- [X86_INSN_MODRM_REG_GROUP_11].insns = {
- _0 (mov), _0 (bad), _0 (bad), _0 (bad),
- _0 (bad), _0 (bad), _0 (bad), _0 (bad),
- },
-
- [X86_INSN_MODRM_REG_GROUP_12].insns = {
- _0 (bad),
- _0 (bad),
- _2 (psrlw, Rm, Ib),
- _0 (bad),
- _2 (psraw, Rm, Ib),
- _0 (bad),
- _2 (psllw, Rm, Ib),
- _0 (bad),
- },
-
- [X86_INSN_MODRM_REG_GROUP_13].insns = {
- _0 (bad),
- _0 (bad),
- _2 (psrld, Rm, Ib),
- _0 (bad),
- _2 (psrad, Rm, Ib),
- _0 (bad),
- _2 (pslld, Rm, Ib),
- _0 (bad),
- },
-
- [X86_INSN_MODRM_REG_GROUP_14].insns = {
- _0 (bad),
- _0 (bad),
- _2 (psrlq, Rm, Ib),
- _0f (bad, 0),
- _0 (bad),
- _0 (bad),
- _2 (psllq, Rm, Ib),
- _0f (bad, 0),
- },
-
- [X86_INSN_MODRM_REG_GROUP_15].insns = {
- _1 (fxsave, Mv),
- _1 (fxrstor, Mv),
- _1 (ldmxcsr, Mv),
- _1 (stmxcsr, Mv),
- _0 (bad),
- _1 (lfence, Mv),
- _1 (mfence, Mv),
- _1 (sfence, Mv),
- },
-
- [X86_INSN_MODRM_REG_GROUP_16].insns = {
- _1 (prefetch_nta, Mv),
- _1 (prefetch_t0, Mv),
- _1 (prefetch_t1, Mv),
- _1 (prefetch_t2, Mv),
- _1 (prefetch_nop, Mv),
- _1 (prefetch_nop, Mv),
- _1 (prefetch_nop, Mv),
- _1 (prefetch_nop, Mv),
- },
-
- [X86_INSN_MODRM_REG_GROUP_p].insns = {
- _1 (prefetch_exclusive, Mv),
- _1 (prefetch_modified, Mv),
- _1 (prefetch_nop, Mv),
- _1 (prefetch_modified, Mv),
- _1 (prefetch_nop, Mv),
- _1 (prefetch_nop, Mv),
- _1 (prefetch_nop, Mv),
- _1 (prefetch_nop, Mv),
- },
-};
-
-static x86_insn_group8_t x86_insn_sse_groups_repz[] = {
- [X86_INSN_SSE_GROUP_10].insns = {
- _2 (movss, Gx, Ex),
- _2 (movss, Ex, Gx),
- _2 (movsldup, Gx, Ex),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _2 (movshdup, Gx, Ex),
- _0 (bad),
- },
-
- [X86_INSN_SSE_GROUP_28].insns = {
- _0 (bad),
- _0 (bad),
- _2 (cvtsi2ss, Gx, Ev),
- _0 (bad),
- _2 (cvttss2si, Gv, Ex),
- _2 (cvtss2si, Gv, Ex),
- _0 (bad),
- _0 (bad),
- },
-
- [X86_INSN_SSE_GROUP_50].insns = {
- _0 (bad),
- _2 (sqrtss, Gx, Ex),
- _2 (rsqrtps, Gx, Ex),
- _2 (rcpss, Gx, Ex),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- },
-
- [X86_INSN_SSE_GROUP_58].insns = {
- _2 (addss, Gx, Ex),
- _2 (mulss, Gx, Ex),
- _2 (cvtss2sd, Gx, Ex),
- _2 (cvttps2dq, Gx, Ex),
- _2 (subss, Gx, Ex),
- _2 (minss, Gx, Ex),
- _2 (divss, Gx, Ex),
- _2 (maxss, Gx, Ex),
- },
-
- [X86_INSN_SSE_GROUP_60].insns = {
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- },
-
- [X86_INSN_SSE_GROUP_68].insns = {
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _2 (movdqu, Gx, Ex),
- },
-
- [X86_INSN_SSE_GROUP_70].insns = {
- _3 (pshufhw, Gx, Ex, Ib),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- },
-
- [X86_INSN_SSE_GROUP_78].insns = {
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _2 (movq, Gx, Ex),
- _2 (movdqu, Ex, Gx),
- },
-
- [X86_INSN_SSE_GROUP_c0].insns = {
- _0 (bad),
- _0 (bad),
- _3 (cmpss, Gx, Ex, Ib),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- },
-
- [X86_INSN_SSE_GROUP_d0].insns = {
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _2 (movq2dq, Gx, Em),
- _0 (bad),
- },
-
- [X86_INSN_SSE_GROUP_d8].insns = {
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- },
-
- [X86_INSN_SSE_GROUP_e0].insns = {
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _2 (cvtdq2pd, Gx, Ex),
- _0 (bad),
- },
-
- [X86_INSN_SSE_GROUP_e8].insns = {
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- },
-
- [X86_INSN_SSE_GROUP_f0].insns = {
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- },
-
- [X86_INSN_SSE_GROUP_f8].insns = {
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- },
-};
-
-static x86_insn_group8_t x86_insn_sse_groups_operand_size[] = {
- [X86_INSN_SSE_GROUP_10].insns = {
- _2 (movupd, Gx, Ex),
- _2 (movupd, Ex, Gx),
- _2 (movlpd, Gx, Ex),
- _2 (movlpd, Ex, Gx),
- _2 (unpcklpd, Gx, Ex),
- _2 (unpckhpd, Gx, Ex),
- _2 (movhpd, Gx, Mx),
- _2 (movhpd, Mx, Gx),
- },
-
- [X86_INSN_SSE_GROUP_28].insns = {
- _2 (movapd, Gx, Ex),
- _2 (movapd, Ex, Gx),
- _2 (cvtpi2pd, Gx, Ex),
- _2 (movntpd, Mx, Gx),
- _2 (cvttpd2pi, Gx, Mx),
- _2 (cvtpd2pi, Gx, Mx),
- _2 (ucomisd, Gx, Ex),
- _2 (comisd, Gx, Ex),
- },
-
- [X86_INSN_SSE_GROUP_50].insns = {
- _2 (movmskpd, Gd, Rx),
- _2 (sqrtpd, Gx, Ex),
- _0 (bad),
- _0 (bad),
- _2 (andpd, Gx, Ex),
- _2 (andnpd, Gx, Ex),
- _2 (orpd, Gx, Ex),
- _2 (xorpd, Gx, Ex),
- },
-
- [X86_INSN_SSE_GROUP_58].insns = {
- _2 (addpd, Gx, Ex),
- _2 (mulpd, Gx, Ex),
- _2 (cvtpd2ps, Gx, Ex),
- _2 (cvtps2dq, Gx, Ex),
- _2 (subpd, Gx, Ex),
- _2 (minpd, Gx, Ex),
- _2 (divpd, Gx, Ex),
- _2 (maxpd, Gx, Ex),
- },
-
- [X86_INSN_SSE_GROUP_60].insns = {
- _2 (punpcklbw, Gx, Ex),
- _2 (punpcklwd, Gx, Ex),
- _2 (punpckldq, Gx, Ex),
- _2 (packsswb, Gx, Ex),
- _2 (pcmpgtb, Gx, Ex),
- _2 (pcmpgtw, Gx, Ex),
- _2 (pcmpgtd, Gx, Ex),
- _2 (packuswb, Gx, Ex),
- },
-
- [X86_INSN_SSE_GROUP_68].insns = {
- _2 (punpckhbw, Gx, Ex),
- _2 (punpckhwd, Gx, Ex),
- _2 (punpckhdq, Gx, Ex),
- _2 (packssdw, Gx, Ex),
- _2 (punpcklqdq, Gx, Ex),
- _2 (punpckhqdq, Gx, Ex),
- _2 (movd, Gx, Ev),
- _2 (movdqa, Gx, Ex),
- },
-
- [X86_INSN_SSE_GROUP_70].insns = {
- _3 (pshufd, Gx, Ex, Ib),
- _0f (modrm_group_12, X86_INSN_FLAG_MODRM_REG_GROUP_12),
- _0f (modrm_group_13, X86_INSN_FLAG_MODRM_REG_GROUP_13),
- _0f (modrm_group_14, X86_INSN_FLAG_MODRM_REG_GROUP_14),
- _2 (pcmpeqb, Gx, Ex),
- _2 (pcmpeqw, Gx, Ex),
- _2 (pcmpeqd, Gx, Ex),
- _0 (bad),
- },
-
- [X86_INSN_SSE_GROUP_78].insns = {
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _2 (haddpd, Gx, Ex),
- _2 (hsubpd, Gx, Ex),
- _2 (movd, Ev, Gx),
- _2 (movdqa, Ex, Gx),
- },
-
- [X86_INSN_SSE_GROUP_c0].insns = {
- _0 (bad),
- _0 (bad),
- _3 (cmppd, Gx, Ex, Ib),
- _0 (bad),
- _3 (pinsrw, Gx, Ew, Ib),
- _3 (pextrw, Gd, Gx, Ib),
- _3 (shufpd, Gx, Ex, Ib),
- _0 (bad),
- },
-
- [X86_INSN_SSE_GROUP_d0].insns = {
- _2 (addsubpd, Gx, Ex),
- _2 (psrlw, Gx, Ex),
- _2 (psrld, Gx, Ex),
- _2 (psrlq, Gx, Ex),
- _2 (paddq, Gx, Ex),
- _2 (pmullw, Gx, Ex),
- _2 (movq, Ex, Gx),
- _2 (pmovmskb, Gd, Rx),
- },
-
- [X86_INSN_SSE_GROUP_d8].insns = {
- _2 (psubusb, Gx, Ex),
- _2 (psubusw, Gx, Ex),
- _2 (pminub, Gx, Ex),
- _2 (pand, Gx, Ex),
- _2 (paddusb, Gx, Ex),
- _2 (paddusw, Gx, Ex),
- _2 (pmaxub, Gx, Ex),
- _2 (pandn, Gx, Ex),
- },
-
- [X86_INSN_SSE_GROUP_e0].insns = {
- _2 (pavgb, Gx, Ex),
- _2 (psraw, Gx, Ex),
- _2 (psrad, Gx, Ex),
- _2 (pavgw, Gx, Ex),
- _2 (pmulhuw, Gx, Ex),
- _2 (pmulhw, Gx, Ex),
- _2 (cvttpd2dq, Gx, Ex),
- _2 (movntdq, Mx, Gx),
- },
-
- [X86_INSN_SSE_GROUP_e8].insns = {
- _2 (psubsb, Gx, Ex),
- _2 (psubsw, Gx, Ex),
- _2 (pminsw, Gx, Ex),
- _2 (por, Gx, Ex),
- _2 (paddsb, Gx, Ex),
- _2 (paddsw, Gx, Ex),
- _2 (pmaxsw, Gx, Ex),
- _2 (pxor, Gx, Ex),
- },
-
- [X86_INSN_SSE_GROUP_f0].insns = {
- _0 (bad),
- _2 (psllw, Gx, Ex),
- _2 (pslld, Gx, Ex),
- _2 (psllq, Gx, Ex),
- _2 (pmuludq, Gx, Ex),
- _2 (pmaddwd, Gx, Ex),
- _2 (psadbw, Gx, Ex),
- _2 (maskmovdqu, Gx, Ex),
- },
-
- [X86_INSN_SSE_GROUP_f8].insns = {
- _2 (psubb, Gx, Ex),
- _2 (psubw, Gx, Ex),
- _2 (psubd, Gx, Ex),
- _2 (psubq, Gx, Ex),
- _2 (paddb, Gx, Ex),
- _2 (paddw, Gx, Ex),
- _2 (paddd, Gx, Ex),
- _0 (bad),
- },
-};
-
-static x86_insn_group8_t x86_insn_sse_groups_repnz[] = {
- [X86_INSN_SSE_GROUP_10].insns = {
- _2 (movsd, Gx, Ex),
- _2 (movsd, Ex, Gx),
- _2 (movddup, Gx, Ex),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- },
-
- [X86_INSN_SSE_GROUP_28].insns = {
- _0 (bad),
- _0 (bad),
- _2 (cvtsi2sd, Gx, Ev),
- _0 (bad),
- _2 (cvttsd2si, Gv, Ex),
- _2 (cvtsd2si, Gv, Ex),
- _0 (bad),
- _0 (bad),
- },
-
- [X86_INSN_SSE_GROUP_50].insns = {
- _0 (bad),
- _2 (sqrtsd, Gx, Ex),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- },
-
- [X86_INSN_SSE_GROUP_58].insns = {
- _2 (addsd, Gx, Ex),
- _2 (mulsd, Gx, Ex),
- _2 (cvtsd2ss, Gx, Ex),
- _0 (bad),
- _2 (subsd, Gx, Ex),
- _2 (minsd, Gx, Ex),
- _2 (divsd, Gx, Ex),
- _2 (maxsd, Gx, Ex),
- },
-
- [X86_INSN_SSE_GROUP_60].insns = {
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- },
-
- [X86_INSN_SSE_GROUP_68].insns = {
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- },
-
- [X86_INSN_SSE_GROUP_70].insns = {
- _3 (pshuflw, Gx, Ex, Ib),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- },
-
- [X86_INSN_SSE_GROUP_78].insns = {
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _2 (haddps, Gx, Ex),
- _2 (hsubps, Gx, Ex),
- _0 (bad),
- _0 (bad),
- },
-
- [X86_INSN_SSE_GROUP_c0].insns = {
- _0 (bad),
- _0 (bad),
- _3 (cmpsd, Gx, Ex, Ib),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- },
-
- [X86_INSN_SSE_GROUP_d0].insns = {
- _2 (addsubps, Gx, Ex),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _2 (movdq2q, Gm, Ex),
- _0 (bad),
- },
-
- [X86_INSN_SSE_GROUP_d8].insns = {
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- },
-
- [X86_INSN_SSE_GROUP_e0].insns = {
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _2 (cvtpd2dq, Gx, Ex),
- _0 (bad),
- },
-
- [X86_INSN_SSE_GROUP_e8].insns = {
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- },
-
- [X86_INSN_SSE_GROUP_f0].insns = {
- _2 (lddqu, Gx, Mx),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- },
-
- [X86_INSN_SSE_GROUP_f8].insns = {
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- _0 (bad),
- },
-};
-
-#undef _
-
-/* Parses memory displacements and immediates. */
-static u8 * x86_insn_parse_number (u32 log2_n_bytes,
- u8 * code, u8 * code_end,
- i64 * result)
-{
- i64 x = 0;
-
- if (code + (1 << log2_n_bytes) > code_end)
- return 0;
-
- switch (log2_n_bytes)
- {
- case 3:
- x = clib_little_to_host_unaligned_mem_u64 ((u64 *) code);
- break;
-
- case 2:
- x = (i32) clib_little_to_host_unaligned_mem_u32 ((u32 *) code);
- break;
-
- case 1:
- x = (i16) clib_little_to_host_unaligned_mem_u16 ((u16 *) code);
- break;
-
- case 0:
- x = (i8) code[0];
- break;
-
- default:
- ASSERT (0);
- }
-
- *result = x;
- return code + (1 << log2_n_bytes);
-}
-
-static u32
-x86_insn_log2_immediate_bytes (x86_insn_parse_t * p, x86_insn_t * insn)
-{
- u32 i = ~0;
- switch (x86_insn_immediate_type (insn))
- {
- case 'b': i = 0; break;
- case 'w': i = 1; break;
- case 'd': i = 2; break;
- case 'q': i = 3; break;
-
- case 'z':
- i = p->log2_effective_operand_bytes;
- if (i > 2) i = 2;
- break;
-
- case 'v':
- i = p->log2_effective_operand_bytes;
- break;
-
- default:
- i = ~0;
- break;
- }
-
- return i;
-}
-
-static u8 *
-x86_insn_parse_modrm_byte (x86_insn_parse_t * x,
- x86_insn_modrm_byte_t modrm,
- u32 parse_flags,
- u8 * code,
- u8 * code_end)
-{
- u8 effective_address_bits;
-
- if (parse_flags & X86_INSN_PARSE_64_BIT)
- effective_address_bits = (x->flags & X86_INSN_ADDRESS_SIZE) ? 32 : 64;
- else if (parse_flags & X86_INSN_PARSE_32_BIT)
- effective_address_bits = (x->flags & X86_INSN_ADDRESS_SIZE) ? 16 : 32;
- else
- effective_address_bits = (x->flags & X86_INSN_ADDRESS_SIZE) ? 32 : 16;
-
- x->log2_effective_address_bytes = 1;
- x->log2_effective_address_bytes += effective_address_bits > 16;
- x->log2_effective_address_bytes += effective_address_bits > 32;
-
- x->regs[0] |= modrm.reg;
- if (modrm.mode == 3)
- x->regs[1] |= modrm.rm;
- else
- {
- u32 log2_disp_bytes = ~0;
-
- x->flags |= X86_INSN_IS_ADDRESS;
-
- if (effective_address_bits != 16)
- {
- u8 has_sib_byte = 0;
-
- switch (modrm.mode)
- {
- case 0:
- /* When base is bp displacement is present for mode 0. */
- if (modrm.rm == X86_INSN_GP_REG_BP)
- {
- log2_disp_bytes = x->log2_effective_address_bytes;
- break;
- }
- else if (modrm.rm == X86_INSN_GP_REG_SP
- && effective_address_bits != 16)
- {
- has_sib_byte = 1;
- break;
- }
- /* fall through */
- case 1:
- case 2:
- x->regs[1] |= modrm.rm;
- x->flags |= X86_INSN_HAS_BASE;
- if (modrm.mode != 0)
- {
- log2_disp_bytes = (modrm.mode == 1
- ? 0
- : x->log2_effective_address_bytes);
- if (log2_disp_bytes > 2)
- log2_disp_bytes = 2;
- }
- break;
- }
-
- if (has_sib_byte)
- {
- x86_insn_sib_byte_t sib;
-
- if (code >= code_end)
- return 0;
- sib.byte = *code++;
-
- x->log2_index_scale = 1 << sib.log2_scale;
- x->regs[1] |= sib.base;
- x->flags |= X86_INSN_HAS_BASE;
-
- if (sib.index != X86_INSN_GP_REG_SP)
- {
- x->regs[2] |= sib.index;
- x->flags |= X86_INSN_HAS_INDEX;
- }
- }
- }
- else
- {
- /* effective_address_bits == 16 */
- switch (modrm.mode)
- {
- case 0:
- if (modrm.rm == 6)
- {
- /* [disp16] */
- log2_disp_bytes = 1;
- break;
- }
- /* fall through */
- case 1:
- case 2:
- switch (modrm.rm)
- {
- case 0: /* [bx + si/di] */
- case 1:
- x->regs[1] = X86_INSN_GP_REG_BX;
- x->regs[2] = X86_INSN_GP_REG_SI + (modrm.rm & 1);
- x->flags |= X86_INSN_HAS_BASE | X86_INSN_HAS_INDEX;
- break;
-
- case 2: /* [bp + si/di] */
- case 3:
- x->regs[1] = X86_INSN_GP_REG_BP;
- x->regs[2] = X86_INSN_GP_REG_SI + (modrm.rm & 1);
- x->flags |= X86_INSN_HAS_BASE | X86_INSN_HAS_INDEX;
- break;
-
- case 4: /* [si/di] */
- case 5:
- x->regs[1] = X86_INSN_GP_REG_SI + (modrm.rm & 1);
- x->flags |= X86_INSN_HAS_BASE;
- break;
-
- case 6: /* [bp + disp] */
- x->regs[1] = X86_INSN_GP_REG_BP;
- x->flags |= X86_INSN_HAS_BASE;
- break;
-
- case 7: /* [bx + disp] */
- x->regs[1] = X86_INSN_GP_REG_BX;
- x->flags |= X86_INSN_HAS_BASE;
- break;
- }
-
- if (modrm.mode != 0)
- log2_disp_bytes = modrm.mode == 1 ? 0 : 1;
- break;
- }
- }
-
- if (log2_disp_bytes != ~0)
- {
- i64 disp;
- code = x86_insn_parse_number (log2_disp_bytes, code, code_end,
- &disp);
- if (code)
- x->displacement = disp;
- }
- }
-
- return code;
-}
-
-u8 * x86_insn_parse (x86_insn_parse_t * p, u8 * code_start)
-{
- u8 i, * code, * code_end;
- x86_insn_t * insn, * group_insn;
- u8 default_operand_bits, effective_operand_bits;
- u32 opcode, parse_flags;
-
- /* Preserve global parse flags. */
- parse_flags = p->flags & (X86_INSN_PARSE_32_BIT | X86_INSN_PARSE_64_BIT);
- clib_memset (p, 0, sizeof (p[0]));
- p->flags = parse_flags;
-
- /* 64 implies 32 bit parsing. */
- if (parse_flags & X86_INSN_PARSE_64_BIT)
- parse_flags |= X86_INSN_PARSE_32_BIT;
-
- /* Instruction must be <= 15 bytes. */
- code = code_start;
- code_end = code + 15;
-
- /* Parse legacy prefixes. */
- while (1)
- {
- if (code >= code_end)
- goto insn_too_long;
- i = code[0];
- code++;
- switch (i)
- {
- default: goto prefix_done;
-
- /* Set flags based on prefix. */
-#define _(x,o) case o: p->flags |= X86_INSN_##x; break;
- foreach_x86_legacy_prefix;
-#undef _
- }
- }
- prefix_done:
-
- /* REX prefix. */
- if ((parse_flags & X86_INSN_PARSE_64_BIT) && i >= 0x40 && i <= 0x4f)
- {
- p->regs[0] |= ((i & (1 << 2)) != 0) << 3; /* r bit */
- p->regs[1] |= ((i & (1 << 0)) != 0) << 3; /* b bit */
- p->regs[2] |= ((i & (1 << 1)) != 0) << 3; /* x bit */
- p->flags |= ((i & (1 << 3)) /* w bit */
- ? X86_INSN_OPERAND_SIZE_64 : 0);
- if (code >= code_end)
- goto insn_too_long;
- i = *code++;
- }
-
- opcode = i;
- if (opcode == 0x0f)
- {
- /* two byte opcode. */;
- if (code >= code_end)
- goto insn_too_long;
- i = *code++;
- opcode = (opcode << 8) | i;
- insn = x86_insns_two_byte + i;
- }
- else
- {
- static x86_insn_t arpl = {
- .name = "arpl",
- .operands[0].data = "Ew",
- .operands[1].data = "Gw",
- };
-
- if (PREDICT_FALSE (i == 0x63
- && ! (parse_flags & X86_INSN_PARSE_64_BIT)))
- insn = &arpl;
- else
- insn = x86_insns_one_byte + i;
- }
-
- if ((i = X86_INSN_FLAG_GET_SSE_GROUP (insn->flags)) != 0)
- {
- x86_insn_group8_t * g8;
-
- if (p->flags & X86_INSN_OPERAND_SIZE)
- g8 = x86_insn_sse_groups_operand_size;
- else if (p->flags & X86_INSN_REPZ)
- g8 = x86_insn_sse_groups_repz;
- else if (p->flags & X86_INSN_REPNZ)
- g8 = x86_insn_sse_groups_repnz;
- else
- g8 = 0;
-
- /* insn flags have 1 + group so != 0 test above can work. */
- ASSERT ((i - 1) < ARRAY_LEN (x86_insn_sse_groups_operand_size));
- if (g8)
- insn = g8[i - 1].insns + (opcode & 7);
- }
-
- /* Parse modrm and displacement if present. */
- if (x86_insn_has_modrm_byte (insn))
- {
- x86_insn_modrm_byte_t modrm;
-
- if (code >= code_end)
- goto insn_too_long;
- modrm.byte = *code++;
-
- /* Handle special 0x0f01 and 0x0fae encodings. */
- if (PREDICT_FALSE (modrm.mode == 3
- && (opcode == 0x0f01
- || opcode == 0x0fae)))
- {
- static x86_insn_t x86_insns_0f01_special[] = {
- _0 (swapgs), _0 (rdtscp), _0 (bad), _0 (bad),
- _0 (bad), _0 (bad), _0 (bad), _0 (bad),
- };
- static x86_insn_t x86_insns_0fae_special[] = {
- _0 (vmrun), _0 (vmmcall), _0 (vmload), _0 (vmsave),
- _0 (stgi), _0 (clgi), _0 (skinit), _0 (invlpga),
- };
-
- if (opcode == 0x0f01)
- insn = x86_insns_0f01_special;
- else
- insn = x86_insns_0fae_special;
- insn += modrm.rm;
- opcode = (opcode << 8) | modrm.byte;
- }
- else
- {
- code = x86_insn_parse_modrm_byte (p, modrm, parse_flags,
- code, code_end);
- if (! code)
- goto insn_too_long;
- }
- }
-
- group_insn = 0;
- if ((i = X86_INSN_FLAG_GET_MODRM_REG_GROUP (insn->flags)) != 0)
- {
- u32 g = i - 1;
- ASSERT (g < ARRAY_LEN (x86_insn_modrm_reg_groups));
- group_insn = x86_insn_modrm_reg_groups[g].insns + (p->regs[0] & 7);
- }
-
- p->insn = insn[0];
- if (group_insn)
- {
- u32 k;
- p->insn.name = group_insn->name;
- p->insn.flags |= group_insn->flags;
- for (k = 0; k < ARRAY_LEN (group_insn->operands); k++)
- if (x86_insn_operand_is_valid (group_insn, k))
- p->insn.operands[k] = group_insn->operands[k];
- }
-
- default_operand_bits
- = ((((parse_flags & X86_INSN_PARSE_32_BIT) != 0)
- ^ ((p->flags & X86_INSN_OPERAND_SIZE) != 0))
- ? BITS (u32) : BITS (u16));
-
- if ((parse_flags & X86_INSN_PARSE_64_BIT)
- && (p->insn.flags & X86_INSN_FLAG_DEFAULT_64_BIT))
- default_operand_bits = BITS (u64);
-
- effective_operand_bits = default_operand_bits;
- if (p->flags & X86_INSN_OPERAND_SIZE_64)
- effective_operand_bits = BITS (u64);
-
- p->log2_effective_operand_bytes = 1;
- p->log2_effective_operand_bytes += effective_operand_bits > 16;
- p->log2_effective_operand_bytes += effective_operand_bits > 32;
-
- /* Parse immediate if present. */
- {
- u32 l = x86_insn_log2_immediate_bytes (p, insn);
- if (l <= 3)
- {
- code = x86_insn_parse_number (l, code, code_end, &p->immediate);
- if (! code)
- goto insn_too_long;
- }
- }
-
- return code;
-
- insn_too_long:
- return 0;
-}
-
-static u8 * format_x86_gp_reg_operand (u8 * s, va_list * va)
-{
- u32 r = va_arg (*va, u32);
- u32 log2_n_bytes = va_arg (*va, u32);
-
- const char names8[8] = "acdbsbsd";
- const char names16[8] = "xxxxppii";
-
- ASSERT (r < 16);
-
- /* Add % register prefix. */
- vec_add1 (s, '%');
-
- switch (log2_n_bytes)
- {
- case 0:
- {
-
- if (r < 8)
- s = format (s, "%c%c", names8[r & 3], (r >> 2) ? 'l' : 'h');
- else
- s = format (s, "r%db", r);
- }
- break;
-
- case 2:
- case 3:
- s = format (s, "%c", log2_n_bytes == 2 ? 'e' : 'r');
- /* fall through */
- case 1:
- if (r < 8)
- s = format (s, "%c%c", names8[r], names16[r]);
- else
- {
- s = format (s, "%d", r);
- if (log2_n_bytes != 3)
- s = format (s, "%c", log2_n_bytes == 1 ? 'w' : 'd');
- }
- break;
-
- default:
- ASSERT (0);
- }
-
- return s;
-}
-
-static u8 * format_x86_reg_operand (u8 * s, va_list * va)
-{
- u32 reg = va_arg (*va, u32);
- u32 log2_n_bytes = va_arg (*va, u32);
- u32 type = va_arg (*va, u32);
-
- switch (type)
- {
- default:
- ASSERT (0);
- break;
-
- case 'x':
- ASSERT (reg < 16);
- return format (s, "%%xmm%d", reg);
-
- case 'm':
- ASSERT (reg < 8);
- return format (s, "%%mm%d", reg);
-
- /* Explicit byte/word/double-word/quad-word */
- case 'b': log2_n_bytes = 0; break;
- case 'w': log2_n_bytes = 1; break;
- case 'd': log2_n_bytes = 2; break;
- case 'q': log2_n_bytes = 3; break;
-
- /* Use effective operand size. */
- case 'v': break;
-
- /* word or double-word depending on effective operand size. */
- case 'z':
- log2_n_bytes = clib_min (log2_n_bytes, 2);
- break;
- }
-
- s = format (s, "%U", format_x86_gp_reg_operand, reg, log2_n_bytes);
- return s;
-}
-
-static u8 * format_x86_mem_operand (u8 * s, va_list * va)
-{
- x86_insn_parse_t * p = va_arg (*va, x86_insn_parse_t *);
-
- if (p->displacement != 0)
- s = format (s, "0x%x", p->displacement);
-
- if (p->flags & X86_INSN_HAS_BASE)
- {
- s = format (s, "(%U",
- format_x86_gp_reg_operand, p->regs[1],
- p->log2_effective_address_bytes);
- if (p->flags & X86_INSN_HAS_INDEX)
- {
- s = format (s, ",%U",
- format_x86_gp_reg_operand, p->regs[2],
- p->log2_effective_address_bytes);
- if (p->log2_index_scale != 0)
- s = format (s, ",%d", 1 << p->log2_index_scale);
- }
- s = format (s, ")");
- }
-
- /* [RIP+disp] PC relative addressing in 64 bit mode. */
- else if (p->flags & X86_INSN_PARSE_64_BIT)
- s = format (s, "(%%rip)");
-
- return s;
-}
-
-static u8 * format_x86_insn_operand (u8 * s, va_list * va)
-{
- x86_insn_parse_t * p = va_arg (*va, x86_insn_parse_t *);
- x86_insn_t * insn = &p->insn;
- u32 o = va_arg (*va, u32);
- u8 c, t;
-
- ASSERT (o < ARRAY_LEN (insn->operands));
- c = insn->operands[o].code;
- t = insn->operands[o].type;
-
- /* Register encoded in instruction. */
- if (c < 8)
- return format (s, "%U",
- format_x86_gp_reg_operand, c,
- p->log2_effective_operand_bytes);
-
- switch (c)
- {
- /* Memory or reg field from modrm byte. */
- case 'M':
- ASSERT (p->flags & X86_INSN_IS_ADDRESS);
- /* FALLTHROUGH */
- case 'E':
- if (p->flags & X86_INSN_IS_ADDRESS)
- s = format (s, "%U", format_x86_mem_operand, p);
- else
- s = format (s, "%U",
- format_x86_reg_operand, p->regs[1],
- p->log2_effective_operand_bytes, t);
- break;
-
- /* reg field from modrm byte. */
- case 'R':
- case 'G':
- s = format (s, "%U",
- format_x86_reg_operand, p->regs[0],
- p->log2_effective_operand_bytes, t);
- break;
-
- case 'I':
- {
- u32 l = x86_insn_log2_immediate_bytes (p, insn);
- i64 mask = pow2_mask (8ULL << l);
- s = format (s, "$0x%Lx", p->immediate & mask);
- }
- break;
-
- case 'J':
- if (p->immediate < 0)
- s = format (s, "- 0x%Lx", -p->immediate);
- else
- s = format (s, "+ 0x%Lx", p->immediate);
- break;
-
- case 'O':
- s = format (s, "0x%Lx", p->immediate);
- break;
-
- case 'A':
- /* AX/AL */
- s = format (s, "%U",
- format_x86_gp_reg_operand, X86_INSN_GP_REG_AX,
- t == 'L' ? 0 : p->log2_effective_operand_bytes);
- break;
-
- case 'B':
- /* BX/BL/BP */
- s = format (s, "%U",
- format_x86_gp_reg_operand,
- t == 'P' ? X86_INSN_GP_REG_BP : X86_INSN_GP_REG_BX,
- t == 'L' ? 0 : p->log2_effective_operand_bytes);
- break;
-
- case 'C':
- /* CX/CL */
- s = format (s, "%U",
- format_x86_gp_reg_operand, X86_INSN_GP_REG_CX,
- t == 'L' ? 0 : p->log2_effective_operand_bytes);
- break;
-
- case 'D':
- /* DX/DL/DI */
- s = format (s, "%U",
- format_x86_gp_reg_operand,
- t == 'I' ? X86_INSN_GP_REG_DI : X86_INSN_GP_REG_DX,
- t == 'L' ? 0 : p->log2_effective_operand_bytes);
- break;
-
- case 'S':
- /* SI/SP */
- s = format (s, "%U",
- format_x86_gp_reg_operand,
- t == 'I' ? X86_INSN_GP_REG_SI : X86_INSN_GP_REG_SP,
- p->log2_effective_operand_bytes);
- break;
-
- case '1':
- s = format (s, "1");
- break;
-
- default:
- ASSERT (0);
- }
-
- return s;
-}
-
-u8 * format_x86_insn_parse (u8 * s, va_list * va)
-{
- x86_insn_parse_t * p = va_arg (*va, x86_insn_parse_t *);
- x86_insn_t * insn = &p->insn;
- u32 o, i, is_src_dst;
-
- s = format (s, "%s", insn->name);
-
- if (! x86_insn_operand_is_valid (insn, 0))
- goto done;
-
- is_src_dst = x86_insn_operand_is_valid (insn, 1);
-
- /* If instruction has immediate add suffix to opcode to
- indicate operand size. */
- if (is_src_dst)
- {
- u32 b;
-
- b = x86_insn_log2_immediate_bytes (p, insn);
- if (b < p->log2_effective_operand_bytes
- && (p->flags & X86_INSN_IS_ADDRESS))
- s = format (s, "%c", "bwlq"[b]);
- }
-
- for (i = 0; i < ARRAY_LEN (insn->operands); i++)
- {
- o = is_src_dst + i;
- if (! x86_insn_operand_is_valid (insn, o))
- break;
- s = format (s, "%s%U",
- i == 0 ? " " : ", ",
- format_x86_insn_operand, p, o);
- }
-
- if (is_src_dst)
- s = format (s, ", %U",
- format_x86_insn_operand, p, 0);
-
- done:
- return s;
-}
diff --git a/src/vppinfra/asm_x86.h b/src/vppinfra/asm_x86.h
deleted file mode 100644
index dacef61755c..00000000000
--- a/src/vppinfra/asm_x86.h
+++ /dev/null
@@ -1,125 +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 included_asm_x86_h
-#define included_asm_x86_h
-
-#include <vppinfra/format.h>
-
-typedef union
-{
- struct
- {
- u8 code;
- u8 type;
- };
- u8 data[2];
-} x86_insn_operand_t;
-
-typedef struct
-{
- /* Instruction name. */
- char *name;
-
- /* X86 instructions may have up to 3 operands. */
- x86_insn_operand_t operands[3];
-
- u16 flags;
-#define X86_INSN_FLAG_DEFAULT_64_BIT (1 << 0)
-#define X86_INSN_FLAG_SET_SSE_GROUP(n) ((n) << 5)
-#define X86_INSN_FLAG_GET_SSE_GROUP(f) (((f) >> 5) & 0x1f)
-#define X86_INSN_FLAG_SET_MODRM_REG_GROUP(n) (((n) & 0x3f) << 10)
-#define X86_INSN_FLAG_GET_MODRM_REG_GROUP(f) (((f) >> 10) & 0x3f)
-} x86_insn_t;
-
-always_inline uword
-x86_insn_operand_is_valid (x86_insn_t * i, uword o)
-{
- ASSERT (o < ARRAY_LEN (i->operands));
- return i->operands[o].code != '_';
-}
-
-#define foreach_x86_legacy_prefix \
- _ (OPERAND_SIZE, 0x66) \
- _ (ADDRESS_SIZE, 0x67) \
- _ (SEGMENT_CS, 0x2e) \
- _ (SEGMENT_DS, 0x3e) \
- _ (SEGMENT_ES, 0x26) \
- _ (SEGMENT_FS, 0x64) \
- _ (SEGMENT_GS, 0x65) \
- _ (SEGMENT_SS, 0x36) \
- _ (LOCK, 0xf0) \
- _ (REPZ, 0xf3) \
- _ (REPNZ, 0xf2)
-
-#define foreach_x86_insn_parse_flag \
- /* Parse in 32/64-bit mode. */ \
- _ (PARSE_32_BIT, 0) \
- _ (PARSE_64_BIT, 0) \
- _ (IS_ADDRESS, 0) \
- /* regs[1/2] is a valid base/index register */ \
- _ (HAS_BASE, 0) \
- _ (HAS_INDEX, 0) \
- /* rex w bit */ \
- _ (OPERAND_SIZE_64, 0)
-
-typedef enum
-{
-#define _(f,o) X86_INSN_FLAG_BIT_##f,
- foreach_x86_insn_parse_flag foreach_x86_legacy_prefix
-#undef _
-} x86_insn_parse_flag_bit_t;
-
-typedef enum
-{
-#define _(f,o) X86_INSN_##f = 1 << X86_INSN_FLAG_BIT_##f,
- foreach_x86_insn_parse_flag foreach_x86_legacy_prefix
-#undef _
-} x86_insn_parse_flag_t;
-
-typedef struct
-{
- /* Registers in instruction.
- [0] is modrm reg field
- [1] is base reg
- [2] is index reg. */
- u8 regs[3];
-
- /* Scale for index register. */
- u8 log2_index_scale:2;
- u8 log2_effective_operand_bytes:3;
- u8 log2_effective_address_bytes:3;
-
- i32 displacement;
-
- /* Parser flags: set of x86_insn_parse_flag_t enums. */
- u32 flags;
-
- i64 immediate;
-
- x86_insn_t insn;
-} x86_insn_parse_t;
-
-u8 *x86_insn_parse (x86_insn_parse_t * p, u8 * code_start);
-format_function_t format_x86_insn_parse;
-
-#endif /* included_asm_x86_h */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/src/vppinfra/backtrace.c b/src/vppinfra/backtrace.c
deleted file mode 100644
index e713bae6876..00000000000
--- a/src/vppinfra/backtrace.c
+++ /dev/null
@@ -1,260 +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.
- */
-/*
- Copyright (c) 2004 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.
-*/
-
-#include <vppinfra/clib.h>
-#include <vppinfra/error.h>
-
-#ifdef __mips__
-
-/* Let code below know we've defined _clib_backtrace */
-#define clib_backtrace_defined
-
-#include <vppinfra/asm_mips.h>
-
-__clib_export uword
-clib_backtrace (uword * callers, uword max_callers, uword n_frames_to_skip)
-{
- u32 *pc;
- void *sp;
- uword i, saved_pc;
-
- /* Figure current PC, saved PC and stack pointer. */
- asm volatile (".set push\n"
- ".set noat\n" "move %[saved_pc], $31\n" "move %[sp], $29\n"
- /* Fetches current PC. */
- "la $at, 1f\n"
- "jalr %[pc], $at\n"
- "nop\n"
- "1:\n"
- ".set pop\n":[pc] "=r" (pc),
- [saved_pc] "=r" (saved_pc),[sp] "=r" (sp));
-
- /* Also skip current frame. */
- n_frames_to_skip += 1;
-
- for (i = 0; i < max_callers + n_frames_to_skip; i++)
- {
- mips_insn_opcode_t op;
- mips_insn_special_funct_t funct;
- i32 insn, rs, rt, rd, immediate, found_saved_pc;
- u32 *start_pc;
-
- /* Parse instructions until we reach prologue for this
- stack frame. We'll need to figure out where saved
- PC is and where previous stack frame lives. */
- start_pc = pc;
- found_saved_pc = 0;
- while (1)
- {
- insn = *--pc;
- op = mips_insn_get_op (insn);
- funct = mips_insn_get_funct (insn);
- rs = mips_insn_get_rs (insn);
- rt = mips_insn_get_rt (insn);
- rd = mips_insn_get_rd (insn);
- immediate = mips_insn_get_immediate (insn);
-
- switch (op)
- {
- default:
- break;
-
- case MIPS_OPCODE_sd:
- case MIPS_OPCODE_sw:
- /* Trace stores of return address. */
- if (rt == MIPS_REG_RA)
- {
- void *addr = sp + immediate;
-
- /* If RA is stored somewhere other than in the
- stack frame, give up. */
- if (rs != MIPS_REG_SP)
- goto backtrace_done;
-
- ASSERT (immediate % 4 == 0);
- if (op == MIPS_OPCODE_sw)
- saved_pc = ((u32 *) addr)[0];
- else
- saved_pc = ((u64 *) addr)[0];
- found_saved_pc = 1;
- }
- break;
-
- case MIPS_OPCODE_addiu:
- case MIPS_OPCODE_daddiu:
- case MIPS_OPCODE_addi:
- case MIPS_OPCODE_daddi:
- if (rt == MIPS_REG_SP)
- {
- if (rs != MIPS_REG_SP)
- goto backtrace_done;
-
- ASSERT (immediate % 4 == 0);
-
- /* Assume positive offset is part of the epilogue.
- E.g.
- jr ra
- add sp,sp,100
- */
- if (immediate > 0)
- continue;
-
- /* Negative offset means allocate stack space.
- This could either be the prologue or could be due to
- alloca. */
- sp -= immediate;
-
- /* This frame will not save RA. */
- if (i == 0)
- goto found_prologue;
-
- /* Assume that addiu sp,sp,-N without store of ra means
- that we have not found the prologue yet. */
- if (found_saved_pc)
- goto found_prologue;
- }
- break;
-
- case MIPS_OPCODE_slti:
- case MIPS_OPCODE_sltiu:
- case MIPS_OPCODE_andi:
- case MIPS_OPCODE_ori:
- case MIPS_OPCODE_xori:
- case MIPS_OPCODE_lui:
- case MIPS_OPCODE_ldl:
- case MIPS_OPCODE_ldr:
- case MIPS_OPCODE_lb:
- case MIPS_OPCODE_lh:
- case MIPS_OPCODE_lwl:
- case MIPS_OPCODE_lw:
- case MIPS_OPCODE_lbu:
- case MIPS_OPCODE_lhu:
- case MIPS_OPCODE_lwr:
- case MIPS_OPCODE_lwu:
- case MIPS_OPCODE_ld:
- /* Give up when we find anyone setting the stack pointer. */
- if (rt == MIPS_REG_SP)
- goto backtrace_done;
- break;
-
- case MIPS_OPCODE_SPECIAL:
- if (rd == MIPS_REG_SP)
- switch (funct)
- {
- default:
- /* Give up when we find anyone setting the stack pointer. */
- goto backtrace_done;
-
- case MIPS_SPECIAL_FUNCT_break:
- case MIPS_SPECIAL_FUNCT_jr:
- case MIPS_SPECIAL_FUNCT_sync:
- case MIPS_SPECIAL_FUNCT_syscall:
- case MIPS_SPECIAL_FUNCT_tge:
- case MIPS_SPECIAL_FUNCT_tgeu:
- case MIPS_SPECIAL_FUNCT_tlt:
- case MIPS_SPECIAL_FUNCT_tltu:
- case MIPS_SPECIAL_FUNCT_teq:
- case MIPS_SPECIAL_FUNCT_tne:
- /* These instructions can validly have rd == MIPS_REG_SP */
- break;
- }
- break;
- }
- }
-
- found_prologue:
- /* Check sanity of saved pc. */
- if (saved_pc & 3)
- goto backtrace_done;
- if (saved_pc == 0)
- goto backtrace_done;
-
- if (i >= n_frames_to_skip)
- callers[i - n_frames_to_skip] = saved_pc;
- pc = uword_to_pointer (saved_pc, u32 *);
- }
-
-backtrace_done:
- if (i < n_frames_to_skip)
- return 0;
- else
- return i - n_frames_to_skip;
-}
-#endif /* __mips__ */
-
-#ifndef clib_backtrace_defined
-#define clib_backtrace_defined
-
-/* use glibc backtrace for stack trace */
-#include <execinfo.h>
-
-__clib_export uword
-clib_backtrace (uword * callers, uword max_callers, uword n_frames_to_skip)
-{
- int size;
- void *array[20];
- /* Also skip current frame. */
- n_frames_to_skip += 1;
-
- size = clib_min (ARRAY_LEN (array), max_callers + n_frames_to_skip);
-
- size = backtrace (array, size);
-
- uword i;
-
- for (i = 0; i < max_callers + n_frames_to_skip && i < size; i++)
- {
- if (i >= n_frames_to_skip)
- callers[i - n_frames_to_skip] = pointer_to_uword (array[i]);
- }
-
- if (i < n_frames_to_skip)
- return 0;
- else
- return i - n_frames_to_skip;
-}
-
-
-#endif /* clib_backtrace_defined */
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "gnu")
- * End:
- */
diff --git a/src/vppinfra/cJSON.c b/src/vppinfra/cJSON.c
index 448435de4dc..24e0110ed08 100644
--- a/src/vppinfra/cJSON.c
+++ b/src/vppinfra/cJSON.c
@@ -20,6 +20,7 @@
THE SOFTWARE.
*/
/* clang-format off */
+
/* cJSON */
/* JSON parser in C. */
@@ -96,9 +97,9 @@ CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
return (const char*) (global_error.json + global_error.position);
}
-CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item)
+CJSON_PUBLIC (char *) cJSON_GetStringValue (const cJSON *const item)
{
- if (!cJSON_IsString(item))
+ if (!cJSON_IsString (item))
{
return NULL;
}
@@ -106,9 +107,9 @@ CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item)
return item->valuestring;
}
-CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item)
+CJSON_PUBLIC (double) cJSON_GetNumberValue (const cJSON *const item)
{
- if (!cJSON_IsNumber(item))
+ if (!cJSON_IsNumber (item))
{
return (double) NAN;
}
@@ -117,8 +118,9 @@ CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item)
}
/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */
-#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 14)
- #error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
+#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || \
+ (CJSON_VERSION_PATCH != 17)
+#error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
#endif
CJSON_PUBLIC(const char*) cJSON_Version(void)
@@ -157,7 +159,7 @@ typedef struct internal_hooks
{
void *(CJSON_CDECL *allocate)(size_t size);
void (CJSON_CDECL *deallocate)(void *pointer);
- void *(CJSON_CDECL *reallocate)(void *pointer, size_t new_size, size_t old_size);
+ void *(CJSON_CDECL *reallocate) (void *pointer, size_t size);
} internal_hooks;
#if defined(_MSC_VER)
@@ -170,20 +172,17 @@ static void CJSON_CDECL internal_free(void *pointer)
{
free(pointer);
}
+static void *CJSON_CDECL
+internal_realloc (void *pointer, size_t size)
+{
+ return realloc (pointer, size);
+}
#else
#define internal_malloc malloc
#define internal_free free
+#define internal_realloc realloc
#endif
-static void * CJSON_CDECL internal_realloc(void *pointer, size_t new_size,
- size_t old_size)
-{
- return realloc(pointer, new_size);
-}
-
-static void *
-cjson_realloc_internal (void *ptr, size_t new_size, size_t old_size);
-
/* strlen of character literals resolved at compile time */
#define static_strlen(string_literal) (sizeof(string_literal) - sizeof(""))
@@ -217,8 +216,8 @@ CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks)
/* Reset hooks */
global_hooks.allocate = malloc;
global_hooks.deallocate = free;
- global_hooks.reallocate = internal_realloc;
- return;
+ global_hooks.reallocate = realloc;
+ return;
}
global_hooks.allocate = malloc;
@@ -233,16 +232,11 @@ CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks)
global_hooks.deallocate = hooks->free_fn;
}
- /* use realloc only if both free and malloc are used */
- global_hooks.reallocate = NULL;
- if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free))
- {
- global_hooks.reallocate = internal_realloc;
- }
- else
- {
- global_hooks.reallocate = cjson_realloc_internal;
- }
+ global_hooks.reallocate = realloc;
+ if (hooks->realloc_fn != NULL)
+ {
+ global_hooks.reallocate = hooks->realloc_fn;
+ }
}
/* Internal constructor. */
@@ -405,14 +399,22 @@ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
return object->valuedouble = number;
}
+/* Note: when passing a NULL valuestring, cJSON_SetValuestring treats this as
+ * an error and return NULL */
CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring)
{
char *copy = NULL;
/* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */
- if (!(object->type & cJSON_String) || (object->type & cJSON_IsReference))
- {
- return NULL;
- }
+ if ((object == NULL) || !(object->type & cJSON_String) ||
+ (object->type & cJSON_IsReference))
+ {
+ return NULL;
+ }
+ /* return NULL if the object is corrupted or valuestring is NULL */
+ if (object->valuestring == NULL || valuestring == NULL)
+ {
+ return NULL;
+ }
if (strlen(valuestring) <= strlen(object->valuestring))
{
strcpy(object->valuestring, valuestring);
@@ -443,27 +445,6 @@ typedef struct
internal_hooks hooks;
} printbuffer;
-static void *
-cjson_realloc_internal (void *ptr, size_t new_size, size_t old_size)
-{
- size_t copy_size;
- if (old_size < new_size)
- copy_size = old_size;
- else
- copy_size = new_size;
-
- unsigned char *newbuffer = global_hooks.allocate(new_size);
- if (!newbuffer)
- {
- global_hooks.deallocate(ptr);
- return NULL;
- }
-
- memcpy (newbuffer, ptr, copy_size);
- global_hooks.deallocate (ptr);
- return newbuffer;
-}
-
/* realloc printbuffer if necessary to have at least "needed" bytes more */
static unsigned char* ensure(printbuffer * const p, size_t needed)
{
@@ -515,14 +496,35 @@ static unsigned char* ensure(printbuffer * const p, size_t needed)
newsize = needed * 2;
}
- newbuffer = p->hooks.reallocate (p->buffer, newsize, p->length);
- if (newbuffer == NULL)
- {
- p->hooks.deallocate(p->buffer);
- p->length = 0;
- p->buffer = NULL;
- return NULL;
- }
+ if (p->hooks.reallocate != NULL)
+ {
+ /* reallocate with realloc if available */
+ newbuffer = (unsigned char *) p->hooks.reallocate (p->buffer, newsize);
+ if (newbuffer == NULL)
+ {
+ p->hooks.deallocate (p->buffer);
+ p->length = 0;
+ p->buffer = NULL;
+
+ return NULL;
+ }
+ }
+ else
+ {
+ /* otherwise reallocate manually */
+ newbuffer = (unsigned char *) p->hooks.allocate (newsize);
+ if (!newbuffer)
+ {
+ p->hooks.deallocate (p->buffer);
+ p->length = 0;
+ p->buffer = NULL;
+
+ return NULL;
+ }
+
+ memcpy (newbuffer, p->buffer, p->offset + 1);
+ p->hooks.deallocate (p->buffer);
+ }
p->length = newsize;
p->buffer = newbuffer;
@@ -570,6 +572,10 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out
{
length = sprintf((char*)number_buffer, "null");
}
+ else if (d == (double) item->valueint)
+ {
+ length = sprintf ((char *) number_buffer, "%d", item->valueint);
+ }
else
{
/* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
@@ -1111,7 +1117,7 @@ CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer
}
buffer.content = (const unsigned char*)value;
- buffer.length = buffer_length;
+ buffer.length = buffer_length;
buffer.offset = 0;
buffer.hooks = global_hooks;
@@ -1216,11 +1222,13 @@ static unsigned char *print(const cJSON * const item, cJSON_bool format, const i
/* check if reallocate is available */
if (hooks->reallocate != NULL)
{
- printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1, default_buffer_size);
- if (printed == NULL) {
- goto fail;
- }
- buffer->buffer = NULL;
+ printed = (unsigned char *) hooks->reallocate (buffer->buffer,
+ buffer->offset + 1);
+ if (printed == NULL)
+ {
+ goto fail;
+ }
+ buffer->buffer = NULL;
}
else /* otherwise copy the JSON over to a new buffer */
{
@@ -1658,8 +1666,13 @@ static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_bu
current_item = new_item;
}
- /* parse the name of the child */
- input_buffer->offset++;
+ if (cannot_access_at_index (input_buffer, 1))
+ {
+ goto fail; /* nothing comes after the comma */
+ }
+
+ /* parse the name of the child */
+ input_buffer->offset++;
buffer_skip_whitespace(input_buffer);
if (!parse_string(current_item, input_buffer))
{
@@ -2268,10 +2281,10 @@ CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON
{
cJSON *after_inserted = NULL;
- if (which < 0)
- {
- return false;
- }
+ if (which < 0 || newitem == NULL)
+ {
+ return false;
+ }
after_inserted = get_array_item(array, (size_t)which);
if (after_inserted == NULL)
@@ -2279,6 +2292,12 @@ CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON
return add_item_to_array(array, newitem);
}
+ if (after_inserted != array->child && after_inserted->prev == NULL)
+ {
+ /* return false if after_inserted is a corrupted array item */
+ return false;
+ }
+
newitem->next = after_inserted;
newitem->prev = after_inserted->prev;
after_inserted->prev = newitem;
@@ -2295,7 +2314,8 @@ CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement)
{
- if ((parent == NULL) || (replacement == NULL) || (item == NULL))
+ if ((parent == NULL) || (parent->child == NULL) || (replacement == NULL) ||
+ (item == NULL))
{
return false;
}
@@ -2365,6 +2385,11 @@ static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSO
cJSON_free(replacement->string);
}
replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
+ if (replacement->string == NULL)
+ {
+ return false;
+ }
+
replacement->type &= ~cJSON_StringIsConst;
return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);
@@ -2639,9 +2664,9 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
for (i = 0; a && (i < (size_t) count); i++)
{
- n = cJSON_CreateNumber(numbers[i]);
- if(!n)
- {
+ n = cJSON_CreateNumber (numbers[i]);
+ if (!n)
+ {
cJSON_Delete(a);
return NULL;
}
@@ -2988,7 +3013,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive)
{
- if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)) || cJSON_IsInvalid(a))
+ if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)))
{
return false;
}
@@ -3121,7 +3146,7 @@ CJSON_PUBLIC(void) cJSON_free(void *object)
global_hooks.deallocate(object);
}
-CJSON_PUBLIC(void *) cJSON_realloc(void *object, size_t new_size, size_t old_size)
+CJSON_PUBLIC (void *) cJSON_realloc (void *object, size_t size)
{
- return global_hooks.reallocate(object, new_size, old_size);
+ return global_hooks.reallocate (object, size);
}
diff --git a/src/vppinfra/cJSON.h b/src/vppinfra/cJSON.h
index 1474c4e5c49..1c98dfac70e 100644
--- a/src/vppinfra/cJSON.h
+++ b/src/vppinfra/cJSON.h
@@ -81,7 +81,7 @@ then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJ
/* project version */
#define CJSON_VERSION_MAJOR 1
#define CJSON_VERSION_MINOR 7
-#define CJSON_VERSION_PATCH 14
+#define CJSON_VERSION_PATCH 17
#include <stddef.h>
@@ -127,8 +127,7 @@ typedef struct cJSON_Hooks
/* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */
void *(CJSON_CDECL *malloc_fn)(size_t sz);
void (CJSON_CDECL *free_fn)(void *ptr);
- void *(CJSON_CDECL *realloc_fn) (void *ptr, size_t new_size,
- size_t old_size);
+ void *(CJSON_CDECL *realloc_fn) (void *ptr, size_t sz);
} cJSON_Hooks;
typedef int cJSON_bool;
@@ -256,9 +255,10 @@ CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
* case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */
CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);
-/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings.
- * The input pointer json cannot point to a read-only address area, such as a string constant,
- * but should point to a readable and writable adress area. */
+/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n')
+ * from strings. The input pointer json cannot point to a read-only address
+ * area, such as a string constant,
+ * but should point to a readable and writable address area. */
CJSON_PUBLIC(void) cJSON_Minify(char *json);
/* Helper functions for creating and adding items to an object at the same time.
@@ -281,14 +281,21 @@ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */
CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring);
+/* If the object is not a boolean type this does nothing and returns
+ * cJSON_Invalid else it returns the new type*/
+#define cJSON_SetBoolValue(object, boolValue) \
+ ((object != NULL && ((object)->type & (cJSON_False | cJSON_True))) ? \
+ (object)->type = ((object)->type & (~(cJSON_False | cJSON_True))) | \
+ ((boolValue) ? cJSON_True : cJSON_False) : \
+ cJSON_Invalid)
+
/* Macro for iterating over an array or object */
#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */
CJSON_PUBLIC(void *) cJSON_malloc(size_t size);
CJSON_PUBLIC(void) cJSON_free(void *object);
-CJSON_PUBLIC (void *)
-cJSON_realloc (void *object, size_t new_size, size_t old_size);
+CJSON_PUBLIC (void *) cJSON_realloc (void *object, size_t size);
#ifdef __cplusplus
}
diff --git a/src/vppinfra/clib.h b/src/vppinfra/clib.h
index d14582492d6..75cebc65672 100644
--- a/src/vppinfra/clib.h
+++ b/src/vppinfra/clib.h
@@ -385,10 +385,6 @@ void qsort (void *base, uword n, uword size,
int (*)(const void *, const void *));
#endif
-/* Stack backtrace. */
-uword
-clib_backtrace (uword * callers, uword max_callers, uword n_frames_to_skip);
-
#include <vppinfra/byte_order.h>
#endif /* included_clib_h */
diff --git a/src/vppinfra/format_ansi.h b/src/vppinfra/format_ansi.h
new file mode 100644
index 00000000000..c35406aacf7
--- /dev/null
+++ b/src/vppinfra/format_ansi.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: Apache-2.0
+ * Copyright (c) 2024 Cisco Systems, Inc.
+ */
+
+#ifndef __FORMAT_ANSI_H__
+#define __FORMAT_ANSI_H__
+
+#define ANSI_RESET "\x1b[0m"
+#define ANSI_BOLD "\x1b[1m"
+#define ANSI_ITALIC "\x1b[3m"
+#define ANSI_UNDERLINE "\x1b[4m"
+#define ANSI_BLINK "\x1b[5m"
+#define ANSI_FG_BLACK "\x1b[30m"
+#define ANSI_FG_RED "\x1b[31m"
+#define ANSI_FG_GREEN "\x1b[32m"
+#define ANSI_FG_YELLOW "\x1b[33m"
+#define ANSI_FG_BLUE "\x1b[34m"
+#define ANSI_FG_MAGENTA "\x1b[35m"
+#define ANSI_FG_CYAN "\x1b[36m"
+#define ANSI_FG_WHITE "\x1b[37m"
+#define ANSI_FG_DEFAULT "\x1b[39m"
+#define ANSI_BG_BLACK "\x1b[40m"
+#define ANSI_BG_RED "\x1b[41m"
+#define ANSI_BG_GREEN "\x1b[42m"
+#define ANSI_BG_YELLOW "\x1b[43m"
+#define ANSI_BG_BLUE "\x1b[44m"
+#define ANSI_BG_MAGENTA "\x1b[45m"
+#define ANSI_BG_CYAN "\x1b[46m"
+#define ANSI_BG_WHITE "\x1b[47m"
+#define ANSI_BG_DEFAULT "\x1b[49m"
+#define ANSI_FG_BR_BLACK "\x1b[90m"
+#define ANSI_FG_BR_RED "\x1b[91m"
+#define ANSI_FG_BR_GREEN "\x1b[92m"
+#define ANSI_FG_BR_YELLOW "\x1b[93m"
+#define ANSI_FG_BR_BLUE "\x1b[94m"
+#define ANSI_FG_BR_MAGENTA "\x1b[95m"
+#define ANSI_FG_BR_CYAN "\x1b[96m"
+#define ANSI_FG_BR_WHITE "\x1b[97m"
+#define ANSI_BG_BR_BLACK "\x1b[100m"
+#define ANSI_BG_BR_RED "\x1b[101m"
+#define ANSI_BG_BR_GREEN "\x1b[102m"
+#define ANSI_BG_BR_YELLOW "\x1b[103m"
+#define ANSI_BG_BR_BLUE "\x1b[104m"
+#define ANSI_BG_BR_MAGENTA "\x1b[105m"
+#define ANSI_BG_BR_CYAN "\x1b[106m"
+#define ANSI_BG_BR_WHITE "\x1b[107m"
+
+#endif /* __FORMAT_ANSI_H__ */
diff --git a/src/vppinfra/heap.c b/src/vppinfra/heap.c
index 7db814200f8..9920528732d 100644
--- a/src/vppinfra/heap.c
+++ b/src/vppinfra/heap.c
@@ -680,6 +680,7 @@ debug_elt (u8 * s, void *v, word i, word n)
i = -n / 2;
for (e = e0; 1; e = heap_next (e))
{
+ s = format (s, " ");
if (heap_is_free (e))
s = format (s, "index %4d, free\n", e - h->elts);
else if (h->format_elt)
diff --git a/src/vppinfra/mem_dlmalloc.c b/src/vppinfra/mem_dlmalloc.c
index a188164a7ba..e98687fff2a 100644
--- a/src/vppinfra/mem_dlmalloc.c
+++ b/src/vppinfra/mem_dlmalloc.c
@@ -19,6 +19,7 @@
#include <vppinfra/lock.h>
#include <vppinfra/hash.h>
#include <vppinfra/elf_clib.h>
+#include <vppinfra/stack.h>
typedef struct
{
@@ -65,15 +66,13 @@ mheap_get_trace_internal (const clib_mem_heap_t *heap, uword offset,
{
mheap_trace_main_t *tm = &mheap_trace_main;
mheap_trace_t *t;
- uword i, n_callers, trace_index, *p;
- mheap_trace_t trace;
+ uword i, trace_index, *p;
+ mheap_trace_t trace = {};
+ int index;
if (heap != tm->current_traced_mheap || mheap_trace_thread_disable)
return;
- /* Spurious Coverity warnings be gone. */
- clib_memset (&trace, 0, sizeof (trace));
-
clib_spinlock_lock (&tm->lock);
/* heap could have changed while we were waiting on the lock */
@@ -83,9 +82,19 @@ mheap_get_trace_internal (const clib_mem_heap_t *heap, uword offset,
/* Turn off tracing for this thread to avoid embarrassment... */
mheap_trace_thread_disable = 1;
- /* Skip our frame and mspace_get_aligned's frame */
- n_callers = clib_backtrace (trace.callers, ARRAY_LEN (trace.callers), 2);
- if (n_callers == 0)
+ index = -2; /* skip first 2 stack frames */
+ foreach_clib_stack_frame (sf)
+ {
+ if (index >= 0)
+ {
+ if (index == ARRAY_LEN (trace.callers))
+ break;
+ trace.callers[index] = sf->ip;
+ }
+ index++;
+ }
+
+ if (index < 1)
goto out;
if (!tm->trace_by_callers)
diff --git a/src/vppinfra/mhash.c b/src/vppinfra/mhash.c
index f0f1aa470d7..babaaeec726 100644
--- a/src/vppinfra/mhash.c
+++ b/src/vppinfra/mhash.c
@@ -164,6 +164,8 @@ mhash_sanitize_hash_user (mhash_t * mh)
h->user = pointer_to_uword (mh);
}
+static u8 *mhash_format_pair_default (u8 *s, va_list *args);
+
__clib_export void
mhash_init (mhash_t * h, uword n_value_bytes, uword n_key_bytes)
{
@@ -208,12 +210,12 @@ mhash_init (mhash_t * h, uword n_value_bytes, uword n_key_bytes)
vec_validate (h->key_tmps, os_get_nthreads () - 1);
ASSERT (n_key_bytes < ARRAY_LEN (t));
- h->hash = hash_create2 ( /* elts */ 0,
+ h->hash = hash_create2 (/* elts */ 0,
/* user */ pointer_to_uword (h),
/* value_bytes */ n_value_bytes,
t[n_key_bytes].key_sum, t[n_key_bytes].key_equal,
/* format pair/arg */
- 0, 0);
+ mhash_format_pair_default, 0);
}
static uword
@@ -331,8 +333,8 @@ mhash_set_mem (mhash_t * h, void *key, uword * new_value, uword * old_value)
{
if (key_alloc_from_free_list)
{
- h->key_vector_free_indices[l] = i;
- vec_set_len (h->key_vector_free_indices, l + 1);
+ vec_set_len (h->key_vector_free_indices, l);
+ h->key_vector_free_indices[l - 1] = i;
}
else
vec_dec_len (h->key_vector_or_heap, h->n_key_bytes);
@@ -371,8 +373,8 @@ mhash_unset (mhash_t * h, void *key, uword * old_value)
return 1;
}
-u8 *
-format_mhash_key (u8 * s, va_list * va)
+__clib_export u8 *
+format_mhash_key (u8 *s, va_list *va)
{
mhash_t *h = va_arg (*va, mhash_t *);
u32 ki = va_arg (*va, u32);
@@ -387,7 +389,43 @@ format_mhash_key (u8 * s, va_list * va)
else if (h->format_key)
s = format (s, "%U", h->format_key, k);
else
- s = format (s, "%U", format_hex_bytes, k, h->n_key_bytes);
+ s = format (s, "0x%U", format_hex_bytes, k, h->n_key_bytes);
+
+ return s;
+}
+
+static u8 *
+mhash_format_pair_default (u8 *s, va_list *args)
+{
+ void *CLIB_UNUSED (user_arg) = va_arg (*args, void *);
+ void *v = va_arg (*args, void *);
+ hash_pair_t *p = va_arg (*args, hash_pair_t *);
+ hash_t *h = hash_header (v);
+ mhash_t *mh = uword_to_pointer (h->user, mhash_t *);
+
+ s = format (s, "%U", format_mhash_key, mh, (u32) p->key);
+ if (hash_value_bytes (h) > 0)
+ s = format (s, " -> 0x%8U", format_hex_bytes, &p->value[0],
+ hash_value_bytes (h));
+ return s;
+}
+
+__clib_export u8 *
+format_mhash (u8 *s, va_list *va)
+{
+ mhash_t *h = va_arg (*va, mhash_t *);
+ int verbose = va_arg (*va, int);
+
+ s = format (s, "mhash %p, %wd elts, \n", h, mhash_elts (h));
+ if (mhash_key_vector_is_heap (h))
+ s = format (s, " %U", format_heap, h->key_vector_or_heap, verbose);
+ else
+ s = format (s, " keys %wd elts, %wd size, %wd free, %wd bytes used\n",
+ vec_len (h->key_vector_or_heap) / h->n_key_bytes,
+ h->n_key_bytes, vec_len (h->key_vector_free_indices),
+ vec_bytes (h->key_vector_or_heap) +
+ vec_bytes (h->key_vector_free_indices));
+ s = format (s, " %U", format_hash, h->hash, verbose);
return s;
}
diff --git a/src/vppinfra/mhash.h b/src/vppinfra/mhash.h
index 7eb1918384e..62aee365fa3 100644
--- a/src/vppinfra/mhash.h
+++ b/src/vppinfra/mhash.h
@@ -166,8 +166,13 @@ do { \
})); \
} while (0)
+u8 *format_mhash (u8 *s, va_list *va);
+
format_function_t format_mhash_key;
+/* Main test routine. */
+int test_mhash_main (unformat_input_t *input);
+
#endif /* included_clib_mhash_h */
/*
diff --git a/src/vppinfra/stack.c b/src/vppinfra/stack.c
new file mode 100644
index 00000000000..190e880c228
--- /dev/null
+++ b/src/vppinfra/stack.c
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: Apache-2.0
+ * Copyright (c) 2024 Cisco Systems, Inc.
+ */
+
+#define _GNU_SOURCE
+#include <dlfcn.h>
+
+#include <vppinfra/clib.h>
+#include <vppinfra/stack.h>
+#include <vppinfra/error.h>
+
+#if HAVE_LIBUNWIND == 1
+
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+
+static __thread unw_cursor_t cursor;
+static __thread unw_context_t context;
+
+#endif
+
+__clib_export clib_stack_frame_t *
+clib_stack_frame_get (clib_stack_frame_t *sf)
+{
+#if HAVE_LIBUNWIND == 1
+ Dl_info info = {};
+
+ if (sf->index == 0)
+ {
+ if (unw_getcontext (&context) < 0)
+ {
+ clib_warning ("libunwind: cannot get local machine state\n");
+ return 0;
+ }
+ if (unw_init_local (&cursor, &context) < 0)
+ {
+ clib_warning (
+ "libunwind: cannot initialize cursor for local unwinding\n");
+ return 0;
+ }
+ if (unw_step (&cursor) < 1)
+ return 0;
+ }
+ else if (unw_step (&cursor) < 1)
+ return 0;
+
+ if (unw_get_reg (&cursor, UNW_REG_IP, &sf->ip))
+ {
+ clib_warning ("libunwind: cannot read IP\n");
+ return 0;
+ }
+
+ if (unw_get_reg (&cursor, UNW_REG_SP, &sf->sp))
+ {
+ clib_warning ("libunwind: cannot read SP\n");
+ return 0;
+ }
+
+ if (unw_get_proc_name (&cursor, sf->name, sizeof (sf->name), &sf->offset) <
+ 0)
+ sf->name[0] = sf->offset = 0;
+
+ sf->is_signal_frame = unw_is_signal_frame (&cursor) ? 1 : 0;
+
+ if (dladdr ((void *) sf->ip, &info))
+ sf->file_name = info.dli_fname;
+ else
+ sf->file_name = 0;
+
+ sf->index++;
+ return sf;
+#else
+ return 0;
+#endif
+}
diff --git a/src/vppinfra/stack.h b/src/vppinfra/stack.h
new file mode 100644
index 00000000000..98a621d4176
--- /dev/null
+++ b/src/vppinfra/stack.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: Apache-2.0
+ * Copyright (c) 2024 Cisco Systems, Inc.
+ */
+
+#ifndef __STACK_H__
+#define __STACK_H__
+
+#include <vppinfra/clib.h>
+
+typedef struct
+{
+ uword ip, sp;
+ uword offset;
+ char name[64];
+ const char *file_name;
+ u32 index;
+ u8 is_signal_frame;
+} clib_stack_frame_t;
+
+clib_stack_frame_t *clib_stack_frame_get (clib_stack_frame_t *);
+
+#define foreach_clib_stack_frame(sf) \
+ for (clib_stack_frame_t _sf = {}, *sf = clib_stack_frame_get (&_sf); sf; \
+ sf = clib_stack_frame_get (sf))
+
+#endif /* __STACK_H__ */
diff --git a/src/vppinfra/test_mhash.c b/src/vppinfra/test_mhash.c
new file mode 100644
index 00000000000..70be2b9b382
--- /dev/null
+++ b/src/vppinfra/test_mhash.c
@@ -0,0 +1,403 @@
+/* SPDX-License-Identifier: Apache-2.0
+ * Copyright(c) 2023 Yandex LLC.
+ */
+
+#ifdef CLIB_LINUX_KERNEL
+#include <linux/unistd.h>
+#endif
+
+#ifdef CLIB_UNIX
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <vppinfra/time.h>
+#endif
+
+#include <vppinfra/random.h>
+#include <vppinfra/mem.h>
+#include <vppinfra/hash.h>
+#include <vppinfra/mhash.h>
+#include <vppinfra/error.h>
+#include <vppinfra/format.h>
+#include <vppinfra/bitmap.h>
+
+static int verbose;
+#define if_verbose(format, args...) \
+ if (verbose) \
+ { \
+ clib_warning (format, ##args); \
+ }
+
+typedef struct
+{
+ int n_iterations;
+
+ int n_iterations_per_print;
+
+ /* Number of pairs to insert into mhash. */
+ int n_pairs;
+
+ /* True to validate correctness of mhash functions. */
+ int n_iterations_per_validate;
+
+ /* Verbosity level for mhash formats. */
+ int verbose;
+
+ /* Random number seed. */
+ u32 seed;
+} mhash_test_t;
+
+static clib_error_t *
+mhash_next_test (mhash_t *h)
+{
+ hash_next_t hn = { 0 };
+ hash_pair_t *p0, *p1;
+ clib_error_t *error = 0;
+
+ hash_foreach_pair (p0, h->hash, {
+ p1 = hash_next (h->hash, &hn);
+ error = CLIB_ERROR_ASSERT (p0 == p1);
+ if (error)
+ break;
+ });
+
+ if (!error)
+ error = CLIB_ERROR_ASSERT (!hash_next (h->hash, &hn));
+
+ return error;
+}
+
+static clib_error_t *
+test_word_key (mhash_test_t *ht)
+{
+ mhash_t _h = { 0 }, *h = &_h;
+ word i, j;
+
+ word *keys = 0, *vals = 0;
+ uword *is_inserted = 0;
+
+ clib_error_t *error = 0;
+
+ vec_resize (keys, ht->n_pairs);
+ vec_resize (vals, vec_len (keys));
+
+ mhash_init (h, sizeof (vals[0]), sizeof (keys[0]));
+ /* borrow 0 elt to make index keys non-zero */
+ vec_validate (h->key_vector_or_heap, 0);
+
+ {
+ uword *unique = 0;
+ u32 k;
+
+ for (i = 0; i < vec_len (keys); i++)
+ {
+ do
+ {
+ k = random_u32 (&ht->seed) & 0xfffff;
+ }
+ while (clib_bitmap_get (unique, k));
+ unique = clib_bitmap_ori (unique, k);
+ keys[i] = k;
+ vals[i] = i;
+ }
+
+ clib_bitmap_free (unique);
+ }
+
+ for (i = 0; i < ht->n_iterations; i++)
+ {
+ u32 vi = random_u32 (&ht->seed) % vec_len (keys);
+
+ if (clib_bitmap_get (is_inserted, vi))
+ {
+ mhash_unset (h, &keys[vi], 0);
+ mhash_unset (h, &keys[vi], 0);
+ }
+ else
+ {
+ mhash_set (h, &keys[vi], vals[vi], 0);
+ mhash_set (h, &keys[vi], vals[vi], 0);
+ }
+
+ is_inserted = clib_bitmap_xori (is_inserted, vi);
+
+ if (ht->n_iterations_per_print > 0 &&
+ ((i + 1) % ht->n_iterations_per_print) == 0)
+ if_verbose ("iteration %d\n %U", i + 1, format_mhash, h, ht->verbose);
+
+ if (ht->n_iterations_per_validate == 0 ||
+ (i + 1) % ht->n_iterations_per_validate)
+ continue;
+
+ {
+ uword ki, *k, *v;
+
+ mhash_foreach (k, v, h, {
+ ki = v[0];
+ ASSERT (keys[ki] == k[0]);
+ });
+ }
+
+ if ((error = hash_validate (h->hash)))
+ goto done;
+
+ for (j = 0; j < vec_len (keys); j++)
+ {
+ uword *v;
+ v = mhash_get (h, &keys[j]);
+ if ((error = CLIB_ERROR_ASSERT (clib_bitmap_get (is_inserted, j) ==
+ (v != 0))))
+ goto done;
+ if (v)
+ {
+ if ((error = CLIB_ERROR_ASSERT (v[0] == vals[j])))
+ goto done;
+ }
+ }
+ }
+
+ if ((error = mhash_next_test (h)))
+ goto done;
+
+ if_verbose ("%U", format_mhash, h, ht->verbose);
+
+ for (i = 0; i < vec_len (keys); i++)
+ {
+ if (!clib_bitmap_get (is_inserted, i))
+ continue;
+
+ mhash_unset (h, &keys[i], 0);
+ mhash_unset (h, &keys[i], 0);
+ is_inserted = clib_bitmap_xori (is_inserted, i);
+
+ if (ht->n_iterations_per_validate == 0 ||
+ (i + 1) % ht->n_iterations_per_validate)
+ continue;
+
+ if ((error = hash_validate (h->hash)))
+ goto done;
+
+ for (j = 0; j < vec_len (keys); j++)
+ {
+ uword *v;
+ v = mhash_get (h, &keys[j]);
+ if ((error = CLIB_ERROR_ASSERT (clib_bitmap_get (is_inserted, j) ==
+ (v != 0))))
+ goto done;
+ if (v)
+ {
+ if ((error = CLIB_ERROR_ASSERT (v[0] == vals[j])))
+ goto done;
+ }
+ }
+ }
+
+done:
+ mhash_free (h);
+ vec_free (keys);
+ vec_free (vals);
+ clib_bitmap_free (is_inserted);
+
+ if (verbose)
+ fformat (stderr, "%U\n", format_clib_mem_usage, /* verbose */ 0);
+
+ return error;
+}
+
+static u8 *
+test2_format (u8 *s, va_list *args)
+{
+ void *CLIB_UNUSED (user_arg) = va_arg (*args, void *);
+ void *v = va_arg (*args, void *);
+ hash_pair_t *p = va_arg (*args, hash_pair_t *);
+ hash_t *h = hash_header (v);
+ mhash_t *mh = uword_to_pointer (h->user, mhash_t *);
+
+ return format (s, "0x%8U <- %U", format_hex_bytes, &p->value[0],
+ hash_value_bytes (h), format_mhash_key, mh, (u32) p->key);
+}
+
+static clib_error_t *
+test_string_key (mhash_test_t *ht, uword is_c_string)
+{
+ mhash_t _h = { 0 }, *h = &_h;
+ word i, j;
+
+ u8 **keys = 0;
+ word *vals = 0;
+ uword *is_inserted = 0;
+
+ clib_error_t *error = 0;
+
+ vec_resize (keys, ht->n_pairs);
+ vec_resize (vals, vec_len (keys));
+
+ if (is_c_string)
+ mhash_init_c_string (h, sizeof (vals[0]));
+ else
+ mhash_init_vec_string (h, sizeof (vals[0]));
+ hash_set_pair_format (h->hash, test2_format, 0);
+
+ for (i = 0; i < vec_len (keys); i++)
+ {
+ keys[i] = random_string (&ht->seed, 5 + (random_u32 (&ht->seed) & 0xf));
+ keys[i] = format (keys[i], "%x", i);
+ if (is_c_string)
+ vec_terminate_c_string (keys[i]);
+ vals[i] = random_u32 (&ht->seed);
+ }
+
+ for (i = 0; i < ht->n_iterations; i++)
+ {
+ u32 vi = random_u32 (&ht->seed) % vec_len (keys);
+
+ if (clib_bitmap_get (is_inserted, vi))
+ {
+ mhash_unset (h, keys[vi], 0);
+ mhash_unset (h, keys[vi], 0);
+ }
+ else
+ {
+ mhash_set (h, keys[vi], vals[vi], 0);
+ mhash_set (h, keys[vi], vals[vi], 0);
+ }
+
+ is_inserted = clib_bitmap_xori (is_inserted, vi);
+
+ if (ht->n_iterations_per_print > 0 &&
+ ((i + 1) % ht->n_iterations_per_print) == 0)
+ if_verbose ("iteration %d\n %U", i + 1, format_mhash, h, ht->verbose);
+
+ if (ht->n_iterations_per_validate == 0 ||
+ (i + 1) % ht->n_iterations_per_validate)
+ continue;
+
+ if ((error = hash_validate (h->hash)))
+ goto done;
+
+ for (j = 0; j < vec_len (keys); j++)
+ {
+ uword *v;
+ v = mhash_get (h, keys[j]);
+ if ((error = CLIB_ERROR_ASSERT (clib_bitmap_get (is_inserted, j) ==
+ (v != 0))))
+ goto done;
+ if (v)
+ {
+ if ((error = CLIB_ERROR_ASSERT (v[0] == vals[j])))
+ goto done;
+ }
+ }
+ }
+
+ if ((error = mhash_next_test (h)))
+ goto done;
+
+ if_verbose ("%U", format_mhash, h, ht->verbose);
+
+ for (i = 0; i < vec_len (keys); i++)
+ {
+ if (!clib_bitmap_get (is_inserted, i))
+ continue;
+
+ mhash_unset (h, keys[i], 0);
+ mhash_unset (h, keys[i], 0);
+ is_inserted = clib_bitmap_xori (is_inserted, i);
+
+ if (ht->n_iterations_per_validate == 0 ||
+ (i + 1) % ht->n_iterations_per_validate)
+ continue;
+
+ if ((error = hash_validate (h->hash)))
+ goto done;
+
+ for (j = 0; j < vec_len (keys); j++)
+ {
+ uword *v;
+ v = mhash_get (h, keys[j]);
+ if ((error = CLIB_ERROR_ASSERT (clib_bitmap_get (is_inserted, j) ==
+ (v != 0))))
+ goto done;
+ if (v)
+ {
+ if ((error = CLIB_ERROR_ASSERT (v[0] == vals[j])))
+ goto done;
+ }
+ }
+ }
+
+done:
+ mhash_free (h);
+ vec_free (vals);
+ clib_bitmap_free (is_inserted);
+
+ for (i = 0; i < vec_len (keys); i++)
+ vec_free (keys[i]);
+ vec_free (keys);
+
+ if (verbose)
+ fformat (stderr, "%U\n", format_clib_mem_usage, /* verbose */ 0);
+
+ return error;
+}
+
+int
+test_mhash_main (unformat_input_t *input)
+{
+ mhash_test_t _ht = { 0 }, *ht = &_ht;
+ clib_error_t *error;
+
+ ht->n_iterations = 100;
+ ht->n_pairs = 10;
+
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (0 == unformat (input, "iter %d", &ht->n_iterations) &&
+ 0 == unformat (input, "print %d", &ht->n_iterations_per_print) &&
+ 0 == unformat (input, "elts %d", &ht->n_pairs) &&
+ 0 == unformat (input, "seed %d", &ht->seed) &&
+ 0 == unformat (input, "verbose %=", &ht->verbose, 1) &&
+ 0 == unformat (input, "valid %d", &ht->n_iterations_per_validate))
+ {
+ clib_warning ("unknown input `%U'", format_unformat_error, input);
+ return 1;
+ }
+ }
+
+ if (!ht->seed)
+ ht->seed = random_default_seed ();
+
+ if_verbose ("testing %d iterations, seed %d", ht->n_iterations, ht->seed);
+
+ error = test_word_key (ht);
+ if (error)
+ clib_error_report (error);
+
+ error = test_string_key (ht, 0);
+ if (error)
+ clib_error_report (error);
+
+ error = test_string_key (ht, 1);
+ if (error)
+ clib_error_report (error);
+
+ return 0;
+}
+
+#ifdef CLIB_UNIX
+int
+main (int argc, char *argv[])
+{
+ unformat_input_t i;
+ int ret;
+
+ clib_mem_init (0, 3ULL << 30);
+
+ verbose = (argc > 1);
+ unformat_init_command_line (&i, argv);
+ ret = test_mhash_main (&i);
+ unformat_free (&i);
+
+ return ret;
+}
+#endif /* CLIB_UNIX */
diff --git a/src/vppinfra/unix-misc.c b/src/vppinfra/unix-misc.c
index 29cbe0a557d..31c0a489e8d 100644
--- a/src/vppinfra/unix-misc.c
+++ b/src/vppinfra/unix-misc.c
@@ -35,6 +35,10 @@
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
#include <vppinfra/error.h>
#include <vppinfra/os.h>
#include <vppinfra/bitmap.h>
@@ -42,13 +46,19 @@
#include <vppinfra/format.h>
#ifdef __linux__
#include <vppinfra/linux/sysfs.h>
-#else
+#include <sched.h>
+#elif defined(__FreeBSD__)
+#define _WANT_FREEBSD_BITSET
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/cpuset.h>
+#include <sys/domainset.h>
#include <sys/sysctl.h>
#endif
#include <sys/stat.h>
#include <sys/types.h>
-#include <sys/syscall.h>
#include <sys/uio.h> /* writev */
#include <fcntl.h>
#include <stdio.h> /* for sprintf */
@@ -290,7 +300,7 @@ os_get_cpu_affinity_bitmap (int pid)
__CPU_ZERO_S (sizeof (cpu_set_t), &cpuset);
- ret = syscall (SYS_sched_getaffinity, 0, sizeof (cpu_set_t), &cpuset);
+ ret = sched_getaffinity (0, sizeof (cpu_set_t), &cpuset);
if (ret < 0)
{
@@ -302,8 +312,23 @@ os_get_cpu_affinity_bitmap (int pid)
if (__CPU_ISSET_S (index, sizeof (cpu_set_t), &cpuset))
clib_bitmap_set (affinity_cpus, index, 1);
return affinity_cpus;
+#elif defined(__FreeBSD__)
+ cpuset_t mask;
+ uword *r = NULL;
+
+ if (cpuset_getaffinity (CPU_LEVEL_CPUSET, CPU_WHICH_CPUSET, -1,
+ sizeof (mask), &mask) != 0)
+ {
+ clib_bitmap_free (r);
+ return NULL;
+ }
+
+ for (int bit = 0; bit < CPU_SETSIZE; bit++)
+ clib_bitmap_set (r, bit, CPU_ISSET (bit, &mask));
+
+ return r;
#else
- return 0;
+ return NULL;
#endif
}
@@ -312,6 +337,21 @@ os_get_online_cpu_node_bitmap ()
{
#if __linux__
return clib_sysfs_read_bitmap ("/sys/devices/system/node/online");
+#elif defined(__FreeBSD__)
+ domainset_t domain;
+ uword *r = NULL;
+ int policy;
+
+ if (cpuset_getdomain (CPU_LEVEL_CPUSET, CPU_WHICH_CPUSET, -1,
+ sizeof (domain), &domain, &policy) != 0)
+ {
+ clib_bitmap_free (r);
+ return NULL;
+ }
+
+ for (int bit = 0; bit < CPU_SETSIZE; bit++)
+ clib_bitmap_set (r, bit, CPU_ISSET (bit, &domain));
+ return r;
#else
return 0;
#endif
diff --git a/src/vppinfra/unix.h b/src/vppinfra/unix.h
index abda21879f9..d0ddb93a46f 100644
--- a/src/vppinfra/unix.h
+++ b/src/vppinfra/unix.h
@@ -56,9 +56,6 @@ clib_error_t *unix_proc_file_contents (char *file, u8 ** result);
/* Retrieve bitmap of online cpu cures */
clib_bitmap_t *os_get_online_cpu_core_bitmap ();
-/* Retrieve bitmap of cpus vpp has affinity to */
-clib_bitmap_t *os_get_cpu_affinity_bitmap (int pid);
-
/* Retrieve bitmap of online cpu nodes (sockets) */
clib_bitmap_t *os_get_online_cpu_node_bitmap ();
diff --git a/test/Makefile b/test/Makefile
index 9b9cc178cf6..203a12e6e9b 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -354,12 +354,12 @@ cov-prep: test-dep
cov-post: wipe-cov $(BUILD_COV_DIR)
@lcov --capture \
--directory $(VPP_BUILD_DIR) \
- --output-file $(BUILD_COV_DIR)/coverage.info
+ --output-file $(BUILD_COV_DIR)/coverage$(HS_TEST).info
@test -z "$(EXTERN_COV_DIR)" || \
lcov --capture \
--directory $(EXTERN_COV_DIR) \
- --output-file $(BUILD_COV_DIR)/extern-coverage.info
- @lcov --remove $(BUILD_COV_DIR)/coverage.info \
+ --output-file $(BUILD_COV_DIR)/extern-coverage$(HS_TEST).info
+ @lcov --remove $(BUILD_COV_DIR)/coverage$(HS_TEST).info \
"/usr/include/*" "*/build-root/*" "/opt/*" "/usr/lib/*" \
"*_test.*" "*vat*" "*rdma*" "*/vpp-api/client/*" "*/plugins/af_packet/*" \
"*/plugins/af_xdp/*" "*/plugins/avf/*" "*/plugins/dma_intel/*" \
@@ -367,15 +367,17 @@ cov-post: wipe-cov $(BUILD_COV_DIR)
"*/plugins/perfmon/arm*" "*/plugins/perfmon/intel/*" "*/vlib/vmbus/*" \
"*/vnet/dev/*" "*/plugins/dev_ena/*" "*/plugins/builtinurl/*" "*/vnet/flow/*" \
"*/plugins/http_static/builtinurl/*" "*/plugins/dev_iavf/*" \
- -o $(BUILD_COV_DIR)/coverage-filtered.info
- @genhtml $(BUILD_COV_DIR)/coverage-filtered.info \
+ -o $(BUILD_COV_DIR)/coverage-filtered$(HS_TEST).info
+ @genhtml $(BUILD_COV_DIR)/coverage-filtered$(HS_TEST).info \
--output-directory $(BUILD_COV_DIR)/html
@test -z "$(EXTERN_COV_DIR)" || \
- genhtml $(BUILD_COV_DIR)/extern-coverage.info \
+ genhtml $(BUILD_COV_DIR)/extern-coverage$(HS_TEST).info \
--output-directory $(BUILD_COV_DIR)/extern-html
@echo
@echo "Build finished. Code coverage report is in $(BUILD_COV_DIR)/html/index.html"
@test -z "$(EXTERN_COV_DIR)" || echo "Code coverage report for out-of-tree objects is in $(BUILD_COV_DIR)/extern-html/index.html"
+ @mkdir -p $(BR)/test-coverage-merged
+ @cp -f $(BUILD_COV_DIR)/coverage-filtered$(HS_TEST).info $(BR)/test-coverage-merged
.PHONY: cov
cov:
@@ -434,6 +436,7 @@ help:
@echo " test-cov-prep - coverage phase #1 : prepare lcov"
@echo " test-cov-build - coverage phase #2 : build gcov image & run tests against it (use TEST=)"
@echo " test-cov-post - coverage phase #3 : generate lcov html report"
+ @echo " test-cov-both - generate and merge code coverage report for Python and Golang tests"
@echo " test-all - build and run functional and extended tests"
@echo " test-all-debug - build and run functional and extended tests (debug build)"
@echo " test-all-cov - generate code coverage report for functional and extended tests"
diff --git a/test/scripts/core_pinning.sh b/test/scripts/core_pinning.sh
deleted file mode 100755
index 941d53871e5..00000000000
--- a/test/scripts/core_pinning.sh
+++ /dev/null
@@ -1,328 +0,0 @@
-#!/bin/bash
-#
-# core_pinning_auto.sh -- script to test vpp (debug-build) core-pinning
-# -- in bare-metal, containers (docker, lxc)
-#
-DOCKER_CONTAINER_NAME="vpp_core_pinning"
-VPP_SOCK_PATH=/run/vpp
-CONTAINER_CPU_RANGE="4-7"
-TEST_SUCCESS=0
-TEST_FAIL=0
-if [ ! $WS_ROOT ]
-then
- if [ ! -d "../../../vpp" ]; then
- echo "VPP workspace path invalid"
- echo "Please execute script from vpp/test/scripts folder.."
- exit 1
- fi
- WS_ROOT="$(dirname $(readlink -e "../../../vpp"))/$(basename "../../../vpp")"
-fi
-# Get available CPU count on host machine
-host_cpulist=$(cat /sys/devices/system/cpu/online)
-startcpu="${host_cpulist%-*}"
-endcpu="${host_cpulist#*\-}"
-cpucount="$(($endcpu - $startcpu + 1))"
-if [ $cpucount -lt 8 ]
-then
- echo "Current host machine has $cpucount CPUs"
- echo "A minimum of 8 CPUs is required to run testcases, exiting.."
- exit 1
-fi
-# Check that container 'vpp_core_pinning' does not already exist
-count=$(docker ps -a | grep -c "$DOCKER_CONTAINER_NAME")
-if [ $count -ne 0 ]
-then
- echo "Error: docker container $DOCKER_CONTAINER_NAME already exists"
- echo "Remove it using 'docker stop/docker rm', then re-run test"
- exit 1
-fi
-# Check that there is no vpp instance currently running on the machine
-count=$(pgrep vpp | wc -l)
-if [ $count -ne 0 ]
-then
- echo "Error: a vpp instance is currently running on this machine"
- echo "Please stop the running instance, then re-run test"
- exit 1
-fi
-mkdir -p $VPP_SOCK_PATH
-
-# Function to parse main core
-parse_maincore () {
- main_core_args=$1
- main_core_parsed=$main_core_args
- if [ $main_core_args = "auto" ];
- then
- main_core_parsed="0"
- if [ -n "$SKIP_CORE" ]
- then
- main_core_parsed=$(($main_core_parsed + $SKIP_CORE))
- fi
- if [ -n "$CONTAINER_RESTRAIN_CPUSET" ]
- then
- main_core_parsed=(${container_cpus[ $main_core_parsed ]})
- fi
- fi
- echo $main_core_parsed
-}
-
-# Function to parse n workers range to an array
-# e.g. "4" is parsed to ('0','1','2','3')
-parse_workers_n () {
- workers_n_args=$1
- workers_n_parsed=()
- main_core_increment="0"
- skip_core_increment="0"
- if [ -n "$SKIP_CORE" ]
- then
- skip_core_increment=$(($SKIP_CORE))
- fi
-
- for ((i=0;i<$workers_n_args;i++)); do
-
- if [ -n "$CONTAINER_RESTRAIN_CPUSET" ]
- then
- if [ $(( ${container_cpus[ $(($i + $skip_core_increment)) ]})) -eq $(("$parsed_main_core")) ]
- then
- main_core_increment=$(($main_core_increment + 1))
- fi
- workers_n_parsed+=" ${container_cpus[ $(($i + $main_core_increment + $skip_core_increment)) ]}"
- else
- if [ $(( $skip_core_increment + $i)) -eq $(("$parsed_main_core")) ]
- then
- main_core_increment=$(($main_core_increment + 1))
- fi
- workers_n_parsed+=" $(($i + $main_core_increment + $skip_core_increment))"
- fi
- done
- echo $workers_n_parsed
-}
-
-# Function to parse corelist range to an array
-# e.g. "0,3-5,7" is parsed to ('0','3','4','5','7')
-parse_corelist () {
- corelist_args=$1
- corelist_args=$(echo $corelist_args | grep -Po '[0-9]+-[0-9]+|[0-9]+')
- corelist_parsed=()
- for corelist_elt in ${corelist_args[@]};do
- if [ $(echo $corelist_elt | grep -Po '[0-9]+-[0-9]+') ]
- then
- startcpu="${corelist_elt%-*}"
- endcpu="${corelist_elt#*\-}"
- cpucount="$(($endcpu - $startcpu))"
- for ((i=0;i<=$cpucount;i++)); do
- corelist_parsed+=" $(($i+$startcpu))"
- done
- elif [ $(echo $corelist_elt | grep -Po '[0-9]+') ]
- then
- corelist_parsed+=" ${corelist_elt}"
- fi
- done
- echo $corelist_parsed
-}
-# Test VPP core pinning configuration
-test_pinning_conf () {
- VPP_CPU_EXTRA_OPTIONS=""
- if [ -n "$CORELIST_WORKERS" ];
- then
- VPP_CPU_EXTRA_OPTIONS=" corelist-workers ${CORELIST_WORKERS}"
- fi
- if [ -n "$WORKERS_AUTO" ];
- then
- VPP_CPU_EXTRA_OPTIONS=" workers ${WORKERS_AUTO}"
- fi
- if [ -n "$SKIP_CORE" ];
- then
- VPP_CPU_EXTRA_OPTIONS="${VPP_CPU_EXTRA_OPTIONS} skip-cores ${SKIP_CORE}"
- fi
- echo "TEST - conf 'cpu {main-core ${MAIN_CORE} ${VPP_CPU_EXTRA_OPTIONS}}'"
- if [ -z "$CONTAINER_RESTRAIN_CPUSET" ];
- then
- VPP_CONTAINER_CPUSET=""
- echo "(Running vpp in container with full host cpuset $host_cpulist)"
- else
- VPP_CONTAINER_CPUSET="--cpuset-cpus $CONTAINER_CPU_RANGE"
- echo "(Running vpp in container with limited cpuset $CONTAINER_CPU_RANGE)"
- fi
- (docker run -d ${VPP_CONTAINER_CPUSET} --name="$DOCKER_CONTAINER_NAME" \
- -e LD_LIBRARY_PATH="/vpp/build-root/build-vpp_debug-native/vpp/lib/x86_64-linux-gnu/" -v $VPP_SOCK_PATH:$VPP_SOCK_PATH \
- -v $WS_ROOT:/vpp ubuntu:22.04 sh -c "/vpp/build-root/build-vpp_debug-native/vpp/bin/vpp unix {interactive \
- nodaemon cli-listen $VPP_SOCK_PATH/cli.sock} cpu {main-core ${MAIN_CORE} ${VPP_CPU_EXTRA_OPTIONS} } plugins \
- { plugin dpdk_plugin.so {disable } }" > /dev/null )
- sleep 3 # wait for VPP to initialize socket
- # Change access permissions on vpp cli socket
- # docker exec -it "$DOCKER_CONTAINER_NAME" /bin/bash -c "chmod 777 $VPP_SOCK_PATH/cli.sock" > /dev/null
- # check if vppctl can connect to vpp container instance
- $WS_ROOT/build-root/build-vpp_debug-native/vpp/bin/vppctl -s $VPP_SOCK_PATH/cli.sock show threads 1> /dev/null
- # get CPUs vpp instance in container is running on
- taskset_vpp_cpus=($( taskset --all-tasks -pc $(pgrep vpp) | grep -e ".$" -o))
- rc=$?
- # parse list of user requested CPUs for vpp
- requested_cpus=()
- parsed_main_core=$(parse_maincore ${MAIN_CORE})
- requested_cpus+=($parsed_main_core)
- if [ -n "$CORELIST_WORKERS" ];
- then
- requested_cpus+=($(parse_corelist ${CORELIST_WORKERS}))
- fi
- if [ -n "$WORKERS_AUTO" ];
- then
- requested_cpus+=($(parse_workers_n ${WORKERS_AUTO}))
- fi
-
- # parse list of expected CPUs used by vpp
- expected_cpu_mapping=()
- expected_cpu_mapping=("${requested_cpus[@]}")
- echo "CPUs requested by user: [${requested_cpus[@]}]"
- echo "--------------------"
- echo "Expected CPU Mapping: [${expected_cpu_mapping[@]}]"
- echo "VPP pinning (taskset): [${taskset_vpp_cpus[@]}]"
- #check if expected CPU mapping matches CPUs vpp instance in container is running on
- failure_cond=""
- for index in ${!taskset_vpp_cpus[@]}; do
- if [ ${taskset_vpp_cpus[$index]} -ne ${expected_cpu_mapping[ $index ]} ]
- then
- failure_cond="t"
- fi
- done
- if [ $rc -eq 0 ] && [ -z "$failure_cond" ]
- then
- echo "Test Successful"
- TEST_SUCCESS=$(($TEST_SUCCESS+1))
- else
- echo "Test Failed"
- TEST_FAIL=$(($TEST_FAIL+1))
- fi
- echo "=============================================="
- echo " "
- # Stop & destroy container instance
- docker stop $DOCKER_CONTAINER_NAME &> /dev/null
- docker rm -f $DOCKER_CONTAINER_NAME &> /dev/null
-}
-test_invalid_conf () {
- if [ -n "$CORELIST_WORKERS" ];
- then
- VPP_CPU_EXTRA_OPTIONS=" corelist-workers ${CORELIST_WORKERS}"
- fi
- if [ -n "$WORKERS_AUTO" ];
- then
- VPP_CPU_EXTRA_OPTIONS=" workers ${WORKERS_AUTO}"
- fi
- if [ -n "$SKIP_CORE" ];
- then
- VPP_CPU_EXTRA_OPTIONS="${VPP_CPU_EXTRA_OPTIONS} skip-cores ${SKIP_CORE}"
- fi
- echo "TEST - conf 'cpu {main-core ${MAIN_CORE} ${VPP_CPU_EXTRA_OPTIONS}}'"
- if [ -z "$CONTAINER_RESTRAIN_CPUSET" ];
- then
- VPP_CONTAINER_CPUSET=""
- echo "(Running vpp in container with full host cpuset $host_cpulist)"
- else
- VPP_CONTAINER_CPUSET="--cpuset-cpus $CONTAINER_CPU_RANGE"
- echo "(Running vpp in container with limited cpuset $CONTAINER_CPU_RANGE)"
- fi
- (docker run -d --cpuset-cpus $CONTAINER_CPU_RANGE --name="$DOCKER_CONTAINER_NAME" \
- -e LD_LIBRARY_PATH="/vpp/build-root/build-vpp_debug-native/vpp/lib/x86_64-linux-gnu/" -v $VPP_SOCK_PATH:$VPP_SOCK_PATH \
- -v $WS_ROOT:/vpp ubuntu:22.04 sh -c "/vpp/build-root/build-vpp_debug-native/vpp/bin/vpp unix {interactive \
- nodaemon cli-listen $VPP_SOCK_PATH/cli.sock} cpu {main-core ${MAIN_CORE} ${VPP_CPU_EXTRA_OPTIONS}} plugins \
- { plugin dpdk_plugin.so {disable } }" > /dev/null)
- sleep 3 # wait for vpp to initialize socket
- # check if vpp launched with invalid configuration
- taskset --all-tasks -pc $(pgrep vpp) &> /dev/null
- rc=$?
- if [ $rc -eq 1 ]
- then
- echo " "
- echo "OK... VPP did not launch with invalid configuration"
- TEST_SUCCESS=$(($TEST_SUCCESS+1))
- else
- echo " "
- echo "Failure... VPP launched with wrong configuration"
- TEST_FAIL=$(($TEST_FAIL+1))
- fi
- echo "=============================================="
- echo " "
- # Stop & destroy container instance
- docker stop $DOCKER_CONTAINER_NAME &> /dev/null
- docker rm -f $DOCKER_CONTAINER_NAME &> /dev/null
-}
-run_tests () {
- container_cpus=($(parse_corelist ${CONTAINER_CPU_RANGE}))
- echo "TESTING VALID CORE PINNING CONFIGURATIONS"
- echo " "
- WORKERS_AUTO=""
- SKIP_CORE=""
- CONTAINER_RESTRAIN_CPUSET=""
- CORELIST_WORKERS="1-3"
- MAIN_CORE="0"
- test_pinning_conf
- WORKERS_AUTO=""
- SKIP_CORE=""
- CONTAINER_RESTRAIN_CPUSET=""
- CORELIST_WORKERS="0,2-3"
- MAIN_CORE="1"
- test_pinning_conf
- WORKERS_AUTO=""
- SKIP_CORE=""
- CONTAINER_RESTRAIN_CPUSET=""
- CORELIST_WORKERS="0-2"
- MAIN_CORE="3"
- test_pinning_conf
- WORKERS_AUTO="2"
- SKIP_CORE=""
- CONTAINER_RESTRAIN_CPUSET=""
- CORELIST_WORKERS=""
- MAIN_CORE="auto"
- test_pinning_conf
- WORKERS_AUTO="3"
- SKIP_CORE=""
- CONTAINER_RESTRAIN_CPUSET="t"
- CORELIST_WORKERS=""
- MAIN_CORE="auto"
- test_pinning_conf
- WORKERS_AUTO="2"
- SKIP_CORE="1"
- CONTAINER_RESTRAIN_CPUSET="t"
- CORELIST_WORKERS=""
- MAIN_CORE="auto"
- test_pinning_conf
- WORKERS_AUTO="2"
- SKIP_CORE=""
- CONTAINER_RESTRAIN_CPUSET="t"
- CORELIST_WORKERS=""
- MAIN_CORE="5"
- test_pinning_conf
- echo "TESTING NON-VALID CORE PINNING CONFIGURATIONS"
- echo " "
- WORKERS_AUTO=""
- SKIP_CORE=""
- CONTAINER_RESTRAIN_CPUSET="t"
- CORELIST_WORKERS="1-3"
- MAIN_CORE="0"
- test_invalid_conf
- WORKERS_AUTO="3"
- SKIP_CORE="1"
- CONTAINER_RESTRAIN_CPUSET="t"
- CORELIST_WORKERS=""
- MAIN_CORE="auto"
- test_invalid_conf
- WORKERS_AUTO="5"
- SKIP_CORE=""
- CONTAINER_RESTRAIN_CPUSET="t"
- CORELIST_WORKERS=""
- MAIN_CORE="auto"
- test_invalid_conf
- WORKERS_AUTO=""
- SKIP_CORE="4"
- CONTAINER_RESTRAIN_CPUSET="t"
- CORELIST_WORKERS=""
- MAIN_CORE="auto"
- test_invalid_conf
- echo " "
- echo "========================"
- echo "RESULTS:"
- echo "SUCCESS: $TEST_SUCCESS"
- echo "FAILURE: $TEST_FAIL"
- echo "========================"
- echo " "
-}
-run_tests \ No newline at end of file
diff --git a/test/test_abf.py b/test/test_abf.py
index 3baec9f9e9b..ec329a0ec9b 100644
--- a/test/test_abf.py
+++ b/test/test_abf.py
@@ -391,7 +391,7 @@ class TestAbf(VppTestCase):
# a packet matching the deny rule
#
p_deny = (
- Ether(src=self.pg0.remote_mac, dst=self.pg3.remote_mac)
+ Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
/ IP(src=self.pg0.remote_ip4, dst=self.pg3.remote_ip4)
/ UDP(sport=1234, dport=1234)
/ Raw(b"\xa5" * 100)
@@ -402,7 +402,7 @@ class TestAbf(VppTestCase):
# a packet matching the permit rule
#
p_permit = (
- Ether(src=self.pg0.remote_mac, dst=self.pg2.remote_mac)
+ Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
/ IP(src=self.pg0.remote_ip4, dst=self.pg2.remote_ip4)
/ UDP(sport=1234, dport=1234)
/ Raw(b"\xa5" * 100)
@@ -454,7 +454,7 @@ class TestAbf(VppTestCase):
# a packet matching the deny rule
#
p_deny = (
- Ether(src=self.pg0.remote_mac, dst=self.pg3.remote_mac)
+ Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
/ IPv6(src=self.pg0.remote_ip6, dst=self.pg3.remote_ip6)
/ UDP(sport=1234, dport=1234)
/ Raw(b"\xa5" * 100)
@@ -465,7 +465,7 @@ class TestAbf(VppTestCase):
# a packet matching the permit rule
#
p_permit = (
- Ether(src=self.pg0.remote_mac, dst=self.pg2.remote_mac)
+ Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
/ IPv6(src=self.pg0.remote_ip6, dst=self.pg2.remote_ip6)
/ UDP(sport=1234, dport=1234)
/ Raw(b"\xa5" * 100)
diff --git a/test/test_flowprobe.py b/test/test_flowprobe.py
index ac0433abc00..8e3fecfd7b4 100644
--- a/test/test_flowprobe.py
+++ b/test/test_flowprobe.py
@@ -559,7 +559,7 @@ class Flowprobe(MethodHolder):
# make a tcp packet
self.pkts = [
(
- Ether(src=self.pg3.remote_mac, dst=self.pg4.local_mac)
+ Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac)
/ IP(src=self.pg3.remote_ip4, dst=self.pg4.remote_ip4)
/ TCP(sport=1234, dport=4321)
/ Raw(b"\xa5" * 50)
diff --git a/test/test_gso.py b/test/test_gso.py
index 1db83be50a8..3d9ce5fb4ee 100644
--- a/test/test_gso.py
+++ b/test/test_gso.py
@@ -405,7 +405,7 @@ class TestGSO(VppTestCase):
# IPv4/IPv4 - VXLAN
#
p45 = (
- Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79")
+ Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
/ IP(src=self.pg2.remote_ip4, dst="172.16.3.3", flags="DF")
/ TCP(sport=1234, dport=1234)
/ Raw(b"\xa5" * 65200)
@@ -424,7 +424,7 @@ class TestGSO(VppTestCase):
inner = rx[VXLAN].payload
self.assertEqual(rx[IP].len - 20 - 8 - 8, len(inner))
self.assertEqual(inner[Ether].src, self.pg2.remote_mac)
- self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79")
+ self.assertEqual(inner[Ether].dst, self.pg2.local_mac)
self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
self.assertEqual(inner[IP].dst, "172.16.3.3")
self.assert_ip_checksum_valid(inner)
@@ -438,7 +438,7 @@ class TestGSO(VppTestCase):
# IPv4/IPv6 - VXLAN
#
p65 = (
- Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79")
+ Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
/ IPv6(src=self.pg2.remote_ip6, dst="fd01:3::3")
/ TCP(sport=1234, dport=1234)
/ Raw(b"\xa5" * 65200)
@@ -457,7 +457,7 @@ class TestGSO(VppTestCase):
inner = rx[VXLAN].payload
self.assertEqual(rx[IP].len - 20 - 8 - 8, len(inner))
self.assertEqual(inner[Ether].src, self.pg2.remote_mac)
- self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79")
+ self.assertEqual(inner[Ether].dst, self.pg2.local_mac)
self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
self.assertEqual(inner[IPv6].dst, "fd01:3::3")
self.assert_tcp_checksum_valid(inner)
@@ -483,7 +483,7 @@ class TestGSO(VppTestCase):
# IPv6/IPv4 - VXLAN
#
p46 = (
- Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79")
+ Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
/ IP(src=self.pg2.remote_ip4, dst="172.16.3.3", flags="DF")
/ TCP(sport=1234, dport=1234)
/ Raw(b"\xa5" * 65200)
@@ -501,7 +501,7 @@ class TestGSO(VppTestCase):
inner = rx[VXLAN].payload
self.assertEqual(rx[IPv6].plen - 8 - 8, len(inner))
self.assertEqual(inner[Ether].src, self.pg2.remote_mac)
- self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79")
+ self.assertEqual(inner[Ether].dst, self.pg2.local_mac)
self.assertEqual(inner[IP].src, self.pg2.remote_ip4)
self.assertEqual(inner[IP].dst, "172.16.3.3")
self.assert_ip_checksum_valid(inner)
@@ -515,7 +515,7 @@ class TestGSO(VppTestCase):
# IPv6/IPv6 - VXLAN
#
p66 = (
- Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79")
+ Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
/ IPv6(src=self.pg2.remote_ip6, dst="fd01:3::3")
/ TCP(sport=1234, dport=1234)
/ Raw(b"\xa5" * 65200)
@@ -533,7 +533,7 @@ class TestGSO(VppTestCase):
inner = rx[VXLAN].payload
self.assertEqual(rx[IPv6].plen - 8 - 8, len(inner))
self.assertEqual(inner[Ether].src, self.pg2.remote_mac)
- self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79")
+ self.assertEqual(inner[Ether].dst, self.pg2.local_mac)
self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6)
self.assertEqual(inner[IPv6].dst, "fd01:3::3")
self.assert_tcp_checksum_valid(inner)
@@ -590,7 +590,7 @@ class TestGSO(VppTestCase):
# IPv4/IPv4 - IPIP
#
p47 = (
- Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79")
+ Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
/ IP(src=self.pg2.remote_ip4, dst="172.16.10.3", flags="DF")
/ TCP(sport=1234, dport=1234)
/ Raw(b"\xa5" * 65200)
@@ -633,7 +633,7 @@ class TestGSO(VppTestCase):
# IPv4/IPv6 - IPIP
#
p67 = (
- Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79")
+ Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
/ IPv6(src=self.pg2.remote_ip6, dst="fd01:10::3")
/ TCP(sport=1234, dport=1234)
/ Raw(b"\xa5" * 65200)
@@ -731,7 +731,7 @@ class TestGSO(VppTestCase):
# IPv6/IPv4 - IPIP
#
p48 = (
- Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79")
+ Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
/ IP(src=self.pg2.remote_ip4, dst="172.16.10.3", flags="DF")
/ TCP(sport=1234, dport=1234)
/ Raw(b"\xa5" * 65200)
@@ -774,7 +774,7 @@ class TestGSO(VppTestCase):
# IPv6/IPv6 - IPIP
#
p68 = (
- Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79")
+ Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
/ IPv6(src=self.pg2.remote_ip6, dst="fd01:10::3")
/ TCP(sport=1234, dport=1234)
/ Raw(b"\xa5" * 65200)
@@ -842,7 +842,7 @@ class TestGSO(VppTestCase):
self.ip4_via_gre4_tunnel.add_vpp_config()
pgre4 = (
- Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79")
+ Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
/ IP(src=self.pg2.remote_ip4, dst="172.16.10.3", flags="DF")
/ TCP(sport=1234, dport=1234)
/ Raw(b"\xa5" * 65200)
@@ -952,7 +952,7 @@ class TestGSO(VppTestCase):
# Create IPv6 packet
#
pgre6 = (
- Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79")
+ Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
/ IPv6(src=self.pg2.remote_ip6, dst="fd01:10::3")
/ TCP(sport=1234, dport=1234)
/ Raw(b"\xa5" * 65200)
@@ -1078,7 +1078,7 @@ class TestGSO(VppTestCase):
# IPv4/IPv4 - IPSEC
#
ipsec44 = (
- Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79")
+ Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
/ IP(src=self.pg2.remote_ip4, dst="172.16.10.3", flags="DF")
/ TCP(sport=1234, dport=1234)
/ Raw(b"\xa5" * 65200)
@@ -1116,7 +1116,7 @@ class TestGSO(VppTestCase):
# IPv4/IPv6 - IPSEC
#
ipsec46 = (
- Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79")
+ Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
/ IPv6(src=self.pg2.remote_ip6, dst="fd01:10::3")
/ TCP(sport=1234, dport=1234)
/ Raw(b"\xa5" * 65200)
@@ -1213,7 +1213,7 @@ class TestGSO(VppTestCase):
# IPv6/IPv4 - IPSEC
#
ipsec64 = (
- Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79")
+ Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
/ IP(src=self.pg2.remote_ip4, dst="172.16.10.3", flags="DF")
/ TCP(sport=1234, dport=1234)
/ Raw(b"\xa5" * 65200)
@@ -1252,7 +1252,7 @@ class TestGSO(VppTestCase):
# IPv6/IPv6 - IPSEC
#
ipsec66 = (
- Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79")
+ Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
/ IPv6(src=self.pg2.remote_ip6, dst="fd01:10::3")
/ TCP(sport=1234, dport=1234)
/ Raw(b"\xa5" * 65200)
diff --git a/test/test_gtpu.py b/test/test_gtpu.py
index fd97205ac63..5fe4f36ccb3 100644
--- a/test/test_gtpu.py
+++ b/test/test_gtpu.py
@@ -36,7 +36,7 @@ class TestGtpuUDP(VppTestCase):
def _check_udp_port_ip4(self, enabled=True):
pkt = (
- Ether(src=self.pg0.local_mac, dst=self.pg0.remote_mac)
+ Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
/ IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4)
/ UDP(sport=self.dport, dport=self.dport, chksum=0)
)
@@ -55,7 +55,7 @@ class TestGtpuUDP(VppTestCase):
def _check_udp_port_ip6(self, enabled=True):
pkt = (
- Ether(src=self.pg0.local_mac, dst=self.pg0.remote_mac)
+ Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
/ IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6)
/ UDP(sport=self.dport, dport=self.dport, chksum=0)
)
diff --git a/test/test_ip6.py b/test/test_ip6.py
index a1cd943570c..84b060aa7a3 100644
--- a/test/test_ip6.py
+++ b/test/test_ip6.py
@@ -3409,9 +3409,11 @@ class TestIP6LinkLocal(VppTestCase):
# Use the specific link-local API on pg1
#
VppIp6LinkLocalAddress(self, self.pg1, ll1).add_vpp_config()
+ p_echo_request_1.dst = self.pg1.local_mac
self.send_and_expect(self.pg1, [p_echo_request_1], self.pg1)
VppIp6LinkLocalAddress(self, self.pg1, ll3).add_vpp_config()
+ p_echo_request_3.dst = self.pg1.local_mac
self.send_and_expect(self.pg1, [p_echo_request_3], self.pg1)
def test_ip6_ll_p2p(self):
diff --git a/test/test_ip6_nd_mirror_proxy.py b/test/test_ip6_nd_mirror_proxy.py
index 65209925e87..10dc77e1a86 100644
--- a/test/test_ip6_nd_mirror_proxy.py
+++ b/test/test_ip6_nd_mirror_proxy.py
@@ -161,7 +161,7 @@ class TestNDPROXY(VppTestCase):
redirect.add_vpp_config()
echo_reply = (
- Ether(dst=self.pg0.remote_mac, src=self.pg0.local_mac)
+ Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
/ IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6)
/ ICMPv6EchoReply(seq=1, id=id)
)
diff --git a/test/test_ipip.py b/test/test_ipip.py
index 2817d5a17ba..9574c2c299c 100644
--- a/test/test_ipip.py
+++ b/test/test_ipip.py
@@ -677,7 +677,7 @@ class TestIPIP(VppTestCase):
/ Raw(b"0x44" * 100)
)
tx_e = [
- (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / inner)
+ (Ether(dst=self.pg2.local_mac, src=self.pg0.remote_mac) / inner)
for x in range(63)
]
@@ -1454,7 +1454,7 @@ class TestIPIPMPLS(VppTestCase):
# Tunnel Decap
#
p4 = (
- self.p_ether
+ Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
/ IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4)
/ MPLS(label=44, ttl=4)
/ IP(src="1.1.1.1", dst="2.2.2.2")
@@ -1468,7 +1468,7 @@ class TestIPIPMPLS(VppTestCase):
self.assertEqual(rx[IP].dst, "2.2.2.2")
p6 = (
- self.p_ether
+ Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
/ IPv6(src=self.pg1.remote_ip6, dst=self.pg1.local_ip6)
/ MPLS(label=66, ttl=4)
/ IPv6(src="1::1", dst="2::2")
diff --git a/test/test_l3xc.py b/test/test_l3xc.py
index 351c599051c..69267b35817 100644
--- a/test/test_l3xc.py
+++ b/test/test_l3xc.py
@@ -126,7 +126,7 @@ class TestL3xc(VppTestCase):
p_2 = []
for ii in range(NUM_PKTS):
p_2.append(
- Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
+ Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
/ IP(src="1.1.1.1", dst="1.1.1.2")
/ UDP(sport=1000 + ii, dport=1234)
/ Raw(b"\xa5" * 100)
diff --git a/test/test_linux_cp.py b/test/test_linux_cp.py
index a9ff242e215..95a9f1aca1f 100644
--- a/test/test_linux_cp.py
+++ b/test/test_linux_cp.py
@@ -126,7 +126,7 @@ class TestLinuxCP(VppTestCase):
for phy, host in zip(phys, hosts):
for j in range(N_HOSTS):
p = (
- Ether(src=phy.local_mac, dst=phy.remote_hosts[j].mac)
+ Ether(src=phy.local_mac, dst=host.local_mac)
/ IP(src=phy.local_ip4, dst=phy.remote_hosts[j].ip4)
/ UDP(sport=1234, dport=1234)
/ Raw()
diff --git a/test/test_map.py b/test/test_map.py
index 565f7da6491..c65c5df7cda 100644
--- a/test/test_map.py
+++ b/test/test_map.py
@@ -494,7 +494,7 @@ class TestMAP(VppTestCase):
#
# Send a v4 packet that will be encapped.
#
- p_ether = Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
+ p_ether = Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
p_ip4 = IP(src=self.pg0.remote_ip4, dst="192.168.1.1")
p_tcp = TCP(sport=20000, dport=30000, flags="S", options=[("MSS", 1455)])
p4 = p_ether / p_ip4 / p_tcp
diff --git a/test/test_map_br.py b/test/test_map_br.py
index 0de0e31520c..a2c00d8d8ea 100644
--- a/test/test_map_br.py
+++ b/test/test_map_br.py
@@ -280,7 +280,7 @@ class TestMAPBR(VppTestCase):
def test_map_t_echo_request_ip4_to_ip6(self):
"""MAP-T echo request IPv4 -> IPv6"""
- eth = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
+ eth = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
ip = IP(src=self.pg0.remote_ip4, dst=self.ipv4_map_address)
icmp = ICMP(type="echo-request", id=self.ipv6_udp_or_tcp_map_port)
payload = "H" * 10
@@ -306,7 +306,7 @@ class TestMAPBR(VppTestCase):
def test_map_t_echo_reply_ip4_to_ip6(self):
"""MAP-T echo reply IPv4 -> IPv6"""
- eth = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
+ eth = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
ip = IP(src=self.pg0.remote_ip4, dst=self.ipv4_map_address)
icmp = ICMP(type="echo-reply", id=self.ipv6_udp_or_tcp_map_port)
payload = "H" * 10
diff --git a/test/test_mpls.py b/test/test_mpls.py
index 9c07251a481..0e747ec7cd0 100644
--- a/test/test_mpls.py
+++ b/test/test_mpls.py
@@ -2018,7 +2018,7 @@ class TestMPLS(VppTestCase):
binding.add_vpp_config()
tx = (
- Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
+ Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
/ MPLS(label=44, ttl=64)
/ IP(src=self.pg0.remote_ip4, dst=self.pg0.remote_ip4)
/ UDP(sport=1234, dport=1234)
diff --git a/test/test_nat44_ed_output.py b/test/test_nat44_ed_output.py
index ad1c5611418..dbf1dc40a75 100644
--- a/test/test_nat44_ed_output.py
+++ b/test/test_nat44_ed_output.py
@@ -216,7 +216,7 @@ class TestNAT44EDOutput(VppTestCase):
# send FIN+ACK packet in->out - will cause session to be wiped
# but won't create a new session
p = (
- Ether(src=pg0.remote_mac, dst=pg0.local_mac)
+ Ether(src=pg1.remote_mac, dst=pg1.local_mac)
/ IP(src=local_host, dst=remote_host)
/ TCP(sport=local_sport, dport=remote_dport, flags="FA", seq=300, ack=101)
)
diff --git a/test/test_neighbor.py b/test/test_neighbor.py
index 6fcf13f8261..d11d4abac14 100644
--- a/test/test_neighbor.py
+++ b/test/test_neighbor.py
@@ -2176,6 +2176,7 @@ class ARPTestCase(VppTestCase):
table_id=1,
).add_vpp_config()
+ p2.dst = self.pg3.local_mac
rxs = self.send_and_expect(self.pg3, [p2], self.pg1)
for rx in rxs:
self.verify_arp_req(rx, self.pg1.local_mac, "10.0.1.2", "10.0.1.128")
diff --git a/test/test_pcap.py b/test/test_pcap.py
index ae3a298f76a..72d215cea06 100644
--- a/test/test_pcap.py
+++ b/test/test_pcap.py
@@ -135,7 +135,7 @@ class TestPcap(VppTestCase):
self.vapi.cli("classify filter pcap del mask l3 ip4 src")
pkt = (
- Ether(src=self.pg0.local_mac, dst=self.pg0.remote_mac)
+ Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
# wrong destination address
/ IP(src=self.pg0.local_ip4, dst=self.pg0.local_ip4, ttl=2)
/ UDP(sport=1234, dport=2345)
diff --git a/test/test_reassembly.py b/test/test_reassembly.py
index 6b6745f221c..98c50f9bb61 100644
--- a/test/test_reassembly.py
+++ b/test/test_reassembly.py
@@ -1647,7 +1647,7 @@ class TestIPv6Reassembly(VppTestCase):
def test_atomic_fragment(self):
"""IPv6 atomic fragment"""
pkt = (
- Ether(src=self.pg0.local_mac, dst=self.pg0.remote_mac)
+ Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
/ IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6, nh=44, plen=65535)
/ IPv6ExtHdrFragment(
offset=8191, m=1, res1=0xFF, res2=0xFF, nh=255, id=0xFFFF
@@ -1669,7 +1669,7 @@ class TestIPv6Reassembly(VppTestCase):
self.send_and_assert_no_replies(self.pg0, [pkt])
pkt = (
- Ether(src=self.pg0.local_mac, dst=self.pg0.remote_mac)
+ Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
/ IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6)
/ ICMPv6EchoRequest()
)
@@ -1678,7 +1678,7 @@ class TestIPv6Reassembly(VppTestCase):
def test_one_fragment(self):
"""whole packet in one fragment processed independently"""
pkt = (
- Ether(src=self.pg0.local_mac, dst=self.pg0.remote_mac)
+ Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
/ IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6)
/ ICMPv6EchoRequest()
/ Raw("X" * 1600)
@@ -1690,7 +1690,7 @@ class TestIPv6Reassembly(VppTestCase):
# send an atomic fragment with same id - should be reassembled
pkt = (
- Ether(src=self.pg0.local_mac, dst=self.pg0.remote_mac)
+ Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
/ IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6)
/ IPv6ExtHdrFragment(id=1)
/ ICMPv6EchoRequest()
@@ -1705,7 +1705,7 @@ class TestIPv6Reassembly(VppTestCase):
def test_bunch_of_fragments(self):
"""valid fragments followed by rogue fragments and atomic fragment"""
pkt = (
- Ether(src=self.pg0.local_mac, dst=self.pg0.remote_mac)
+ Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
/ IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6)
/ ICMPv6EchoRequest()
/ Raw("X" * 1600)
@@ -1723,7 +1723,7 @@ class TestIPv6Reassembly(VppTestCase):
self.send_and_assert_no_replies(self.pg0, inc_frag * 604)
pkt = (
- Ether(src=self.pg0.local_mac, dst=self.pg0.remote_mac)
+ Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
/ IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6)
/ IPv6ExtHdrFragment(id=1)
/ ICMPv6EchoRequest()
@@ -1738,7 +1738,7 @@ class TestIPv6Reassembly(VppTestCase):
)
self.vapi.ip_local_reass_enable_disable(enable_ip6=True)
pkt = (
- Ether(src=self.src_if.local_mac, dst=self.src_if.remote_mac)
+ Ether(src=self.src_if.remote_mac, dst=self.src_if.local_mac)
/ IPv6(src=self.src_if.remote_ip6, dst=self.src_if.local_ip6)
/ ICMPv6EchoRequest(id=1234)
/ Raw("X" * 1600)
@@ -2184,7 +2184,7 @@ class TestIPv6SVReassembly(VppTestCase):
def test_one_fragment(self):
"""whole packet in one fragment processed independently"""
pkt = (
- Ether(src=self.src_if.local_mac, dst=self.src_if.remote_mac)
+ Ether(src=self.src_if.remote_mac, dst=self.src_if.local_mac)
/ IPv6(src=self.src_if.remote_ip6, dst=self.dst_if.remote_ip6)
/ ICMPv6EchoRequest()
/ Raw("X" * 1600)
@@ -2196,7 +2196,7 @@ class TestIPv6SVReassembly(VppTestCase):
# send an atomic fragment with same id - should be reassembled
pkt = (
- Ether(src=self.src_if.local_mac, dst=self.src_if.remote_mac)
+ Ether(src=self.src_if.remote_mac, dst=self.src_if.local_mac)
/ IPv6(src=self.src_if.remote_ip6, dst=self.dst_if.remote_ip6)
/ IPv6ExtHdrFragment(id=1)
/ ICMPv6EchoRequest()
@@ -2209,7 +2209,7 @@ class TestIPv6SVReassembly(VppTestCase):
def test_bunch_of_fragments(self):
"""valid fragments followed by rogue fragments and atomic fragment"""
pkt = (
- Ether(src=self.src_if.local_mac, dst=self.src_if.remote_mac)
+ Ether(src=self.src_if.remote_mac, dst=self.src_if.local_mac)
/ IPv6(src=self.src_if.remote_ip6, dst=self.dst_if.remote_ip6)
/ ICMPv6EchoRequest()
/ Raw("X" * 1600)
@@ -2218,7 +2218,7 @@ class TestIPv6SVReassembly(VppTestCase):
rx = self.send_and_expect(self.src_if, frags, self.dst_if)
rogue = (
- Ether(src=self.src_if.local_mac, dst=self.src_if.remote_mac)
+ Ether(src=self.src_if.remote_mac, dst=self.src_if.local_mac)
/ IPv6(src=self.src_if.remote_ip6, dst=self.dst_if.remote_ip6)
/ IPv6ExtHdrFragment(id=1, nh=58, offset=608)
/ Raw("X" * 308)
@@ -2227,7 +2227,7 @@ class TestIPv6SVReassembly(VppTestCase):
self.send_and_expect(self.src_if, rogue * 604, self.dst_if)
pkt = (
- Ether(src=self.src_if.local_mac, dst=self.src_if.remote_mac)
+ Ether(src=self.src_if.remote_mac, dst=self.src_if.local_mac)
/ IPv6(src=self.src_if.remote_ip6, dst=self.dst_if.remote_ip6)
/ IPv6ExtHdrFragment(id=1)
/ ICMPv6EchoRequest()
diff --git a/test/test_srv6_mobile.py b/test/test_srv6_mobile.py
index 9d39f194015..314dfc114e2 100644
--- a/test/test_srv6_mobile.py
+++ b/test/test_srv6_mobile.py
@@ -60,7 +60,7 @@ class TestSRv6EndMGTP4E(VppTestCase):
pkts = list()
for d, s in inner:
pkt = (
- Ether()
+ Ether(dst=self.pg0.local_mac)
/ IPv6(dst=str(ip6_dst), src=str(ip6_src))
/ IPv6ExtHdrSegmentRouting()
/ IPv6(dst=d, src=s)
@@ -149,7 +149,7 @@ class TestSRv6TMGTP4D(VppTestCase):
pkts = list()
for d, s in inner:
pkt = (
- Ether()
+ Ether(dst=self.pg0.local_mac)
/ IP(dst=str(ip4_dst), src=str(ip4_src))
/ UDP(sport=2152, dport=2152)
/ GTP_U_Header(gtp_type="g_pdu", teid=200)
@@ -254,7 +254,7 @@ class TestSRv6EndMGTP6E(VppTestCase):
pkts = list()
for d, s in inner:
pkt = (
- Ether()
+ Ether(dst=self.pg0.local_mac)
/ IPv6(dst=str(ip6_dst), src=str(ip6_src))
/ IPv6ExtHdrSegmentRouting(
segleft=1, lastentry=0, tag=0, addresses=["a1::1"]
@@ -344,7 +344,7 @@ class TestSRv6EndMGTP6D(VppTestCase):
pkts = list()
for d, s in inner:
pkt = (
- Ether()
+ Ether(dst=self.pg0.local_mac)
/ IPv6(dst=str(ip6_dst), src=str(ip6_src))
/ UDP(sport=2152, dport=2152)
/ GTP_U_Header(gtp_type="g_pdu", teid=200)
diff --git a/test/test_trace_filter.py b/test/test_trace_filter.py
index 58494cd7ad9..c188631c200 100644
--- a/test/test_trace_filter.py
+++ b/test/test_trace_filter.py
@@ -386,7 +386,7 @@ class TestTraceFilterInner(TemplateTraceFilter):
def __gen_encrypt_pkt(self, scapy_sa, pkt):
return Ether(
- src=self.pg0.local_mac, dst=self.pg0.remote_mac
+ src=self.pg0.remote_mac, dst=self.pg0.local_mac
) / scapy_sa.encrypt(pkt)
def test_encrypted_encap(self):
diff --git a/test/test_vxlan.py b/test/test_vxlan.py
index 6128d1070d3..284e1359116 100644
--- a/test/test_vxlan.py
+++ b/test/test_vxlan.py
@@ -580,6 +580,7 @@ class TestVxlanL2Mode(VppTestCase):
# Send packets
NUM_PKTS = 128
+ p.dst = self.pg1.local_mac
rx = self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0)
self.assertEqual(NUM_PKTS, len(rx))