diff options
Diffstat (limited to 'build/external')
14 files changed, 1233 insertions, 0 deletions
diff --git a/build/external/Makefile b/build/external/Makefile new file mode 100644 index 00000000000..201cf122fda --- /dev/null +++ b/build/external/Makefile @@ -0,0 +1,488 @@ +# 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. + +# Scripts require non-POSIX parts of bash +SHELL := /bin/bash + +DPDK_BUILD_DIR ?= $(CURDIR)/_build +DPDK_INSTALL_DIR ?= $(CURDIR)/_install +DPDK_PKTMBUF_HEADROOM ?= 128 +DPDK_CACHE_LINE_SIZE ?= 64 +DPDK_DOWNLOAD_DIR ?= $(HOME)/Downloads +DPDK_DEBUG ?= n +DPDK_MLX4_PMD ?= n +DPDK_MLX5_PMD ?= n +DPDK_TAP_PMD ?= n +DPDK_FAILSAFE_PMD ?= n + +B := $(DPDK_BUILD_DIR) +I := $(DPDK_INSTALL_DIR) +DPDK_VERSION ?= 18.08 +PKG_VERSION ?= $(shell git describe --abbrev=0 | cut -d- -f1 | cut -dv -f2) +PKG_SUFFIX ?= $(shell git log --oneline $$(git describe --abbrev=0).. . | wc -l) +DPDK_BASE_URL ?= http://fast.dpdk.org/rel +DPDK_TARBALL := dpdk-$(DPDK_VERSION).tar.xz +DPDK_TAR_URL := $(DPDK_BASE_URL)/$(DPDK_TARBALL) +DPDK_18.05_TARBALL_MD5_CKSUM := 9fc86367cd9407ff6a8dfea56c4eddc4 +DPDK_18.08_TARBALL_MD5_CKSUM := da5e7fb25ab063c47e53929fb8c58be5 +MACHINE=$(shell uname -m) + +# replace dot with space, and if 3rd word exists we deal with stable dpdk rel +ifeq ($(word 3,$(subst ., ,$(DPDK_VERSION))),) +DPDK_SOURCE := $(B)/dpdk-$(DPDK_VERSION) +else +DPDK_SOURCE := $(B)/dpdk-stable-$(DPDK_VERSION) +endif + +NASM_BASE_URL := http://www.nasm.us/pub/nasm/releasebuilds +NASM_VER := 2.13.03 +NASM_TARBALL := nasm-$(NASM_VER).tar.xz +NASM_TAR_URL := $(NASM_BASE_URL)/$(NASM_VER)/$(NASM_TARBALL) +NASM_SOURCE := $(B)/nasm-$(NASM_VER) + +ifneq (,$(findstring 18.02,$(DPDK_VERSION))) +IPSEC_MB_VER ?= 0.48 +else +IPSEC_MB_VER ?= 0.49 +endif + +ifeq ($(MACHINE),$(filter $(MACHINE),x86_64)) + AESNI ?= y +$(info Building IPSec-MB $(IPSEC_MB_VER) library) +else + AESNI ?= N +endif + +AESNIMB_LIB_TARBALL := v$(IPSEC_MB_VER).tar.gz +AESNIMB_LIB_TARBALL_URL := http://github.com/01org/intel-ipsec-mb/archive/$(AESNIMB_LIB_TARBALL) +AESNIMB_LIB_SOURCE := $(B)/intel-ipsec-mb-$(IPSEC_MB_VER) + +ifneq (,$(findstring clang,$(CC))) +DPDK_CC=clang +else ifneq (,$(findstring icc,$(CC))) +DPDK_CC=icc +else +DPDK_CC=gcc +endif + +############################################################################## +# Intel x86 +############################################################################## +ifeq ($(MACHINE),$(filter $(MACHINE),x86_64 i686)) +DPDK_TARGET ?= $(MACHINE)-native-linuxapp-$(DPDK_CC) +DPDK_MACHINE ?= nhm +DPDK_TUNE ?= core-avx2 + +############################################################################## +# ARM64 +############################################################################## +else ifeq ($(MACHINE),aarch64) +CROSS := +export CROSS +DPDK_TARGET ?= arm64-armv8a-linuxapp-$(DPDK_CC) +DPDK_MACHINE ?= armv8a +DPDK_TUNE ?= generic + +CPU_IMP_ARM = 0x41 +CPU_IMP_CAVIUM = 0x43 + +CPU_PART_ARM_CORTEX_A53 = 0xd03 +CPU_PART_ARM_CORTEX_A57 = 0xd07 +CPU_PART_ARM_CORTEX_A72 = 0xd08 +CPU_PART_ARM_CORTEX_A73 = 0xd09 + +CPU_PART_CAVIUM_THUNDERX = 0x0a1 +CPU_PART_CAVIUM_THUNDERX_81XX = 0x0a2 +CPU_PART_CAVIUM_THUNDERX_83XX = 0x0a3 + +MIDR_IMPLEMENTER=$(shell awk '/implementer/ {print $$4;exit}' /proc/cpuinfo) +MIDR_PARTNUM=$(shell awk '/part/ {print $$4;exit}' /proc/cpuinfo) + +ifeq ($(MIDR_IMPLEMENTER),$(CPU_IMP_ARM)) +############################################################################## +# Arm Cortex +############################################################################## +CPU_PART_ARM_TUNE := $(CPU_PART_ARM_CORTEX_A53)/cortex-a53 \ + $(CPU_PART_ARM_CORTEX_A57)/cortex-a57 \ + $(CPU_PART_ARM_CORTEX_A72)/cortex-a72 \ + $(CPU_PART_ARM_CORTEX_A73)/cortex-a73 +CPU_TUNE = $(notdir $(filter $(MIDR_PARTNUM)/%,$(CPU_PART_ARM_TUNE))) +ifneq ($(CPU_TUNE),) +DPDK_TUNE = $(CPU_TUNE) +else +$(warning Unknown Arm CPU) +endif + +else ifeq ($(MIDR_IMPLEMENTER),$(CPU_IMP_CAVIUM)) +############################################################################## +# Cavium ThunderX +############################################################################## +ifneq (,$(findstring $(MIDR_PARTNUM),$(CPU_PART_CAVIUM_THUNDERX) \ + $(CPU_PART_CAVIUM_THUNDERX_81XX) $(CPU_PART_CAVIUM_THUNDERX_83XX))) +DPDK_TARGET = arm64-thunderx-linuxapp-$(DPDK_CC) +DPDK_MACHINE = thunderx +DPDK_CACHE_LINE_SIZE := 128 +else +$(warning Unknown Cavium CPU) +endif +endif + +############################################################################## +# Unknown platform +############################################################################## +else +$(error Unknown platform) +endif + +# /proc/cpuinfo does not exist on platforms without a /proc and on some +# platforms, notably inside containers, it has no content. In those cases +# we assume there's 1 processor; we use 2*ncpu for the -j option. +# NB: GNU Make 4.2 will let us use '$(file </proc/cpuinfo)' to both test +# for file presence and content; for now this will have to do. +JOBS := $(if $(shell [ -f /proc/cpuinfo ] && head /proc/cpuinfo),\ + $(shell grep -c ^processor /proc/cpuinfo), 2) + +# compiler/linker custom arguments +ifeq ($(DPDK_CC),clang) +DPDK_CPU_CFLAGS := -fPIE -fPIC +else +DPDK_CPU_CFLAGS := -pie -fPIC +endif + +ifeq ($(DPDK_DEBUG),n) +DPDK_EXTRA_CFLAGS := -g -mtune=$(DPDK_TUNE) +else +DPDK_EXTRA_CFLAGS := -g -O0 +endif + +# -Wimplicit-fallthrough was introduced starting from GCC 7, +# and it requires newer version of ccache. +# Disable fallthrough warning for old ccache version. +ifeq ($(DPDK_CC),gcc) +GCC_VER_V = "7.0.0" +CCACHE_VER_V = "3.4.1" +GCC_VER = $(shell gcc --version | grep ^gcc | sed 's/^.* //g') +CCACHE_VER = $(shell ccache --version | grep ^ccache | sed 's/^.* //g') +ifeq ($(shell expr "$(GCC_VER)" ">=" "$(GCC_VER_V)"),1) +ifeq ($(shell expr "$(CCACHE_VER)" "<" "$(CCACHE_VER_V)"),1) +DPDK_EXTRA_CFLAGS += -Wimplicit-fallthrough=0 +endif +endif +endif + +ifeq ($(AESNI),y) +IPSEC_MB_BUILD_PATH := $(B)/intel-ipsec-mb-$(IPSEC_MB_VER) +DPDK_EXTRA_CFLAGS += -L$(IPSEC_MB_BUILD_PATH) -I$(IPSEC_MB_BUILD_PATH) +endif + +DPDK_MAKE_EXTRA_ARGS += AESNI_MULTI_BUFFER_LIB_PATH=$(AESNIMB_LIB_SOURCE) + +# assemble DPDK make arguments +DPDK_MAKE_ARGS := -C $(DPDK_SOURCE) -j $(JOBS) \ + T=$(DPDK_TARGET) \ + RTE_CONFIG_TEMPLATE=../custom-config \ + EXTRA_CFLAGS="$(DPDK_EXTRA_CFLAGS)" \ + EXTRA_LDFLAGS="$(DPDK_EXTRA_LDFLAGS)" \ + CPU_CFLAGS="$(DPDK_CPU_CFLAGS)" \ + DESTDIR=$(I) \ + $(DPDK_MAKE_EXTRA_ARGS) + +define set +@if grep -q CONFIG_$1 $@ ; \ + then sed -i -e 's/.*\(CONFIG_$1=\).*/\1$2/' $@ ; \ + else echo CONFIG_$1=$2 >> $@ ; \ +fi +endef + +all: build + +$(B)/custom-config: $(B)/.patch.ok Makefile + @echo --- generating custom config from $(DPDK_SOURCE)/config/defconfig_$(DPDK_TARGET) --- + @cpp -undef -ffreestanding -x assembler-with-cpp $(DPDK_SOURCE)/config/defconfig_$(DPDK_TARGET) $@ + $(call set,RTE_MACHINE,$(DPDK_MACHINE)) + @# modify options + $(call set,RTE_MAX_LCORE,256) + $(call set,RTE_PKTMBUF_HEADROOM,$(DPDK_PKTMBUF_HEADROOM)) + $(call set,RTE_CACHE_LINE_SIZE,$(DPDK_CACHE_LINE_SIZE)) + $(call set,RTE_LIBEAL_USE_HPET,y) + $(call set,RTE_BUILD_COMBINE_LIBS,y) + $(call set,RTE_PCI_CONFIG,y) + $(call set,RTE_PCI_EXTENDED_TAG,"on") + $(call set,RTE_PCI_MAX_READ_REQUEST_SIZE,4096) + @# enable debug init for device drivers + $(call set,RTE_LIBRTE_I40E_DEBUG_INIT,$(DPDK_DEBUG)) + $(call set,RTE_LIBRTE_IXGBE_DEBUG_INIT,$(DPDK_DEBUG)) + $(call set,RTE_LIBRTE_E1000_DEBUG_INIT,$(DPDK_DEBUG)) + $(call set,RTE_LIBRTE_VIRTIO_DEBUG_INIT,$(DPDK_DEBUG)) + $(call set,RTE_LIBRTE_VMXNET3_DEBUG_INIT,$(DPDK_DEBUG)) + $(call set,RTE_LIBRTE_PMD_BOND,y) + $(call set,RTE_LIBRTE_IP_FRAG,y) + $(call set,RTE_LIBRTE_PMD_QAT,y) + $(call set,RTE_LIBRTE_PMD_AESNI_MB,$(AESNI)) + $(call set,RTE_LIBRTE_PMD_AESNI_GCM,$(AESNI)) + $(call set,RTE_LIBRTE_MLX4_PMD,$(DPDK_MLX4_PMD)) + $(call set,RTE_LIBRTE_MLX5_PMD,$(DPDK_MLX5_PMD)) + $(call set,RTE_LIBRTE_PMD_SOFTNIC,n) + $(call set,RTE_LIBRTE_MLX4_DLOPEN_DEPS,$(DPDK_MLX4_PMD)) + $(call set,RTE_LIBRTE_MLX5_DLOPEN_DEPS,$(DPDK_MLX5_PMD)) + $(call set,RTE_LIBRTE_PMD_TAP,$(DPDK_TAP_PMD)) + $(call set,RTE_LIBRTE_PMD_FAILSAFE,$(DPDK_FAILSAFE_PMD)) + @# not needed + $(call set,RTE_LIBRTE_CFGFILE,n) + $(call set,RTE_LIBRTE_LPM,n) + $(call set,RTE_LIBRTE_ACL,n) + $(call set,RTE_LIBRTE_POWER,n) + $(call set,RTE_LIBRTE_DISTRIBUTOR,n) + $(call set,RTE_LIBRTE_PORT,n) + $(call set,RTE_LIBRTE_TABLE,n) + $(call set,RTE_LIBRTE_PIPELINE,n) + $(call set,RTE_LIBRTE_FLOW_CLASSIFY,n) + $(call set,RTE_KNI_KMOD,n) + $(call set,RTE_EAL_IGB_UIO,n) + @# currently broken in 18.02 + $(call set,RTE_LIBRTE_DPAA_BUS,n) + $(call set,RTE_LIBRTE_DPAA_MEMPOOL,n) + $(call set,RTE_LIBRTE_DPAA_PMD,n) + $(call set,RTE_LIBRTE_PMD_DPAA_SEC,n) + $(call set,RTE_LIBRTE_PMD_DPAA_EVENTDEV,n) + @rm -f .config.ok + +$(CURDIR)/$(DPDK_TARBALL): + @if [ -e $(DPDK_DOWNLOAD_DIR)/$(DPDK_TARBALL) ] ; \ + then cp $(DPDK_DOWNLOAD_DIR)/$(DPDK_TARBALL) $(CURDIR) ; \ + else curl -o $(CURDIR)/$(DPDK_TARBALL) -LO $(DPDK_TAR_URL) ; \ + fi + @rm -f $(B)/.download.ok + +$(CURDIR)/$(NASM_TARBALL): + @if [ -e $(DPDK_DOWNLOAD_DIR)/$(NASM_TARBALL) ] ; \ + then cp $(DPDK_DOWNLOAD_DIR)/$(NASM_TARBALL) $(CURDIR) ; \ + else curl -o $(CURDIR)/$(NASM_TARBALL) -LO $(NASM_TAR_URL) ; \ + fi + +$(CURDIR)/$(AESNIMB_LIB_TARBALL): + @if [ -e $(DPDK_DOWNLOAD_DIR)/$(AESNIMB_LIB_TARBALL) ] ; \ + then cp $(DPDK_DOWNLOAD_DIR)/$(AESNIMB_LIB_TARBALL) $(CURDIR) ; \ + else curl -o $@ -LO $(AESNIMB_LIB_TARBALL_URL) ; \ + fi + +DPDK_DOWNLOADS = $(CURDIR)/$(DPDK_TARBALL) +ifeq ($(AESNI),y) +DPDK_DOWNLOADS += $(CURDIR)/$(NASM_TARBALL) +DPDK_DOWNLOADS += $(CURDIR)/$(AESNIMB_LIB_TARBALL) +endif + +$(B)/.download.ok: $(DPDK_DOWNLOADS) + @mkdir -p $(B) + @openssl md5 $< | cut -f 2 -d " " - > $(B)/$(DPDK_TARBALL).md5sum + @([ "$$(<$(B)/$(DPDK_TARBALL).md5sum)" = "$(DPDK_$(DPDK_VERSION)_TARBALL_MD5_CKSUM)" ] || \ + ( echo "Bad Checksum! Please remove $< and retry" && \ + rm $(B)/$(DPDK_TARBALL).md5sum && false )) + @touch $@ + +.PHONY: download +download: $(B)/.download.ok + +$(B)/.extract.ok: $(B)/.download.ok + @echo --- extracting $(DPDK_TARBALL) --- + @tar --directory $(B) --extract --file $(CURDIR)/$(DPDK_TARBALL) +ifeq ($(AESNI),y) + @echo --- extracting $(NASM_TARBALL) --- + @tar --directory $(B) --extract --file $(CURDIR)/$(NASM_TARBALL) + @echo --- extracting $(AESNIMB_LIB_TARBALL) --- + @tar --directory $(B) --extract --file $(CURDIR)/$(AESNIMB_LIB_TARBALL) +endif + @touch $@ + +.PHONY: extract +extract: $(B)/.extract.ok + +$(B)/.patch.ok: $(B)/.extract.ok +ifneq ($(wildcard $(CURDIR)/dpdk-$(DPDK_VERSION)_patches/*.patch),) + @echo --- patching --- + @for f in $(CURDIR)/dpdk-$(DPDK_VERSION)_patches/*.patch ; do \ + echo Applying patch: $$(basename $$f) ; \ + patch -p1 -d $(DPDK_SOURCE) < $$f ; \ + done +endif + @touch $@ + +.PHONY: patch +patch: $(B)/.patch.ok + +$(B)/.config.ok: $(B)/.patch.ok $(B)/custom-config + @make $(DPDK_MAKE_ARGS) config + @touch $@ + +.PHONY: config +config: $(B)/.config.ok + +.PHONY: build-nasm +build-nasm: + cd $(NASM_SOURCE) && sh configure && make -j + +.PHONY: build-ipsec-mb +build-ipsec-mb: + mkdir -p $(I)/lib/ + # Do not build GCM stuff if we are building ISA_L + make -C $(AESNIMB_LIB_SOURCE) -j SHARED=n \ + EXTRA_CFLAGS=-fPIC NASM=$(NASM_SOURCE)/nasm + cp $(AESNIMB_LIB_SOURCE)/libIPSec_MB.a $(I)/lib/ + +.PHONY: build-dpdk +build-dpdk: + @if [ ! -e $(B)/.config.ok ] ; then echo 'Please run "make config" first' && false ; fi + @make $(DPDK_MAKE_ARGS) install + +# Order matters +ifeq ($(AESNI),y) +BUILD_TARGETS += build-nasm +BUILD_TARGETS += build-ipsec-mb +endif +BUILD_TARGETS += build-dpdk + +$(B)/.build.ok: $(BUILD_TARGETS) + @touch $@ + +.PHONY: build +build: $(B)/.build.ok + +.PHONY: install +install: $(B)/.build.ok + +.PHONY: clean +clean: + @rm -rf $(B) $(I) + +############################################################################## +# .deb packaging +############################################################################## + +DEB_VER := $(PKG_VERSION) +DEB_ARCH=$(shell dpkg --print-architecture 2> /dev/null) +DEV_DEB=vpp-ext-deps_$(DEB_VER)-$(PKG_SUFFIX)_$(DEB_ARCH).deb +INSTALLED_VER=$(shell dpkg-query --showformat='$${Version}' --show vpp-ext-deps 2> /dev/null) + +.PHONY: build-deb install-deb check-deb + +deb/debian/changelog: Makefile + @echo "vpp-ext-deps ($(DEB_VER)-$(PKG_SUFFIX)) unstable; urgency=low" > $@ + @echo "" >> $@ + @echo " * Version $(DEB_VER)" >> $@ + @echo "" >> $@ + @echo " -- VPP Dev <vpp-dev@lists.fd.io> $(shell date -R)" >> $@ + +$(DEV_DEB): deb/debian/changelog + @cd deb && dpkg-buildpackage -b -uc -us + git clean -fdx deb + +build-deb: $(DEV_DEB) + +install-deb: +ifneq ($(INSTALLED_VER),$(DEB_VER)-$(PKG_SUFFIX)) + @echo "==========================================================" + @echo " Out of date vpp-ext-deps package installed." + @echo " Installed: $(INSTALLED_VER)" + @echo " Needed: $(DEB_VER)-$(PKG_SUFFIX)" + @echo "==========================================================" + @make $(DEV_DEB) + @sudo dpkg -i $(DEV_DEB) +else + @echo "==========================================================" + @echo " Up-to-date vpp-ext-deps package already installed" + @echo "==========================================================" +endif + +check-deb: +ifneq ($(INSTALLED_VER),$(DEB_VER)-$(PKG_SUFFIX)) + @echo "==========================================================" + @echo " Outdated DPDK package detected:" + @echo " Installed: vpp-ext-deps $(INSTALLED_VER)" + @echo " Current: vpp-ext-deps $(DEB_VER)-$(PKG_SUFFIX)" + @echo "" + @echo " Please upgrade by invoking 'make install-ext-deps'" + @echo " from the top level directory." + @echo "==========================================================" +endif + +############################################################################## +# .rpm packaging +############################################################################## + +RPM_VER := $(PKG_VERSION) +RPM_ARCH=$(shell rpm --eval "%{_arch}" 2> /dev/null) +DEV_RPM=vpp-ext-deps-$(RPM_VER)-$(PKG_SUFFIX).$(RPM_ARCH).rpm +INSTALLED_RPM_VER=$(shell rpm -q --queryformat '%{VERSION}-%{RELEASE}' vpp-ext-deps 2> /dev/null | grep -v "not inst") + +.PHONY: build-rpm install-rpm check-rpm + +$(DEV_RPM): Makefile rpm/vpp-ext-deps.spec + @rpmbuild -bb \ + --define "_topdir $(CURDIR)/rpm" \ + --define "_version $(RPM_VER)" \ + --define "_release $(PKG_SUFFIX)" \ + $(CURDIR)/rpm/vpp-ext-deps.spec + mv rpm/RPMS/$(RPM_ARCH)/*.rpm . + git clean -fdx rpm + +build-rpm: $(DEV_RPM) + +install-rpm: +ifneq ($(INSTALLED_RPM_VER),$(PRM_VER)-$(PKG_SUFFIX)) + @$(MAKE) $(DEV_RPM) + sudo rpm -Uih $(DEV_RPM) +else + @echo "==========================================================" + @echo " Up-to-date DPDK package already installed" + @echo "==========================================================" +endif + +check-rpm: +ifneq ($(INSTALLED_RPM_VER),$(RPM_VER)-$(PKG_SUFFIX)) + @echo "==========================================================" + @echo " Outdated DPDK package detected:" + @echo " Installed: vpp-ext-deps $(INSTALLED_RPM_VER)" + @echo " Current: vpp-ext-deps $(RPM_VER)-$(PKG_SUFFIX)" + @echo "" + @echo " Please upgrade by invoking 'make install-ext-deps'" + @echo " from the top level directory." + @echo "==========================================================" +endif + +############################################################################## +# ebuild support +############################################################################## + +.PHONY: ebuild-build ebuild-install + +ebuild-build: +ifeq ($(INSTALLED_VER)$(INSTALLED_RPM_VER),) + @echo "==========================================================" + @echo "Building DPDK from source. Consider installing development" + @echo "package by invoking 'make install-ext-deps' from the" + @echo "top level directory" + @echo "==========================================================" + make config +else +ifneq ($(INSTALLED_VER),) + make check-deb +endif +ifneq ($(INSTALLED_RPM_VER),) + make check-rpm +endif +endif + +ebuild-install: +ifeq ($(INSTALLED_VER)$(INSTALLED_RPM_VER),) + make install +endif diff --git a/build/external/README b/build/external/README new file mode 100644 index 00000000000..95154dc235f --- /dev/null +++ b/build/external/README @@ -0,0 +1,34 @@ + +Changes needed to DPDK are stored here as git patch files. Maintaining these +files using “git format-patch” and “git am” will make it simpler to manage +these changes. Patches made to DPDK should only be temporary until they are +accepted upstream and made available in the next DPDK release. + +The following is the method used to generate these patches: + +1. Git clone the DPDK to a new directory: + # git clone http://dpdk.org/git/dpdk dpdk + +2. Create a branch based on the DPDK release you wish to patch. +Note, “git tag” will show you all the release tags. The following example is +for DPDK release tag “v2.2.0” and will create a branch named “two_dot_two”. + # cd dpdk + # git checkout -b two_dot_two v2.2.0 + +3. Apply all the existing VPP DPDK patches to this new branch. + # git am <VPP directory>/dpdk/dpdk-2.2.0_patches/* + +4. Make your changes and commit your change to your DPDK repository. + # <edit files> + # git commit -s + +5. Create the patch files with format-patch. This creates all the patch files +for your branch (two_dot_two), with your latest commits as the last ones. + # git format-patch master..two_dot_two + +6. Copy, add and commit the new patches into the VPP patches directory. + # cp <new patch files> <VPP directory>/dpdk/dpdk-2.2.0_patches + # cd <VPP directory> + # git add dpdk/dpdk-2.2.0_patches/<new patch files> + # git commit -s + diff --git a/build/external/deb/debian/compat b/build/external/deb/debian/compat new file mode 100755 index 00000000000..ec635144f60 --- /dev/null +++ b/build/external/deb/debian/compat @@ -0,0 +1 @@ +9 diff --git a/build/external/deb/debian/control b/build/external/deb/debian/control new file mode 100644 index 00000000000..80b81b8b375 --- /dev/null +++ b/build/external/deb/debian/control @@ -0,0 +1,13 @@ +Source: vpp-ext-deps +Section: net +Priority: extra +Maintainer: vpp-dev@lists.fd.io +Build-Depends: debhelper (>= 9), dkms +Standards-Version: 3.9.4 + +Package: vpp-ext-deps +Architecture: any +Depends: ${shlibs:Depends} +Description: VPP developer package containing dependencies +Replaces: vpp-dpdk-dev +Conflicts: vpp-dpdk-dev diff --git a/build/external/deb/debian/dkms/Makefile b/build/external/deb/debian/dkms/Makefile new file mode 100644 index 00000000000..452c7c265e9 --- /dev/null +++ b/build/external/deb/debian/dkms/Makefile @@ -0,0 +1,10 @@ +obj-m:=igb_uio.o + +CONFIG_MODULE_SIG=n + +EXTRA_CFLAGS += -Winline -I$(PWD) + +default: + $(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules +clean: + $(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) clean diff --git a/build/external/deb/debian/rules b/build/external/deb/debian/rules new file mode 100755 index 00000000000..6ffefc1d0b2 --- /dev/null +++ b/build/external/deb/debian/rules @@ -0,0 +1,27 @@ +#!/usr/bin/make -f +DH_VERBOSE = 1 +PKG=vpp-ext-deps + +VERSION = $(shell dpkg-parsechangelog | sed -nr '/^Version:/s/Version: //p') +BASE_VER = $(word 1, $(subst -, ,$(VERSION))) + +export DPDK_BUILD_DIR=$(CURDIR)/_build +export DPDK_INSTALL_DIR=$(CURDIR)/debian/tmp/opt/vpp/external/$(shell uname -m)/ + +MAKE_ARGS=-C .. + +include /usr/share/dpkg/default.mk + +%: + dh $@ + +override_dh_clean: + make $(MAKE_ARGS) clean + +override_dh_auto_configure: + make $(MAKE_ARGS) config + +override_dh_install: + make $(MAKE_ARGS) install + dh_install -p$(PKG) --autodest /opt + diff --git a/build/external/dpdk-18.02.1_patches/0001-ixgbe-link-wait-longer.patch b/build/external/dpdk-18.02.1_patches/0001-ixgbe-link-wait-longer.patch new file mode 100644 index 00000000000..fb71e94c7ba --- /dev/null +++ b/build/external/dpdk-18.02.1_patches/0001-ixgbe-link-wait-longer.patch @@ -0,0 +1,13 @@ +diff --git a/drivers/net/ixgbe/base/ixgbe_common.c b/drivers/net/ixgbe/base/ixgbe_common.c +index e7e9256e5..2fb0a072c 100644 +--- a/drivers/net/ixgbe/base/ixgbe_common.c ++++ b/drivers/net/ixgbe/base/ixgbe_common.c +@@ -5296,7 +5296,7 @@ s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw, + * Section 73.10.2, we may have to wait up to 500ms if KR is + * attempted. 82599 uses the same timing for 10g SFI. + */ +- for (i = 0; i < 5; i++) { ++ for (i = 0; i < 10; i++) { + /* Wait for the link partner to also set speed */ + msec_delay(100); + diff --git a/build/external/dpdk-18.02_patches/0001-assign-QAT-cryptodev-to-correct-NUMA-node.patch b/build/external/dpdk-18.02_patches/0001-assign-QAT-cryptodev-to-correct-NUMA-node.patch new file mode 100644 index 00000000000..32d2c783cde --- /dev/null +++ b/build/external/dpdk-18.02_patches/0001-assign-QAT-cryptodev-to-correct-NUMA-node.patch @@ -0,0 +1,29 @@ +From b01857dfdb4e46b8c7d306c608c58ebbabc252ec Mon Sep 17 00:00:00 2001 +From: Lee Roberts <lee.roberts@hpe.com> +Date: Fri, 9 Mar 2018 10:49:34 -0700 +Subject: [PATCH] assign QAT cryptodev to correct NUMA node + +rte_cryptodev_pmd_init_params should use NUMA node of the QAT device +for its socket_id rather than the socket_id of the initializing process. + +Signed-off-by: Lee Roberts <lee.roberts@hpe.com> +--- + drivers/crypto/qat/rte_qat_cryptodev.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/crypto/qat/rte_qat_cryptodev.c b/drivers/crypto/qat/rte_qat_cryptodev.c +index bf83740..82641aa 100644 +--- a/drivers/crypto/qat/rte_qat_cryptodev.c ++++ b/drivers/crypto/qat/rte_qat_cryptodev.c +@@ -130,7 +130,7 @@ static int crypto_qat_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, + { + struct rte_cryptodev_pmd_init_params init_params = { + .name = "", +- .socket_id = rte_socket_id(), ++ .socket_id = pci_dev->device.numa_node, + .private_data_size = sizeof(struct qat_pmd_private), + .max_nb_sessions = RTE_QAT_PMD_MAX_NB_SESSIONS + }; +-- +1.9.1 + diff --git a/build/external/dpdk-18.05_patches/0001-i40evf-don-t-reset-device_info-data.patch b/build/external/dpdk-18.05_patches/0001-i40evf-don-t-reset-device_info-data.patch new file mode 100644 index 00000000000..b737461a99b --- /dev/null +++ b/build/external/dpdk-18.05_patches/0001-i40evf-don-t-reset-device_info-data.patch @@ -0,0 +1,28 @@ +From 65a8641604212d58defd71491c900d84d662a086 Mon Sep 17 00:00:00 2001 +From: Damjan Marion <damarion@cisco.com> +Date: Wed, 6 Jun 2018 21:57:58 +0200 +Subject: [PATCH] i40evf: don't reset device_info data + +At this point valid data is already set by rte_eth_get_device_info. +device field becomes zero and consumer is not able retrieve pci data. + +Signed-off-by: Damjan Marion <damarion@cisco.com> +--- + drivers/net/i40e/i40e_ethdev_vf.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c +index 804e44530..86b38d202 100644 +--- a/drivers/net/i40e/i40e_ethdev_vf.c ++++ b/drivers/net/i40e/i40e_ethdev_vf.c +@@ -2182,7 +2182,6 @@ i40evf_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) + { + struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); + +- memset(dev_info, 0, sizeof(*dev_info)); + dev_info->max_rx_queues = vf->vsi_res->num_queue_pairs; + dev_info->max_tx_queues = vf->vsi_res->num_queue_pairs; + dev_info->min_rx_bufsize = I40E_BUF_SIZE_MIN; +-- +2.17.1 + diff --git a/build/external/dpdk-18.05_patches/0002-ixgbe-link-wait-longer.patch b/build/external/dpdk-18.05_patches/0002-ixgbe-link-wait-longer.patch new file mode 100644 index 00000000000..fb71e94c7ba --- /dev/null +++ b/build/external/dpdk-18.05_patches/0002-ixgbe-link-wait-longer.patch @@ -0,0 +1,13 @@ +diff --git a/drivers/net/ixgbe/base/ixgbe_common.c b/drivers/net/ixgbe/base/ixgbe_common.c +index e7e9256e5..2fb0a072c 100644 +--- a/drivers/net/ixgbe/base/ixgbe_common.c ++++ b/drivers/net/ixgbe/base/ixgbe_common.c +@@ -5296,7 +5296,7 @@ s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw, + * Section 73.10.2, we may have to wait up to 500ms if KR is + * attempted. 82599 uses the same timing for 10g SFI. + */ +- for (i = 0; i < 5; i++) { ++ for (i = 0; i < 10; i++) { + /* Wait for the link partner to also set speed */ + msec_delay(100); + diff --git a/build/external/dpdk-18.08_patches/0001-net-mlx5-support-externally-allocated-mempool.patch b/build/external/dpdk-18.08_patches/0001-net-mlx5-support-externally-allocated-mempool.patch new file mode 100644 index 00000000000..87c9cf92469 --- /dev/null +++ b/build/external/dpdk-18.08_patches/0001-net-mlx5-support-externally-allocated-mempool.patch @@ -0,0 +1,270 @@ +From bd42c77c457146bede32333558b4e0414b30683e Mon Sep 17 00:00:00 2001 +From: Yongseok Koh <yskoh@mellanox.com> +Date: Fri, 24 Aug 2018 16:46:49 -0700 +Subject: [PATCH] net/mlx5: support externally allocated mempool + +When MLX PMD registers memory for DMA, it accesses the global memseg list +of DPDK to maximize the range of registration so that LKey search can be +more efficient. Granularity of MR registration is per page. + +Externally allocated memory shouldn't be used for DMA because it can't be +searched in the memseg list and free event can't be tracked by DPDK. +However, if the external memory is static (allocated on startup and never +freed), such memory can also be registered by little tweak in the code. + +Signed-off-by: Yongseok Koh <yskoh@mellanox.com> +--- + drivers/net/mlx5/mlx5_mr.c | 155 +++++++++++++++++++++++++++++++++++++++++++ + drivers/net/mlx5/mlx5_rxtx.h | 35 +++++++++- + 2 files changed, 189 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/mlx5/mlx5_mr.c b/drivers/net/mlx5/mlx5_mr.c +index 08105a443..876622e91 100644 +--- a/drivers/net/mlx5/mlx5_mr.c ++++ b/drivers/net/mlx5/mlx5_mr.c +@@ -277,6 +277,23 @@ mr_find_next_chunk(struct mlx5_mr *mr, struct mlx5_mr_cache *entry, + uintptr_t end = 0; + uint32_t idx = 0; + ++ /* MR for external memory doesn't have memseg list. */ ++ if (mr->msl == NULL) { ++ struct ibv_mr *ibv_mr = mr->ibv_mr; ++ ++ assert(mr->ms_bmp_n == 1); ++ assert(mr->ms_n == 1); ++ assert(base_idx == 0); ++ /* ++ * Can't search it from memseg list but get it directly from ++ * verbs MR as there's only one chunk. ++ */ ++ entry->start = (uintptr_t)ibv_mr->addr; ++ entry->end = (uintptr_t)ibv_mr->addr + mr->ibv_mr->length; ++ entry->lkey = rte_cpu_to_be_32(mr->ibv_mr->lkey); ++ /* Returning 1 ends iteration. */ ++ return 1; ++ } + for (idx = base_idx; idx < mr->ms_bmp_n; ++idx) { + if (rte_bitmap_get(mr->ms_bmp, idx)) { + const struct rte_memseg_list *msl; +@@ -818,6 +835,7 @@ mlx5_mr_mem_event_free_cb(struct rte_eth_dev *dev, const void *addr, size_t len) + mr = mr_lookup_dev_list(dev, &entry, start); + if (mr == NULL) + continue; ++ assert(mr->msl); /* Can't be external memory. */ + ms = rte_mem_virt2memseg((void *)start, msl); + assert(ms != NULL); + assert(msl->page_sz == ms->hugepage_sz); +@@ -1070,6 +1088,139 @@ mlx5_mr_flush_local_cache(struct mlx5_mr_ctrl *mr_ctrl) + (void *)mr_ctrl, mr_ctrl->cur_gen); + } + ++/** ++ * Called during rte_mempool_mem_iter() by mlx5_mr_update_ext_mp(). ++ * ++ * Externally allocated chunk is registered and a MR is created for the chunk. ++ * The MR object is added to the global list. If memseg list of a MR object ++ * (mr->msl) is null, the MR object can be regarded as externally allocated ++ * memory. ++ * ++ * Once external memory is registered, it should be static. If the memory is ++ * freed and the virtual address range has different physical memory mapped ++ * again, it may cause crash on device due to the wrong translation entry. PMD ++ * can't track the free event of the external memory for now. ++ */ ++static void ++mlx5_mr_update_ext_mp_cb(struct rte_mempool *mp, void *opaque, ++ struct rte_mempool_memhdr *memhdr, ++ unsigned mem_idx __rte_unused) ++{ ++ struct mr_update_mp_data *data = opaque; ++ struct rte_eth_dev *dev = data->dev; ++ struct priv *priv = dev->data->dev_private; ++ struct mlx5_mr_ctrl *mr_ctrl = data->mr_ctrl; ++ struct mlx5_mr *mr = NULL; ++ uintptr_t addr = (uintptr_t)memhdr->addr; ++ size_t len = memhdr->len; ++ struct mlx5_mr_cache entry; ++ uint32_t lkey; ++ ++ /* If already registered, it should return. */ ++ rte_rwlock_read_lock(&priv->mr.rwlock); ++ lkey = mr_lookup_dev(dev, &entry, addr); ++ rte_rwlock_read_unlock(&priv->mr.rwlock); ++ if (lkey != UINT32_MAX) ++ return; ++ mr = rte_zmalloc_socket(NULL, ++ RTE_ALIGN_CEIL(sizeof(*mr), ++ RTE_CACHE_LINE_SIZE), ++ RTE_CACHE_LINE_SIZE, mp->socket_id); ++ if (mr == NULL) { ++ DRV_LOG(WARNING, ++ "port %u unable to allocate memory for a new MR of" ++ " mempool (%s).", ++ dev->data->port_id, mp->name); ++ data->ret = -1; ++ return; ++ } ++ DRV_LOG(DEBUG, "port %u register MR for chunk #%d of mempool (%s)", ++ dev->data->port_id, mem_idx, mp->name); ++ mr->ibv_mr = mlx5_glue->reg_mr(priv->pd, (void *)addr, len, ++ IBV_ACCESS_LOCAL_WRITE); ++ if (mr->ibv_mr == NULL) { ++ DRV_LOG(WARNING, ++ "port %u fail to create a verbs MR for address (%p)", ++ dev->data->port_id, (void *)addr); ++ rte_free(mr); ++ data->ret = -1; ++ return; ++ } ++ mr->msl = NULL; /* Mark it is external memory. */ ++ mr->ms_bmp = NULL; ++ mr->ms_n = 1; ++ mr->ms_bmp_n = 1; ++ rte_rwlock_write_lock(&priv->mr.rwlock); ++ LIST_INSERT_HEAD(&priv->mr.mr_list, mr, mr); ++ DRV_LOG(DEBUG, ++ "port %u MR CREATED (%p) for external memory %p:\n" ++ " [0x%" PRIxPTR ", 0x%" PRIxPTR ")," ++ " lkey=0x%x base_idx=%u ms_n=%u, ms_bmp_n=%u", ++ dev->data->port_id, (void *)mr, (void *)addr, ++ addr, addr + len, rte_cpu_to_be_32(mr->ibv_mr->lkey), ++ mr->ms_base_idx, mr->ms_n, mr->ms_bmp_n); ++ /* Insert to the global cache table. */ ++ mr_insert_dev_cache(dev, mr); ++ rte_rwlock_write_unlock(&priv->mr.rwlock); ++ /* Insert to the local cache table */ ++ mlx5_mr_addr2mr_bh(dev, mr_ctrl, addr); ++} ++ ++/** ++ * Register MR for entire memory chunks in a Mempool having externally allocated ++ * memory and fill in local cache. ++ * ++ * @param dev ++ * Pointer to Ethernet device. ++ * @param mr_ctrl ++ * Pointer to per-queue MR control structure. ++ * @param mp ++ * Pointer to registering Mempool. ++ * ++ * @return ++ * 0 on success, -1 on failure. ++ */ ++static uint32_t ++mlx5_mr_update_ext_mp(struct rte_eth_dev *dev, struct mlx5_mr_ctrl *mr_ctrl, ++ struct rte_mempool *mp) ++{ ++ struct mr_update_mp_data data = { ++ .dev = dev, ++ .mr_ctrl = mr_ctrl, ++ .ret = 0, ++ }; ++ ++ rte_mempool_mem_iter(mp, mlx5_mr_update_ext_mp_cb, &data); ++ return data.ret; ++} ++ ++/** ++ * Register MR entire memory chunks in a Mempool having externally allocated ++ * memory and search LKey of the address to return. ++ * ++ * @param dev ++ * Pointer to Ethernet device. ++ * @param addr ++ * Search key. ++ * @param mp ++ * Pointer to registering Mempool where addr belongs. ++ * ++ * @return ++ * LKey for address on success, UINT32_MAX on failure. ++ */ ++uint32_t ++mlx5_tx_update_ext_mp(struct mlx5_txq_data *txq, uintptr_t addr, ++ struct rte_mempool *mp) ++{ ++ struct mlx5_txq_ctrl *txq_ctrl = ++ container_of(txq, struct mlx5_txq_ctrl, txq); ++ struct mlx5_mr_ctrl *mr_ctrl = &txq->mr_ctrl; ++ struct priv *priv = txq_ctrl->priv; ++ ++ mlx5_mr_update_ext_mp(ETH_DEV(priv), mr_ctrl, mp); ++ return mlx5_tx_addr2mr_bh(txq, addr); ++} ++ + /* Called during rte_mempool_mem_iter() by mlx5_mr_update_mp(). */ + static void + mlx5_mr_update_mp_cb(struct rte_mempool *mp __rte_unused, void *opaque, +@@ -1113,6 +1264,10 @@ mlx5_mr_update_mp(struct rte_eth_dev *dev, struct mlx5_mr_ctrl *mr_ctrl, + }; + + rte_mempool_mem_iter(mp, mlx5_mr_update_mp_cb, &data); ++ if (data.ret < 0 && rte_errno == ENXIO) { ++ /* Mempool may have externally allocated memory. */ ++ return mlx5_mr_update_ext_mp(dev, mr_ctrl, mp); ++ } + return data.ret; + } + +diff --git a/drivers/net/mlx5/mlx5_rxtx.h b/drivers/net/mlx5/mlx5_rxtx.h +index f53bb43c3..b61c23b33 100644 +--- a/drivers/net/mlx5/mlx5_rxtx.h ++++ b/drivers/net/mlx5/mlx5_rxtx.h +@@ -347,6 +347,8 @@ uint16_t mlx5_rx_burst_vec(void *dpdk_txq, struct rte_mbuf **pkts, + void mlx5_mr_flush_local_cache(struct mlx5_mr_ctrl *mr_ctrl); + uint32_t mlx5_rx_addr2mr_bh(struct mlx5_rxq_data *rxq, uintptr_t addr); + uint32_t mlx5_tx_addr2mr_bh(struct mlx5_txq_data *txq, uintptr_t addr); ++uint32_t mlx5_tx_update_ext_mp(struct mlx5_txq_data *txq, uintptr_t addr, ++ struct rte_mempool *mp); + + #ifndef NDEBUG + /** +@@ -534,6 +536,24 @@ mlx5_tx_complete(struct mlx5_txq_data *txq) + } + + /** ++ * Get Memory Pool (MP) from mbuf. If mbuf is indirect, the pool from which the ++ * cloned mbuf is allocated is returned instead. ++ * ++ * @param buf ++ * Pointer to mbuf. ++ * ++ * @return ++ * Memory pool where data is located for given mbuf. ++ */ ++static struct rte_mempool * ++mlx5_mb2mp(struct rte_mbuf *buf) ++{ ++ if (unlikely(RTE_MBUF_INDIRECT(buf))) ++ return rte_mbuf_from_indirect(buf)->pool; ++ return buf->pool; ++} ++ ++/** + * Query LKey from a packet buffer for Rx. No need to flush local caches for Rx + * as mempool is pre-configured and static. + * +@@ -591,7 +611,20 @@ mlx5_tx_addr2mr(struct mlx5_txq_data *txq, uintptr_t addr) + return mlx5_tx_addr2mr_bh(txq, addr); + } + +-#define mlx5_tx_mb2mr(rxq, mb) mlx5_tx_addr2mr(rxq, (uintptr_t)((mb)->buf_addr)) ++static __rte_always_inline uint32_t ++mlx5_tx_mb2mr(struct mlx5_txq_data *txq, struct rte_mbuf *mb) ++{ ++ uintptr_t addr = (uintptr_t)mb->buf_addr; ++ uint32_t lkey = mlx5_tx_addr2mr(txq, addr); ++ ++ if (likely(lkey != UINT32_MAX)) ++ return lkey; ++ if (rte_errno == ENXIO) { ++ /* Mempool may have externally allocated memory. */ ++ lkey = mlx5_tx_update_ext_mp(txq, addr, mlx5_mb2mp(mb)); ++ } ++ return lkey; ++} + + /** + * Ring TX queue doorbell and flush the update if requested. +-- +2.11.0 + diff --git a/build/external/dpdk-18.08_patches/0002-mlx4-support-externally-allocated-mempool.patch b/build/external/dpdk-18.08_patches/0002-mlx4-support-externally-allocated-mempool.patch new file mode 100644 index 00000000000..b32862335e5 --- /dev/null +++ b/build/external/dpdk-18.08_patches/0002-mlx4-support-externally-allocated-mempool.patch @@ -0,0 +1,250 @@ +From c947fd2ec67e9bbacb8b106f320f6e6bae5a9731 Mon Sep 17 00:00:00 2001 +From: Matthew Smith <mgsmith@netgate.com> +Date: Tue, 28 Aug 2018 13:21:04 -0500 +Subject: [PATCH] mlx4: support externally allocated mempool + +Port Mellanox mlx5 PMD patch to work for mlx4 PMD. + +Signed-off-by: Matthew Smith <mgsmith@netgate.com> +--- + drivers/net/mlx4/mlx4_mr.c | 150 +++++++++++++++++++++++++++++++++++++++++++ + drivers/net/mlx4/mlx4_rxtx.h | 35 +++++++++- + 2 files changed, 184 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/mlx4/mlx4_mr.c b/drivers/net/mlx4/mlx4_mr.c +index d23d3c613..55e5555ce 100644 +--- a/drivers/net/mlx4/mlx4_mr.c ++++ b/drivers/net/mlx4/mlx4_mr.c +@@ -289,6 +289,23 @@ mr_find_next_chunk(struct mlx4_mr *mr, struct mlx4_mr_cache *entry, + uintptr_t end = 0; + uint32_t idx = 0; + ++ /* MR for external memory doesn't have memseg list. */ ++ if (mr->msl == NULL) { ++ struct ibv_mr *ibv_mr = mr->ibv_mr; ++ ++ assert(mr->ms_bmp_n == 1); ++ assert(mr->ms_n == 1); ++ assert(base_idx == 0); ++ /* ++ * Can't search it from memseg list but get it directly from ++ * verbs MR as there's only one chunk. ++ */ ++ entry->start = (uintptr_t)ibv_mr->addr; ++ entry->end = (uintptr_t)ibv_mr->addr + mr->ibv_mr->length; ++ entry->lkey = rte_cpu_to_be_32(mr->ibv_mr->lkey); ++ /* Returning 1 ends iteration. */ ++ return 1; ++ } + for (idx = base_idx; idx < mr->ms_bmp_n; ++idx) { + if (rte_bitmap_get(mr->ms_bmp, idx)) { + const struct rte_memseg_list *msl; +@@ -809,6 +826,7 @@ mlx4_mr_mem_event_free_cb(struct rte_eth_dev *dev, const void *addr, size_t len) + mr = mr_lookup_dev_list(dev, &entry, start); + if (mr == NULL) + continue; ++ assert(mr->msl); /* Can't be external memory. */ + ms = rte_mem_virt2memseg((void *)start, msl); + assert(ms != NULL); + assert(msl->page_sz == ms->hugepage_sz); +@@ -1055,6 +1073,134 @@ mlx4_mr_flush_local_cache(struct mlx4_mr_ctrl *mr_ctrl) + (void *)mr_ctrl, mr_ctrl->cur_gen); + } + ++/** ++ * Called during rte_mempool_mem_iter() by mlx4_mr_update_ext_mp(). ++ * ++ * Externally allocated chunk is registered and a MR is created for the chunk. ++ * The MR object is added to the global list. If memseg list of a MR object ++ * (mr->msl) is null, the MR object can be regarded as externally allocated ++ * memory. ++ * ++ * Once external memory is registered, it should be static. If the memory is ++ * freed and the virtual address range has different physical memory mapped ++ * again, it may cause crash on device due to the wrong translation entry. PMD ++ * can't track the free event of the external memory for now. ++ */ ++static void ++mlx4_mr_update_ext_mp_cb(struct rte_mempool *mp, void *opaque, ++ struct rte_mempool_memhdr *memhdr, ++ unsigned mem_idx __rte_unused) ++{ ++ struct mr_update_mp_data *data = opaque; ++ struct rte_eth_dev *dev = data->dev; ++ struct priv *priv = dev->data->dev_private; ++ struct mlx4_mr_ctrl *mr_ctrl = data->mr_ctrl; ++ struct mlx4_mr *mr = NULL; ++ uintptr_t addr = (uintptr_t)memhdr->addr; ++ size_t len = memhdr->len; ++ struct mlx4_mr_cache entry; ++ uint32_t lkey; ++ ++ /* If already registered, it should return. */ ++ rte_rwlock_read_lock(&priv->mr.rwlock); ++ lkey = mr_lookup_dev(dev, &entry, addr); ++ rte_rwlock_read_unlock(&priv->mr.rwlock); ++ if (lkey != UINT32_MAX) ++ return; ++ mr = rte_zmalloc_socket(NULL, ++ RTE_ALIGN_CEIL(sizeof(*mr), ++ RTE_CACHE_LINE_SIZE), ++ RTE_CACHE_LINE_SIZE, mp->socket_id); ++ if (mr == NULL) { ++ WARN("port %u unable to allocate memory for a new MR of" ++ " mempool (%s).", ++ dev->data->port_id, mp->name); ++ data->ret = -1; ++ return; ++ } ++ DEBUG("port %u register MR for chunk #%d of mempool (%s)", ++ dev->data->port_id, mem_idx, mp->name); ++ mr->ibv_mr = mlx4_glue->reg_mr(priv->pd, (void *)addr, len, ++ IBV_ACCESS_LOCAL_WRITE); ++ if (mr->ibv_mr == NULL) { ++ WARN("port %u fail to create a verbs MR for address (%p)", ++ dev->data->port_id, (void *)addr); ++ rte_free(mr); ++ data->ret = -1; ++ return; ++ } ++ mr->msl = NULL; /* Mark it is external memory. */ ++ mr->ms_bmp = NULL; ++ mr->ms_n = 1; ++ mr->ms_bmp_n = 1; ++ rte_rwlock_write_lock(&priv->mr.rwlock); ++ LIST_INSERT_HEAD(&priv->mr.mr_list, mr, mr); ++ DEBUG("port %u MR CREATED (%p) for external memory %p:\n" ++ " [0x%" PRIxPTR ", 0x%" PRIxPTR ")," ++ " lkey=0x%x base_idx=%u ms_n=%u, ms_bmp_n=%u", ++ dev->data->port_id, (void *)mr, (void *)addr, ++ addr, addr + len, rte_cpu_to_be_32(mr->ibv_mr->lkey), ++ mr->ms_base_idx, mr->ms_n, mr->ms_bmp_n); ++ /* Insert to the global cache table. */ ++ mr_insert_dev_cache(dev, mr); ++ rte_rwlock_write_unlock(&priv->mr.rwlock); ++ /* Insert to the local cache table */ ++ mlx4_mr_addr2mr_bh(dev, mr_ctrl, addr); ++} ++ ++/** ++ * Register MR for entire memory chunks in a Mempool having externally allocated ++ * memory and fill in local cache. ++ * ++ * @param dev ++ * Pointer to Ethernet device. ++ * @param mr_ctrl ++ * Pointer to per-queue MR control structure. ++ * @param mp ++ * Pointer to registering Mempool. ++ * ++ * @return ++ * 0 on success, -1 on failure. ++ */ ++static uint32_t ++mlx4_mr_update_ext_mp(struct rte_eth_dev *dev, struct mlx4_mr_ctrl *mr_ctrl, ++ struct rte_mempool *mp) ++{ ++ struct mr_update_mp_data data = { ++ .dev = dev, ++ .mr_ctrl = mr_ctrl, ++ .ret = 0, ++ }; ++ ++ rte_mempool_mem_iter(mp, mlx4_mr_update_ext_mp_cb, &data); ++ return data.ret; ++} ++ ++/** ++ * Register MR entire memory chunks in a Mempool having externally allocated ++ * memory and search LKey of the address to return. ++ * ++ * @param dev ++ * Pointer to Ethernet device. ++ * @param addr ++ * Search key. ++ * @param mp ++ * Pointer to registering Mempool where addr belongs. ++ * ++ * @return ++ * LKey for address on success, UINT32_MAX on failure. ++ */ ++uint32_t ++mlx4_tx_update_ext_mp(struct txq *txq, uintptr_t addr, ++ struct rte_mempool *mp) ++{ ++ struct mlx4_mr_ctrl *mr_ctrl = &txq->mr_ctrl; ++ struct priv *priv = txq->priv; ++ ++ mlx4_mr_update_ext_mp(priv->dev, mr_ctrl, mp); ++ return mlx4_tx_addr2mr_bh(txq, addr); ++} ++ + /* Called during rte_mempool_mem_iter() by mlx4_mr_update_mp(). */ + static void + mlx4_mr_update_mp_cb(struct rte_mempool *mp __rte_unused, void *opaque, +@@ -1098,6 +1244,10 @@ mlx4_mr_update_mp(struct rte_eth_dev *dev, struct mlx4_mr_ctrl *mr_ctrl, + }; + + rte_mempool_mem_iter(mp, mlx4_mr_update_mp_cb, &data); ++ if (data.ret < 0 && rte_errno == ENXIO) { ++ /* Mempool may have externally allocated memory. */ ++ return mlx4_mr_update_ext_mp(dev, mr_ctrl, mp); ++ } + return data.ret; + } + +diff --git a/drivers/net/mlx4/mlx4_rxtx.h b/drivers/net/mlx4/mlx4_rxtx.h +index ffa8abfca..1be060cda 100644 +--- a/drivers/net/mlx4/mlx4_rxtx.h ++++ b/drivers/net/mlx4/mlx4_rxtx.h +@@ -163,6 +163,26 @@ void mlx4_tx_queue_release(void *dpdk_txq); + void mlx4_mr_flush_local_cache(struct mlx4_mr_ctrl *mr_ctrl); + uint32_t mlx4_rx_addr2mr_bh(struct rxq *rxq, uintptr_t addr); + uint32_t mlx4_tx_addr2mr_bh(struct txq *txq, uintptr_t addr); ++uint32_t mlx4_tx_update_ext_mp(struct txq *txq, uintptr_t addr, ++ struct rte_mempool *mp); ++ ++/** ++ * Get Memory Pool (MP) from mbuf. If mbuf is indirect, the pool from which the ++ * cloned mbuf is allocated is returned instead. ++ * ++ * @param buf ++ * Pointer to mbuf. ++ * ++ * @return ++ * Memory pool where data is located for given mbuf. ++ */ ++static struct rte_mempool * ++mlx4_mb2mp(struct rte_mbuf *buf) ++{ ++ if (unlikely(RTE_MBUF_INDIRECT(buf))) ++ return rte_mbuf_from_indirect(buf)->pool; ++ return buf->pool; ++} + + /** + * Query LKey from a packet buffer for Rx. No need to flush local caches for Rx +@@ -222,6 +242,19 @@ mlx4_tx_addr2mr(struct txq *txq, uintptr_t addr) + return mlx4_tx_addr2mr_bh(txq, addr); + } + +-#define mlx4_tx_mb2mr(rxq, mb) mlx4_tx_addr2mr(rxq, (uintptr_t)((mb)->buf_addr)) ++static __rte_always_inline uint32_t ++mlx4_tx_mb2mr(struct txq *txq, struct rte_mbuf *mb) ++{ ++ uintptr_t addr = (uintptr_t)mb->buf_addr; ++ uint32_t lkey = mlx4_tx_addr2mr(txq, addr); ++ ++ if (likely(lkey != UINT32_MAX)) ++ return lkey; ++ if (rte_errno == ENXIO) { ++ /* Mempool may have externally allocated memory. */ ++ lkey = mlx4_tx_update_ext_mp(txq, addr, mlx4_mb2mp(mb)); ++ } ++ return lkey; ++} + + #endif /* MLX4_RXTX_H_ */ +-- +2.15.2 (Apple Git-101.1) + diff --git a/build/external/dpdk-18.08_patches/0003-ixgbe-wait-longer-for-link-after-fiber-MAC-setup.patch b/build/external/dpdk-18.08_patches/0003-ixgbe-wait-longer-for-link-after-fiber-MAC-setup.patch new file mode 100644 index 00000000000..93d1601c677 --- /dev/null +++ b/build/external/dpdk-18.08_patches/0003-ixgbe-wait-longer-for-link-after-fiber-MAC-setup.patch @@ -0,0 +1,39 @@ +From ba9b381c532fe57c726752b7db0ab45ab7726c90 Mon Sep 17 00:00:00 2001 +From: Matthew Smith <mgsmith@netgate.com> +Date: Fri, 13 Jul 2018 16:35:57 -0500 +Subject: [PATCH] ixgbe: wait longer for link after fiber MAC setup + +After setting up the link on a fiber port, the maximum wait time for +the link to come up is 500 ms in ixgbe_setup_mac_link_multispeed_fiber(). +On an x550 SFP+ port, this is often not sufficiently long for the link +to come up. This can result in never being able to retrieve accurate +link status for the port using rte_eth_link_get_nowait(). + +Increase the maximum wait time in ixgbe_setup_mac_link_multispeed_fiber() +to 1 s. + +Bugzilla ID: 69 +Fixes: f3430431abaf ("ixgbe/base: add SFP+ dual-speed support") +Cc: stable@dpdk.org + +Signed-off-by: Matthew Smith <mgsmith@netgate.com> +--- + drivers/net/ixgbe/base/ixgbe_common.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ixgbe/base/ixgbe_common.c b/drivers/net/ixgbe/base/ixgbe_common.c +index e7e9256e5..2fb0a072c 100644 +--- a/drivers/net/ixgbe/base/ixgbe_common.c ++++ b/drivers/net/ixgbe/base/ixgbe_common.c +@@ -5296,7 +5296,7 @@ s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw, + * Section 73.10.2, we may have to wait up to 500ms if KR is + * attempted. 82599 uses the same timing for 10g SFI. + */ +- for (i = 0; i < 5; i++) { ++ for (i = 0; i < 10; i++) { + /* Wait for the link partner to also set speed */ + msec_delay(100); + +-- +2.15.2 (Apple Git-101.1) + diff --git a/build/external/rpm/vpp-ext-deps.spec b/build/external/rpm/vpp-ext-deps.spec new file mode 100644 index 00000000000..c79ae1205bc --- /dev/null +++ b/build/external/rpm/vpp-ext-deps.spec @@ -0,0 +1,18 @@ +%define _install_dir /opt/vpp/external/%(uname -m) +%define _make_args -C ../.. DPDK_BUILD_DIR=%{_topdir}/tmp DPDK_INSTALL_DIR=%{buildroot}/%{_install_dir} + +Name: vpp-ext-deps +Version: %{_version} +Release: %{_release} +Summary: VPP development package with external dependencies +License: BSD + +%description +VPP development package with external dependencies + +%install +make %{_make_args} config +make %{_make_args} install + +%files +%{_install_dir} |